kis_visual_color_selector.h 14.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
/*
 * Copyright (C) Wolthera van Hovell tot Westerflier <griffinvalley@gmail.com>, (C) 2016
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
#ifndef KISVISUALCOLORSELECTOR_H
#define KISVISUALCOLORSELECTOR_H

#include <QWidget>
#include <QScopedPointer>
#include <QPixmap>
#include <QRegion>
#include <QMouseEvent>

#include <KoColor.h>
#include <KoColorSpace.h>
29 30
#include "KoColorDisplayRendererInterface.h"

31 32 33 34 35 36 37 38 39 40 41 42

#include "kritaui_export.h"

/**
 * @brief The KisVisualColorSelector class
 * this gives a color selector box that draws gradients and everything.
 * Unlike other color selectors, this one draws the full gamut of the given colorspace.
 */
class KRITAUI_EXPORT KisVisualColorSelector : public QWidget
{
    Q_OBJECT
public:
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
    //Copied directly from the advanced color selector:
    enum Type {Ring, Square, Wheel, Triangle, Slider};
    enum Parameters {H, hsvS, V, hslS, L, SL, SV, SV2, hsvSH, hslSH, VH, LH, SI, SY, hsiSH, hsySH, I, Y, IH, YH, hsiS, hsyS};
    struct Configuration {
        Type mainType;
        Type subType;
        Parameters mainTypeParameter;
        Parameters subTypeParameter;
        Configuration(Type mainT = Triangle,
                              Type subT = Ring,
                              Parameters mainTP = SL,
                              Parameters subTP = H)
                                  : mainType(mainT),
                                  subType(subT),
                                  mainTypeParameter(mainTP),
                                  subTypeParameter(subTP)
        {}
        Configuration(QString string)
        {
            readString(string);
        }

        QString toString() const
        {
            return QString("%1|%2|%3|%4").arg(mainType).arg(subType).arg(mainTypeParameter).arg(subTypeParameter);
        }
        void readString(QString string)
        {
            QStringList strili = string.split('|');
            if(strili.length()!=4) return;

            int imt=strili.at(0).toInt();
            int ist=strili.at(1).toInt();
            int imtp=strili.at(2).toInt();
            int istp=strili.at(3).toInt();

            if(imt>Slider || ist>Slider || imtp>hsyS || istp>hsyS)//this was LH before
                return;

            mainType = Type(imt);
            subType = Type(ist);
            mainTypeParameter = Parameters(imtp);
            subTypeParameter = Parameters(istp);
        }
        static Configuration fromString(QString string)
        {
            Configuration ret;
            ret.readString(string);
            return ret;
        }
    };

95 96 97 98 99 100 101 102 103 104
    explicit KisVisualColorSelector(QWidget *parent = 0);
    ~KisVisualColorSelector();

Q_SIGNALS:
    void sigNewColor(KoColor c);

public Q_SLOTS:

    void slotSetColor(KoColor c);
    void slotsetColorSpace(const KoColorSpace *cs);
105
    void slotRebuildSelectors();
106
    void setDisplayRenderer (const KoColorDisplayRendererInterface *displayRenderer);
107 108
private Q_SLOTS:
    void updateFromWidgets(KoColor c);
109
    void HSXwrangler();
110 111
protected:
    void leaveEvent(QEvent *);
112
    void resizeEvent(QResizeEvent *);
113 114 115 116 117 118 119 120 121 122 123
private:
    struct Private;
    const QScopedPointer<Private> m_d;

    void updateSelectorElements();
    void drawGradients();

};

//kis_visual_color_selector_shape

124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
/**
 * @brief The KisVisualColorSelectorShape class
 * A 2d widget can represent at maximum 2 coordinates.
 * So first decide howmany coordinates you need. (onedimensional, or twodimensional)
 * Then the model, (Channel, HSV, HSL, HSI, YUV). Channel is the raw color channels.
 * When it finds a non-implemented feature it'll return to Channel.
 * Then, select the channels you wish to be affected. This uses the model, so for cmyk
 * the channel is c=0, m=1, y=2, k=3, but for hsv, hue=0, sat=1, and val=2
 * These can also be set with 'slotsetactive channels'.
 * Then finally, connect the displayrenderer, you can also do this with 'setdisplayrenderer'
 *
 * Either way, this class is made to be subclassed, with a few virtuals so that the geometry
 * can be calculated properly.
 */

139 140 141 142 143 144 145
class KisVisualColorSelectorShape : public QWidget
{
    Q_OBJECT
public:
    /**
     * @brief The Dimensions enum
     * Wether or not the shape is single or two dimensional.
146
     **/
147 148 149 150 151 152
    enum Dimensions{onedimensional, twodimensional};
    enum ColorModel{Channel, HSV, HSL, HSI, HSY, YUV};
    explicit KisVisualColorSelectorShape(QWidget *parent,
                                         KisVisualColorSelectorShape::Dimensions dimension,
                                         KisVisualColorSelectorShape::ColorModel model,
                                         const KoColorSpace *cs,
153
                                         int channel1, int channel2,
154
                                         const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance());
155 156
    ~KisVisualColorSelectorShape();

157 158 159 160
    /**
     * @brief getCursorPosition
     * @return current cursor position in shape-coordinates.
     */
161
    QPointF getCursorPosition();
162 163 164 165
    /**
     * @brief getDimensions
     * @return whether this is a single or twodimensional widget.
     */
166
    Dimensions getDimensions();
167 168 169 170
    /**
     * @brief getColorModel
     * @return the model of this widget.
     */
171
    ColorModel getColorModel();
172 173 174 175 176 177
    /**
     * @brief getPixmap
     * @return the pixmap of the gradient, for drawing on with a subclass.
     * the pixmap will not change unless 'm_d->setPixmap=true' which is toggled by
     * refresh and update functions.
     */
178
    QImage getImageMap();
179 180 181 182 183
    /**
     * @brief setFullImage
     * Set the full widget image to be painted.
     * @param full this should be the full image.
     */
184
    void setFullImage(QImage full);
185 186 187 188
    /**
     * @brief getCurrentColor
     * @return the current kocolor
     */
189
    KoColor getCurrentColor();
190 191 192 193 194
    /**
     * @brief setDisplayRenderer
     * disconnect the old display renderer if needed and connect the new one.
     * @param displayRenderer
     */
195
    void setDisplayRenderer (const KoColorDisplayRendererInterface *displayRenderer);
196 197 198 199 200
    /**
     * @brief getColorFromConverter
     * @param c a koColor.
     * @return get the qcolor from the given kocolorusing this widget's display renderer.
     */
201
    QColor getColorFromConverter(KoColor c);
202 203 204 205 206 207 208 209 210

    /**
     * @brief getSpaceForSquare
     * @param geom the full widget rectangle
     * @return rectangle with enough space for second widget
     */
    virtual QRect getSpaceForSquare(QRect geom) = 0;
    virtual QRect getSpaceForCircle(QRect geom) = 0;
    virtual QRect getSpaceForTriangle(QRect geom) = 0;
211

212 213 214 215
    /**
     * @brief forceImageUpdate
     * force the image to recache.
     */
216
    void forceImageUpdate();
217 218 219 220 221 222

    /**
     * @brief setBorderWidth
     * set the border of the single dimensional selector.
     * @param width
     */
223
    virtual void setBorderWidth(int width) = 0;
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247

    /**
     * @brief getChannels
     * get used channels
     * @return
     */
    QVector <int> getChannels();

    /**
     * @brief setHSX
     * This is for the cursor not to change when selecting
     * black, white, and desaturated values. Will not change the non-native values.
     * @param hsx the hsx value.
     */
    void setHSX(QVector <qreal> hsx);
    /**
     * @brief getHSX sets the sat and hue so they won't
     * switch around much.
     * @param hsx the hsx values.
     * @return returns hsx, corrected.
     */
    QVector <qreal> getHSX(QVector <qreal> hsx, bool wrangler= false);


248 249
Q_SIGNALS:
    void sigNewColor(KoColor col);
250
    void sigHSXchange();
251 252

public Q_SLOTS:
253 254
    /**
     * @brief setColor
255
     * Set this widget's current color and change the cursor position.
256 257
     * @param c
     */
258
    void setColor(KoColor c);
259 260 261 262 263 264
    /**
     * @brief setColorFromSibling
     * set this widget's current color, but don't change the cursor position,
     * instead sent out a signal of the new color.
     * @param c
     */
265
    void setColorFromSibling(KoColor c);
266 267 268 269 270 271
    /**
     * @brief slotSetActiveChannels
     * Change the active channels if necessary.
     * @param channel1 used by single and twodimensional widgets.
     * @param channel2 only used by twodimensional widgets.
     */
272
    void slotSetActiveChannels(int channel1, int channel2);
273 274 275 276
    /**
     * @brief updateFromChangedDisplayRenderer
     * for updating from the display renderer... not sure why this one is public.
     */
277
    void updateFromChangedDisplayRenderer();
278 279
protected:
    void mousePressEvent(QMouseEvent *e);
280 281
    void mouseMoveEvent(QMouseEvent *e);
    void mouseReleaseEvent(QMouseEvent *e);
282 283 284 285 286 287 288 289 290 291 292 293 294
    void paintEvent(QPaintEvent*);
private:
    struct Private;
    const QScopedPointer<Private> m_d;

    /**
     * @brief convertShapeCoordinateToWidgetCoordinate
     * @return take the position in the shape and convert it to screen coordinates.
     */
    virtual QPointF convertShapeCoordinateToWidgetCoordinate(QPointF) = 0;

    /**
     * @brief convertWidgetCoordinateToShapeCoordinate
295
     * Convert a coordinate in the widget's height/width to a shape coordinate.
296 297 298 299
     * @param coordinate the position your wish to have the shape coordinates of.
     */
    virtual QPointF convertWidgetCoordinateToShapeCoordinate(QPoint coordinate) = 0;

300 301 302 303 304 305
    /**
     * @brief updateCursor
     * Update the cursor position.
     */
    void updateCursor();

306
    QPointF convertKoColorToShapeCoordinate(KoColor c);
307
    KoColor convertShapeCoordinateToKoColor(QPointF coordinates, bool cursor=false);
308 309 310 311 312 313 314

    /**
     * @brief getPixmap
     * @return the pixmap of this shape.
     */
    virtual QRegion getMaskMap() = 0;
    virtual void drawCursor() = 0;
315 316 317

    QVector <float> convertvectorqrealTofloat(QVector<qreal> real);
    QVector <qreal> convertvectorfloatToqreal(QVector <float> vloat);
318 319 320 321 322 323
};

class KisVisualRectangleSelectorShape : public KisVisualColorSelectorShape
{
    Q_OBJECT
public:
Wolthera van Hövell's avatar
Wolthera van Hövell committed
324
    enum singelDTypes{vertical, horizontal, border, borderMirrored};
325 326 327 328 329
    explicit KisVisualRectangleSelectorShape(QWidget *parent,
                                         Dimensions dimension,
                                         ColorModel model,
                                         const KoColorSpace *cs,
                                         int channel1, int channel2,
330
                                         const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance(), int width=20,
331 332
                                         KisVisualRectangleSelectorShape::singelDTypes d = KisVisualRectangleSelectorShape::vertical
                                         );
333 334
    ~KisVisualRectangleSelectorShape();

335
    void setBorderWidth(int width);
336

337 338 339 340 341 342 343 344
    /**
     * @brief getSpaceForSquare
     * @param geom the full widget rectangle
     * @return rectangle with enough space for second widget
     */
    virtual QRect getSpaceForSquare(QRect geom);
    virtual QRect getSpaceForCircle(QRect geom);
    virtual QRect getSpaceForTriangle(QRect geom);
345 346
protected:
    void resizeEvent(QResizeEvent *);
347 348 349 350 351
private:
    virtual QPointF convertShapeCoordinateToWidgetCoordinate(QPointF coordinate);
    virtual QPointF convertWidgetCoordinateToShapeCoordinate(QPoint coordinate);

    singelDTypes m_type;
352
    int m_barWidth;
353 354
    virtual QRegion getMaskMap();
    virtual void drawCursor();
355 356
};

357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
class KisVisualEllipticalSelectorShape : public KisVisualColorSelectorShape
{
    Q_OBJECT
public:
    enum singelDTypes{border, borderMirrored};
    explicit KisVisualEllipticalSelectorShape(QWidget *parent,
                                         Dimensions dimension,
                                         ColorModel model,
                                         const KoColorSpace *cs,
                                         int channel1, int channel2,
                                         const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance(), int borwidth=20,
                                         KisVisualEllipticalSelectorShape::singelDTypes d = KisVisualEllipticalSelectorShape::border
                                         );
    ~KisVisualEllipticalSelectorShape();

372
    void setBorderWidth(int width);
373

374 375 376 377 378 379 380 381
    /**
     * @brief getSpaceForSquare
     * @param geom the full widget rectangle
     * @return rectangle with enough space for second widget
     */
    virtual QRect getSpaceForSquare(QRect geom);
    virtual QRect getSpaceForCircle(QRect geom);
    virtual QRect getSpaceForTriangle(QRect geom);
382 383
protected:
    void resizeEvent(QResizeEvent *);
384 385 386 387
private:
    virtual QPointF convertShapeCoordinateToWidgetCoordinate(QPointF coordinate);
    virtual QPointF convertWidgetCoordinateToShapeCoordinate(QPoint coordinate);

388

389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
    singelDTypes m_type;
    int m_barWidth;
    virtual QRegion getMaskMap();
    virtual void drawCursor();
    QSize sizeHint() const;
};

class KisVisualTriangleSelectorShape : public KisVisualColorSelectorShape
{
    Q_OBJECT
public:
    enum singelDTypes{border, borderMirrored};
    explicit KisVisualTriangleSelectorShape(QWidget *parent,
                                         Dimensions dimension,
                                         ColorModel model,
                                         const KoColorSpace *cs,
                                         int channel1, int channel2,
                                         const KoColorDisplayRendererInterface *displayRenderer = KoDumbColorDisplayRenderer::instance(),
                                         int borwidth=20
                                         );
    ~KisVisualTriangleSelectorShape();

411
    void setBorderWidth(int width);
412
    void setTriangle();
413 414 415 416 417 418 419 420 421

    /**
     * @brief getSpaceForSquare
     * @param geom the full widget rectangle
     * @return rectangle with enough space for second widget
     */
    virtual QRect getSpaceForSquare(QRect geom);
    virtual QRect getSpaceForCircle(QRect geom);
    virtual QRect getSpaceForTriangle(QRect geom);
422 423
protected:
    void resizeEvent(QResizeEvent *);
424 425 426 427 428 429 430
private:
    virtual QPointF convertShapeCoordinateToWidgetCoordinate(QPointF coordinate);
    virtual QPointF convertWidgetCoordinateToShapeCoordinate(QPoint coordinate);

    singelDTypes m_type;
    int m_barWidth;
    QPolygon m_triangle;
431 432
    QPointF m_center;
    qreal m_radius;
433 434 435
    virtual QRegion getMaskMap();
    virtual void drawCursor();
};
436
#endif // KISVISUALCOLORSELECTOR_H