diff options
Diffstat (limited to 'kolourpaint/widgets')
27 files changed, 5190 insertions, 0 deletions
diff --git a/kolourpaint/widgets/Makefile.am b/kolourpaint/widgets/Makefile.am new file mode 100644 index 00000000..f6501fac --- /dev/null +++ b/kolourpaint/widgets/Makefile.am @@ -0,0 +1,21 @@ +INCLUDES = -I$(srcdir)/.. -I$(srcdir)/../cursors -I$(srcdir)/../interfaces \ + -I$(srcdir)/../pixmapfx \ + -I$(srcdir)/../tools \ + -I$(srcdir)/../views \ + -I$(srcdir)/../widgets $(all_includes) + +noinst_LTLIBRARIES = libkolourpaintwidgets.la +libkolourpaintwidgets_la_SOURCES = kpcolorsimilaritycube.cpp \ + kpcolorsimilaritydialog.cpp \ + kpcolortoolbar.cpp \ + kpresizesignallinglabel.cpp \ + kpsqueezedtextlabel.cpp \ + kptooltoolbar.cpp \ + kptoolwidgetbase.cpp kptoolwidgetbrush.cpp \ + kptoolwidgeterasersize.cpp kptoolwidgetfillstyle.cpp \ + kptoolwidgetlinewidth.cpp \ + kptoolwidgetopaqueortransparent.cpp \ + kptoolwidgetspraycansize.cpp + +METASOURCES = AUTO + diff --git a/kolourpaint/widgets/kpcolorsimilaritycube.cpp b/kolourpaint/widgets/kpcolorsimilaritycube.cpp new file mode 100644 index 00000000..9fe3f29b --- /dev/null +++ b/kolourpaint/widgets/kpcolorsimilaritycube.cpp @@ -0,0 +1,348 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define DEBUG_KP_COLOR_SIMILARITY_CUBE 0 + + +#include <kpcolorsimilaritycube.h> + +#include <math.h> + +#include <qpainter.h> +#include <qpixmap.h> +#include <qwhatsthis.h> + +#include <kdebug.h> +#include <klocale.h> + +#include <kpcolor.h> +#include <kpcolorsimilaritydialog.h> +#include <kpdefs.h> + + +const double kpColorSimilarityCube::colorCubeDiagonalDistance = + sqrt (255 * 255 * 3); + +kpColorSimilarityCube::kpColorSimilarityCube (int look, + kpMainWindow *mainWindow, + QWidget *parent, + const char *name) + : QFrame (parent, name, Qt::WNoAutoErase/*no flicker*/), + m_mainWindow (mainWindow), + m_colorSimilarity (-1) +{ + if (look & Depressed) + setFrameStyle (QFrame::Panel | QFrame::Sunken); + + setColorSimilarity (0); + + + // Don't cause the translators grief by appending strings + // - duplicate text with 2 cases + + if (look & DoubleClickInstructions) + { + QWhatsThis::add (this, + i18n ("<qt><p><b>Color Similarity</b> is how close " + "colors must be in the RGB Color Cube " + "to be considered the same.</p>" + + "<p>If you set it to something " + "other than <b>Exact</b>, " + "you can work more effectively with dithered " + "images and photos.</p>" + + "<p>This feature applies to transparent selections, as well as " + "the Flood Fill, Color Eraser and Autocrop " + "tools.</p>" + + // sync: different to else case + "<p>To configure it, double click on the cube.</p>" + + "</qt>")); + } + else + { + QWhatsThis::add (this, + i18n ("<qt><p><b>Color Similarity</b> is how close " + "colors must be in the RGB Color Cube " + "to be considered the same.</p>" + + "<p>If you set it to something " + "other than <b>Exact</b>, " + "you can work more effectively with dithered " + "images and photos.</p>" + + "<p>This feature applies to transparent selections, as well as " + "the Flood Fill, Color Eraser and Autocrop " + "tools.</p>" + + "</qt>")); + } +} + +kpColorSimilarityCube::~kpColorSimilarityCube () +{ +} + + +// public +double kpColorSimilarityCube::colorSimilarity () const +{ + return m_colorSimilarity; +} + +// public +void kpColorSimilarityCube::setColorSimilarity (double similarity) +{ +#if DEBUG_KP_COLOR_SIMILARITY_CUBE + kdDebug () << "kpColorSimilarityCube::setColorSimilarity(" << similarity << ")" << endl; +#endif + + if (m_colorSimilarity == similarity) + return; + + if (similarity < 0) + similarity = 0; + else if (similarity > kpColorSimilarityDialog::maximumColorSimilarity) + similarity = kpColorSimilarityDialog::maximumColorSimilarity; + + m_colorSimilarity = similarity; + + repaint (false/*no erase*/); +} + + +// protected virtual [base QWidget] +QSize kpColorSimilarityCube::sizeHint () const +{ + return QSize (52, 52); +} + + +// protected +QColor kpColorSimilarityCube::color (int redOrGreenOrBlue, + int baseBrightness, + int similarityDirection) const +{ + int brightness = int (baseBrightness + + similarityDirection * + .5 * m_colorSimilarity * kpColorSimilarityCube::colorCubeDiagonalDistance); + + if (brightness < 0) + brightness = 0; + else if (brightness > 255) + brightness = 255; + + switch (redOrGreenOrBlue) + { + default: + case 0: return QColor (brightness, 0, 0); + case 1: return QColor (0, brightness, 0); + case 2: return QColor (0, 0, brightness); + } +} + +static QPoint pointBetween (const QPoint &p, const QPoint &q) +{ + return QPoint ((p.x () + q.x ()) / 2, (p.y () + q.y ()) / 2); +} + +static void drawQuadrant (QPainter *p, + const QColor &col, + const QPoint &p1, const QPoint &p2, const QPoint &p3, + const QPoint pointNotOnOutline) +{ + p->save (); + + + QPointArray points (4); + points [0] = p1; + points [1] = p2; + points [2] = p3; + points [3] = pointNotOnOutline; + + p->setPen (col); + p->setBrush (col); + p->drawPolygon (points); + + + points.resize (3); + + p->setPen (Qt::black); + p->setBrush (Qt::NoBrush); + p->drawPolyline (points); + + + p->restore (); +} + +// protected +void kpColorSimilarityCube::drawFace (QPainter *p, + int redOrGreenOrBlue, + const QPoint &tl, const QPoint &tr, + const QPoint &bl, const QPoint &br) +{ +#if DEBUG_KP_COLOR_SIMILARITY_CUBE + kdDebug () << "kpColorSimilarityCube(RorGorB=" << redOrGreenOrBlue + << ",tl=" << tl + << ",tr=" << tr + << ",bl=" << bl + << ",br=" << br + << ")" + << endl; +#endif + + // tl --- tm --- tr + // | | | + // | | | + // ml --- mm --- mr + // | | | + // | | | + // bl --- bm --- br + + const QPoint tm (::pointBetween (tl, tr)); + const QPoint bm (::pointBetween (bl, br)); + + const QPoint ml (::pointBetween (tl, bl)); + const QPoint mr (::pointBetween (tr, br)); + const QPoint mm (::pointBetween (ml, mr)); + + + const int baseBrightness = QMAX (127, + 255 - int (kpColorSimilarityDialog::maximumColorSimilarity * + kpColorSimilarityCube::colorCubeDiagonalDistance / 2)); + QColor colors [2] = + { + color (redOrGreenOrBlue, baseBrightness, -1), + color (redOrGreenOrBlue, baseBrightness, +1) + }; + + if (!isEnabled ()) + { + #if DEBUG_KP_COLOR_SIMILARITY_CUBE + kdDebug () << "\tnot enabled - making us grey" << endl; + #endif + colors [0] = colorGroup ().background (); + colors [1] = colorGroup ().background (); + } + +#if DEBUG_KP_COLOR_SIMILARITY_CUBE + kdDebug () << "\tmaxColorSimilarity=" << kpColorSimilarityDialog::maximumColorSimilarity + << " colorCubeDiagDist=" << kpColorSimilarityCube::colorCubeDiagonalDistance + << endl + << "\tbaseBrightness=" << baseBrightness + << " color[0]=" << ((colors [0].rgb () & RGB_MASK) >> ((2 - redOrGreenOrBlue) * 8)) + << " color[1]=" << ((colors [1].rgb () & RGB_MASK) >> ((2 - redOrGreenOrBlue) * 8)) + << endl; +#endif + + + ::drawQuadrant (p, colors [0], tm, tl, ml, mm); + ::drawQuadrant (p, colors [1], tm, tr, mr, mm); + ::drawQuadrant (p, colors [1], ml, bl, bm, mm); + ::drawQuadrant (p, colors [0], bm, br, mr, mm); +} + +// protected virtual [base QFrame] +void kpColorSimilarityCube::drawContents (QPainter *p) +{ + QRect cr (contentsRect ()); + + QPixmap backBuffer (cr.width (), cr.height ()); + backBuffer.fill (colorGroup ().background ()); + + QPainter backBufferPainter (&backBuffer); + + int cubeRectSize = QMIN (cr.width () * 6 / 8, cr.height () * 6 / 8); + int dx = (cr.width () - cubeRectSize) / 2, + dy = (cr.height () - cubeRectSize) / 2; + backBufferPainter.translate (dx, dy); + + // + // P------- Q --- --- + // / / | | | + // /A / | side | + // R-------S T --- cubeRectSize + // | | / / | + // S | | / side | + // U-------V --- --- + // |-------| + // side + // |-----------| + // cubeRectSize + // + // + + const double angle = KP_DEGREES_TO_RADIANS (45); + // S + S sin A = cubeRectSize + // (1 + sin A) x S = cubeRectSize + const double side = double (cubeRectSize) / (1 + sin (angle)); + + + const QPoint pointP ((int) (side * cos (angle)), 0); + const QPoint pointQ ((int) (side * cos (angle) + side), 0); + const QPoint pointR (0, (int) (side * sin (angle))); + const QPoint pointS ((int) (side), (int) (side * sin (angle))); + const QPoint pointU (0, (int) (side * sin (angle) + side)); + const QPoint pointT ((int) (side + side * cos (angle)), (int) (side)); + const QPoint pointV ((int) (side), (int) (side * sin (angle) + side)); + + + // Top Face + drawFace (&backBufferPainter, + 0/*red*/, + pointP, pointQ, + pointR, pointS); + + + // Bottom Face + drawFace (&backBufferPainter, + 1/*green*/, + pointR, pointS, + pointU, pointV); + + + // Right Face + drawFace (&backBufferPainter, + 2/*blue*/, + pointS, pointQ, + pointV, pointT); + + +#if 0 + backBufferPainter.save (); + backBufferPainter.setPen (Qt::cyan); + backBufferPainter.drawRect (0, 0, cubeRectSize, cubeRectSize); + backBufferPainter.restore (); +#endif + + + backBufferPainter.end (); + + p->drawPixmap (cr, backBuffer); +} diff --git a/kolourpaint/widgets/kpcolorsimilaritycube.h b/kolourpaint/widgets/kpcolorsimilaritycube.h new file mode 100644 index 00000000..358d4b3a --- /dev/null +++ b/kolourpaint/widgets/kpcolorsimilaritycube.h @@ -0,0 +1,72 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef __kp_color_similarity_cube_h__ +#define __kp_color_similarity_cube_h__ + +#include <qframe.h> + +class kpColor; +class kpMainWindow; + +class kpColorSimilarityCube : public QFrame +{ +public: + enum Look + { + Plain = 0, + Depressed = 1, + DoubleClickInstructions = 2 + }; + + kpColorSimilarityCube (int look, + kpMainWindow *mainWindow, + QWidget *parent, + const char *name = 0); + virtual ~kpColorSimilarityCube (); + + static const double colorCubeDiagonalDistance; + + double colorSimilarity () const; + void setColorSimilarity (double similarity); + + virtual QSize sizeHint () const; + +protected: + QColor color (int redOrGreenOrBlue, int baseBrightness, int similarityDirection) const; + void drawFace (QPainter *p, + int redOrGreenOrBlue, + const QPoint &tl, const QPoint &tr, + const QPoint &bl, const QPoint &br); + virtual void drawContents (QPainter *p); + + kpMainWindow *m_mainWindow; + double m_colorSimilarity; +}; + +#endif // __kp_color_similarity_cube_h__ diff --git a/kolourpaint/widgets/kpcolorsimilaritydialog.cpp b/kolourpaint/widgets/kpcolorsimilaritydialog.cpp new file mode 100644 index 00000000..d2766568 --- /dev/null +++ b/kolourpaint/widgets/kpcolorsimilaritydialog.cpp @@ -0,0 +1,123 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include <kpcolorsimilaritydialog.h> + +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> + +#include <klocale.h> +#include <knuminput.h> + +#include <kpcolorsimilaritycube.h> + + +// public static +const double kpColorSimilarityDialog::maximumColorSimilarity = .30; + + +kpColorSimilarityDialog::kpColorSimilarityDialog (kpMainWindow *mainWindow, + QWidget *parent, + const char *name) + : KDialogBase (parent, name, true/*modal*/, + i18n ("Color Similarity"), + KDialogBase::Ok | KDialogBase::Cancel), + m_mainWindow (mainWindow) +{ + QWidget *baseWidget = new QWidget (this); + setMainWidget (baseWidget); + + + QGroupBox *cubeGroupBox = new QGroupBox (i18n ("Preview"), baseWidget); + + m_colorSimilarityCube = new kpColorSimilarityCube (kpColorSimilarityCube::Plain, + mainWindow, cubeGroupBox); + m_colorSimilarityCube->setMinimumSize (240, 180); + + QPushButton *updatePushButton = new QPushButton (i18n ("&Update"), cubeGroupBox); + + + QVBoxLayout *cubeLayout = new QVBoxLayout (cubeGroupBox, marginHint () * 2, spacingHint ()); + cubeLayout->addWidget (m_colorSimilarityCube, 1/*stretch*/); + cubeLayout->addWidget (updatePushButton, 0/*stretch*/, Qt::AlignHCenter); + + + connect (updatePushButton, SIGNAL (clicked ()), + this, SLOT (slotColorSimilarityValueChanged ())); + + + QGroupBox *inputGroupBox = new QGroupBox (i18n ("RGB Color Cube Distance"), baseWidget); + + m_colorSimilarityInput = new KIntNumInput (inputGroupBox); + m_colorSimilarityInput->setRange (0, int (kpColorSimilarityDialog::maximumColorSimilarity * 100 + .1/*don't floor below target int*/), + 5/*step*/, true/*slider*/); + m_colorSimilarityInput->setSuffix (i18n ("%")); + m_colorSimilarityInput->setSpecialValueText (i18n ("Exact Match")); + + + QVBoxLayout *inputLayout = new QVBoxLayout (inputGroupBox, marginHint () * 2, spacingHint ()); + inputLayout->addWidget (m_colorSimilarityInput); + + + connect (m_colorSimilarityInput, SIGNAL (valueChanged (int)), + this, SLOT (slotColorSimilarityValueChanged ())); + + + QVBoxLayout *baseLayout = new QVBoxLayout (baseWidget, 0/*margin*/, spacingHint () * 2); + baseLayout->addWidget (cubeGroupBox, 1/*stretch*/); + baseLayout->addWidget (inputGroupBox); +} + +kpColorSimilarityDialog::~kpColorSimilarityDialog () +{ +} + + +// public +double kpColorSimilarityDialog::colorSimilarity () const +{ + return m_colorSimilarityCube->colorSimilarity (); +} + +// public +void kpColorSimilarityDialog::setColorSimilarity (double similarity) +{ + m_colorSimilarityInput->setValue (qRound (similarity * 100)); +} + + +// private slot +void kpColorSimilarityDialog::slotColorSimilarityValueChanged () +{ + m_colorSimilarityCube->setColorSimilarity (double (m_colorSimilarityInput->value ()) / 100); +} + + +#include <kpcolorsimilaritydialog.moc> diff --git a/kolourpaint/widgets/kpcolorsimilaritydialog.h b/kolourpaint/widgets/kpcolorsimilaritydialog.h new file mode 100644 index 00000000..fd70ecd0 --- /dev/null +++ b/kolourpaint/widgets/kpcolorsimilaritydialog.h @@ -0,0 +1,62 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __kp_color_similarity_dialog_h__ +#define __kp_color_similarity_dialog_h__ + +#include <kdialogbase.h> + +class KIntNumInput; + +class kpColorSimilarityCube; +class kpMainWindow; + +class kpColorSimilarityDialog : public KDialogBase +{ +Q_OBJECT + +public: + kpColorSimilarityDialog (kpMainWindow *mainWindow, + QWidget *parent, + const char *name = 0); + virtual ~kpColorSimilarityDialog (); + + double colorSimilarity () const; + void setColorSimilarity (double similarity); + + static const double maximumColorSimilarity; + +private slots: + void slotColorSimilarityValueChanged (); + +private: + kpMainWindow *m_mainWindow; + kpColorSimilarityCube *m_colorSimilarityCube; + KIntNumInput *m_colorSimilarityInput; +}; + +#endif // __kp_color_similarity_dialog_h__ diff --git a/kolourpaint/widgets/kpcolortoolbar.cpp b/kolourpaint/widgets/kpcolortoolbar.cpp new file mode 100644 index 00000000..cba73b4f --- /dev/null +++ b/kolourpaint/widgets/kpcolortoolbar.cpp @@ -0,0 +1,1112 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define DEBUG_KP_COLOR_TOOL_BAR 0 + + +#include <kpcolortoolbar.h> + +#include <qbitmap.h> +#include <qdrawutil.h> +#include <qframe.h> +#include <qlayout.h> +#include <qpainter.h> +#include <qsize.h> +#include <qtooltip.h> +#include <qwidget.h> + +#include <kapplication.h> +#include <kcolordialog.h> +#include <kcolordrag.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kiconloader.h> +#include <klocale.h> + +#include <kpcolorsimilaritydialog.h> +#include <kpdefs.h> +#include <kpmainwindow.h> +#include <kppixmapfx.h> +#include <kptool.h> +#include <kpview.h> + + +/* + * kpDualColorButton + */ + +kpDualColorButton::kpDualColorButton (kpMainWindow *mainWindow, + QWidget *parent, const char *name) + : QFrame (parent, name, Qt::WNoAutoErase/*no flicker*/), + m_mainWindow (mainWindow), + m_backBuffer (0) +{ + setFrameStyle (QFrame::Panel | QFrame::Sunken); + + m_color [0] = kpColor (0, 0, 0); // black + m_color [1] = kpColor (255, 255, 255); // white + + setAcceptDrops (true); +} + +kpDualColorButton::~kpDualColorButton () +{ + delete m_backBuffer; m_backBuffer = 0; +} + + +kpColor kpDualColorButton::color (int which) const +{ + if (which < 0 || which > 1) + { + kdWarning () << "kpDualColorButton::color (" << which + << ") - out of range" << endl; + which = 0; + } + + return m_color [which]; +} + +kpColor kpDualColorButton::foregroundColor () const +{ + return color (0); +} + +kpColor kpDualColorButton::backgroundColor () const +{ + return color (1); +} + + +void kpDualColorButton::setColor (int which, const kpColor &color) +{ + if (which < 0 || which > 1) + { + kdWarning () << "kpDualColorButton::setColor (" << which + << ") - out of range" << endl; + which = 0; + } + + if (m_color [which] == color) + return; + + m_oldColor [which] = m_color [which]; + m_color [which] = color; + update (); + + if (which == 0) + emit foregroundColorChanged (color); + else + emit backgroundColorChanged (color); +} + +void kpDualColorButton::setForegroundColor (const kpColor &color) +{ + setColor (0, color); +} + +void kpDualColorButton::setBackgroundColor (const kpColor &color) +{ + setColor (1, color); +} + + +// public +kpColor kpDualColorButton::oldForegroundColor () const +{ + return m_oldColor [0]; +} + +// public +kpColor kpDualColorButton::oldBackgroundColor () const +{ + return m_oldColor [1]; +} + + +// public virtual [base QWidget] +QSize kpDualColorButton::sizeHint () const +{ + return QSize (52, 52); +} + + +// protected +QRect kpDualColorButton::swapPixmapRect () const +{ + QPixmap swapPixmap = UserIcon ("colorbutton_swap_16x16"); + + return QRect (contentsRect ().width () - swapPixmap.width (), + 0, + swapPixmap.width (), + swapPixmap.height ()); +} + +// protected +QRect kpDualColorButton::foregroundBackgroundRect () const +{ + QRect cr (contentsRect ()); + return QRect (cr.width () / 8, + cr.height () / 8, + cr.width () * 6 / 8, + cr.height () * 6 / 8); +} + +// protected +QRect kpDualColorButton::foregroundRect () const +{ + QRect fbr (foregroundBackgroundRect ()); + return QRect (fbr.x (), + fbr.y (), + fbr.width () * 3 / 4, + fbr.height () * 3 / 4); +} + +// protected +QRect kpDualColorButton::backgroundRect () const +{ + QRect fbr (foregroundBackgroundRect ()); + return QRect (fbr.x () + fbr.width () / 4, + fbr.y () + fbr.height () / 4, + fbr.width () * 3 / 4, + fbr.height () * 3 / 4); +} + + +// TODO: drag a colour from this widget + +// protected virtual [base QWidget] +void kpDualColorButton::dragMoveEvent (QDragMoveEvent *e) +{ + e->accept ((foregroundRect ().contains (e->pos ()) || + backgroundRect ().contains (e->pos ())) && + KColorDrag::canDecode (e)); +} + +// protected virtual [base QWidget] +void kpDualColorButton::dropEvent (QDropEvent *e) +{ + QColor col; + KColorDrag::decode (e, col/*ref*/); + + if (col.isValid ()) + { + if (foregroundRect ().contains (e->pos ())) + setForegroundColor (kpColor (col.rgb ())); + else if (backgroundRect ().contains (e->pos ())) + setBackgroundColor (kpColor (col.rgb ())); + } +} + + +// protected virtual [base QWidget] +void kpDualColorButton::mousePressEvent (QMouseEvent * /*e*/) +{ + // eat right-mouse click to prevent it from getting to the toolbar +} + +// protected virtual [base QWidget] +void kpDualColorButton::mouseDoubleClickEvent (QMouseEvent *e) +{ + int whichColor = -1; + + if (foregroundRect ().contains (e->pos ())) + whichColor = 0; + else if (backgroundRect ().contains (e->pos ())) + whichColor = 1; + + if (whichColor == 0 || whichColor == 1) + { + QColor col = Qt::black; + if (color (whichColor).isOpaque ()) + col = color (whichColor).toQColor (); + else + { + // TODO: If you double-click on a transparent color and press OK, you get + // black, instead of the color staying as transparent. + // + // We should modify or fork KColorDialog to allow us to fix this. + // + // It would be wrong to stop the user from double-clicking on a + // transparent color as that would make the UI inconsistent, compared + // to opaque colors. + } + + // TODO: parent + if (KColorDialog::getColor (col/*ref*/)) + setColor (whichColor, kpColor (col.rgb ())); + } +} + +// protected virtual [base QWidget] +void kpDualColorButton::mouseReleaseEvent (QMouseEvent *e) +{ + if (swapPixmapRect ().contains (e->pos ()) && + m_color [0] != m_color [1]) + { + #if DEBUG_KP_COLOR_TOOL_BAR && 1 + kdDebug () << "kpDualColorButton::mouseReleaseEvent() swap colors:" << endl; + #endif + m_oldColor [0] = m_color [0]; + m_oldColor [1] = m_color [1]; + + kpColor temp = m_color [0]; + m_color [0] = m_color [1]; + m_color [1] = temp; + + update (); + + emit colorsSwapped (m_color [0], m_color [1]); + emit foregroundColorChanged (m_color [0]); + emit backgroundColorChanged (m_color [1]); + } +} + + +// protected virtual [base QFrame] +void kpDualColorButton::drawContents (QPainter *p) +{ +#if DEBUG_KP_COLOR_TOOL_BAR && 1 + kdDebug () << "kpDualColorButton::draw() rect=" << rect () + << " contentsRect=" << contentsRect () + << endl; +#endif + + if (!m_backBuffer || + m_backBuffer->width () != contentsRect ().width () || + m_backBuffer->height () != contentsRect ().height ()) + { + delete m_backBuffer; + m_backBuffer = new QPixmap (contentsRect ().width (), contentsRect ().height ()); + } + + + QPainter backBufferPainter (m_backBuffer); + + if (isEnabled () && m_mainWindow) + { + kpView::drawTransparentBackground (&backBufferPainter, + m_backBuffer->width (), m_backBuffer->height (), + m_backBuffer->rect (), + true/*preview*/); + } + else + { + backBufferPainter.fillRect (m_backBuffer->rect (), + colorGroup ().color (QColorGroup::Background)); + } + + QPixmap swapPixmap = UserIcon ("colorbutton_swap_16x16"); + if (!isEnabled ()) + { + // swapPixmap has a mask after all + swapPixmap.fill (colorGroup ().color (QColorGroup::Dark)); + } + backBufferPainter.drawPixmap (swapPixmapRect ().topLeft (), swapPixmap); + + // foreground patch must be drawn after background patch + // as it overlaps on top of background patch + QRect bgRect = backgroundRect (); + QRect bgRectInside = QRect (bgRect.x () + 2, bgRect.y () + 2, + bgRect.width () - 4, bgRect.height () - 4); + if (isEnabled ()) + { + #if DEBUG_KP_COLOR_TOOL_BAR && 1 + kdDebug () << "\tbackgroundColor=" << (int *) m_color [1].toQRgb () + << endl; + #endif + if (m_color [1].isOpaque ()) + backBufferPainter.fillRect (bgRectInside, m_color [1].toQColor ()); + else + backBufferPainter.drawPixmap (bgRectInside, UserIcon ("color_transparent_26x26")); + } + else + backBufferPainter.fillRect (bgRectInside, colorGroup ().color (QColorGroup::Button)); + qDrawShadePanel (&backBufferPainter, bgRect, colorGroup (), + false/*not sunken*/, 2/*lineWidth*/, + 0/*never fill*/); + + QRect fgRect = foregroundRect (); + QRect fgRectInside = QRect (fgRect.x () + 2, fgRect.y () + 2, + fgRect.width () - 4, fgRect.height () - 4); + if (isEnabled ()) + { + #if DEBUG_KP_COLOR_TOOL_BAR && 1 + kdDebug () << "\tforegroundColor=" << (int *) m_color [0].toQRgb () + << endl; + #endif + if (m_color [0].isOpaque ()) + backBufferPainter.fillRect (fgRectInside, m_color [0].toQColor ()); + else + backBufferPainter.drawPixmap (fgRectInside, UserIcon ("color_transparent_26x26")); + } + else + backBufferPainter.fillRect (fgRectInside, colorGroup ().color (QColorGroup::Button)); + qDrawShadePanel (&backBufferPainter, fgRect, colorGroup (), + false/*not sunken*/, 2/*lineWidth*/, + 0/*never fill*/); + + backBufferPainter.end (); + + p->drawPixmap (contentsRect (), *m_backBuffer); +} + + +/* + * kpColorCells + */ + +static inline int roundUp2 (int val) +{ + return val % 2 ? val + 1 : val; +} + +static inline int btwn0_255 (int val) +{ + if (val < 0) + return 0; + else if (val > 255) + return 255; + else + return val; +} + +enum +{ + blendDark = 25, + blendNormal = 50, + blendLight = 75, + blendAdd = 100 +}; + +static QColor blend (const QColor &a, const QColor &b, int percent = blendNormal) +{ + return QColor (btwn0_255 (roundUp2 (a.red () + b.red ()) * percent / 100), + btwn0_255 (roundUp2 (a.green () + b.green ()) * percent / 100), + btwn0_255 (roundUp2 (a.blue () + b.blue ()) * percent / 100)); +} + +static QColor add (const QColor &a, const QColor &b) +{ + return blend (a, b, blendAdd); +} + + + + + +// +// make our own colors in case weird ones like "Qt::cyan" +// (turquoise) get changed by Qt +// + +// primary colors + B&W +static QColor kpRed; +static QColor kpGreen; +static QColor kpBlue; +static QColor kpBlack; +static QColor kpWhite; + +// intentionally _not_ an HSV darkener +static QColor dark (const QColor &color) +{ + return blend (color, kpBlack); +} + +// full-brightness colors +static QColor kpYellow; +static QColor kpPurple; +static QColor kpAqua; + +// mixed colors +static QColor kpGrey; +static QColor kpLightGrey; +static QColor kpOrange; + +// pastel colors +static QColor kpPink; +static QColor kpLightGreen; +static QColor kpLightBlue; +static QColor kpTan; + +static bool ownColorsInitialised = false; + +/* TODO: clean up this code!!! + * (probably when adding palette load/save) + */ +#define rows 2 +#define cols 11 +kpColorCells::kpColorCells (QWidget *parent, + Qt::Orientation o, + const char *name) + : KColorCells (parent, rows, cols), + m_mouseButton (-1) +{ + setName (name); + + setShading (false); // no 3D look + + // Trap KColorDrag so that kpMainWindow does not trap it. + // See our impl of dropEvent(). + setAcceptDrops (true); + setAcceptDrags (true); + + connect (this, SIGNAL (colorDoubleClicked (int)), + SLOT (slotColorDoubleClicked (int))); + + if (!ownColorsInitialised) + { + // Don't initialise globally when we probably don't have a colour + // allocation context. This way, the colours aren't sometimes + // invalid (e.g. at 8-bit). + + kpRed = QColor (255, 0, 0); + kpGreen = QColor (0, 255, 0); + kpBlue = QColor (0, 0, 255); + kpBlack = QColor (0, 0, 0); + kpWhite = QColor (255, 255, 255); + + kpYellow = add (kpRed, kpGreen); + kpPurple = add (kpRed, kpBlue); + kpAqua = add (kpGreen, kpBlue); + + kpGrey = blend (kpBlack, kpWhite); + kpLightGrey = blend (kpGrey, kpWhite); + kpOrange = blend (kpRed, kpYellow); + + kpPink = blend (kpRed, kpWhite); + kpLightGreen = blend (kpGreen, kpWhite); + kpLightBlue = blend (kpBlue, kpWhite); + kpTan = blend (kpYellow, kpWhite); + + ownColorsInitialised = true; + } + + setOrientation (o); +} + +kpColorCells::~kpColorCells () +{ +} + +Qt::Orientation kpColorCells::orientation () const +{ + return m_orientation; +} + +void kpColorCells::setOrientation (Qt::Orientation o) +{ + int c, r; + + if (o == Qt::Horizontal) + { + c = cols; + r = rows; + } + else + { + c = rows; + r = cols; + } + +#if DEBUG_KP_COLOR_TOOL_BAR + kdDebug () << "kpColorCells::setOrientation(): r=" << r << " c=" << c << endl; +#endif + + setNumRows (r); + setNumCols (c); + + setCellWidth (26); + setCellHeight (26); + + setFixedSize (numCols () * cellWidth () + frameWidth () * 2, + numRows () * cellHeight () + frameWidth () * 2); + +/* + kdDebug () << "\tlimits: array=" << sizeof (colors) / sizeof (colors [0]) + << " r*c=" << r * c << endl; + kdDebug () << "\tsizeof (colors)=" << sizeof (colors) + << " sizeof (colors [0])=" << sizeof (colors [0]) + << endl;*/ + QColor colors [] = + { + kpBlack, + kpGrey, + kpRed, + kpOrange, + kpYellow, + kpGreen, + kpAqua, + kpBlue, + kpPurple, + kpPink, + kpLightGreen, + + kpWhite, + kpLightGrey, + dark (kpRed), + dark (kpOrange)/*brown*/, + dark (kpYellow), + dark (kpGreen), + dark (kpAqua), + dark (kpBlue), + dark (kpPurple), + kpLightBlue, + kpTan + }; + + for (int i = 0; + /*i < int (sizeof (colors) / sizeof (colors [0])) &&*/ + i < r * c; + i++) + { + int y, x; + int pos; + + if (o == Qt::Horizontal) + { + y = i / cols; + x = i % cols; + pos = i; + } + else + { + y = i % cols; + x = i / cols; + // int x = rows - 1 - i / cols; + pos = y * rows + x; + } + + KColorCells::setColor (pos, colors [i]); + //QToolTip::add (this, cellGeometry (y, x), colors [i].name ()); + } + + m_orientation = o; +} + +// virtual protected [base KColorCells] +void kpColorCells::dropEvent (QDropEvent *e) +{ + // Eat event so that: + // + // 1. User doesn't clobber the palette (until we support reconfigurable + // palettes) + // 2. kpMainWindow::dropEvent() doesn't try to paste colour code as text + // (when the user slips and drags colour cell a little instead of clicking) + e->accept (); +} + +// virtual protected +void kpColorCells::paintCell (QPainter *painter, int row, int col) +{ + QColor oldColor; + int cellNo; + + if (!isEnabled ()) + { + cellNo = row * numCols () + col; + + // make all cells 3D (so that disabled palette doesn't look flat) + setShading (true); + + oldColor = KColorCells::color (cellNo); + KColorCells::colors [cellNo] = backgroundColor (); + } + + + // no focus rect as it doesn't make sense + // since 2 colors (foreground & background) can be selected + KColorCells::selected = -1; + KColorCells::paintCell (painter, row, col); + + + if (!isEnabled ()) + { + KColorCells::colors [cellNo] = oldColor; + setShading (false); + } +} + +// virtual protected +void kpColorCells::mouseReleaseEvent (QMouseEvent *e) +{ + m_mouseButton = -1; + + Qt::ButtonState button = e->button (); +#if DEBUG_KP_COLOR_TOOL_BAR + kdDebug () << "kpColorCells::mouseReleaseEvent(left=" + << (button & Qt::LeftButton) + << ",right=" + << (button & Qt::RightButton) + << ")" + << endl; +#endif + if (!((button & Qt::LeftButton) && (button & Qt::RightButton))) + { + if (button & Qt::LeftButton) + m_mouseButton = 0; + else if (button & Qt::RightButton) + m_mouseButton = 1; + } + + connect (this, SIGNAL (colorSelected (int)), this, SLOT (slotColorSelected (int))); + KColorCells::mouseReleaseEvent (e); + disconnect (this, SIGNAL (colorSelected (int)), this, SLOT (slotColorSelected (int))); + +#if DEBUG_KP_COLOR_TOOL_BAR + kdDebug () << "kpColorCells::mouseReleaseEvent() setting m_mouseButton back to -1" << endl; +#endif + m_mouseButton = -1; +} + +// protected virtual [base KColorCells] +void kpColorCells::resizeEvent (QResizeEvent *e) +{ + // KColorCells::resizeEvent() tries to adjust the cellWidth and cellHeight + // to the current dimensions but doesn't take into account + // frame{Width,Height}(). + // + // In any case, we already set the cell{Width,Height} and a fixed + // widget size and don't want any of it changed. Eat the resize event. + (void) e; +} + +// protected slot +void kpColorCells::slotColorSelected (int cell) +{ +#if DEBUG_KP_COLOR_TOOL_BAR + kdDebug () << "kpColorCells::slotColorSelected(cell=" << cell + << ") mouseButton = " << m_mouseButton << endl; +#endif + QColor c = KColorCells::color (cell); + + if (m_mouseButton == 0) + { + emit foregroundColorChanged (c); + emit foregroundColorChanged (kpColor (c.rgb ())); + } + else if (m_mouseButton == 1) + { + emit backgroundColorChanged (c); + emit backgroundColorChanged (kpColor (c.rgb ())); + } + + m_mouseButton = -1; // just in case +} + +// protected slot +void kpColorCells::slotColorDoubleClicked (int cell) +{ +#if DEBUG_KP_COLOR_TOOL_BAR + kdDebug () << "kpColorCells::slotColorDoubleClicked(cell=" + << cell << ")" << endl; +#endif + + QColor color = KColorCells::color (cell); + + // TODO: parent + if (KColorDialog::getColor (color/*ref*/)) + KColorCells::setColor (cell, color); +} + + +/* + * kpTransparentColorCell + */ + +kpTransparentColorCell::kpTransparentColorCell (QWidget *parent, const char *name) + : QFrame (parent, name) +{ +#if DEBUG_KP_COLOR_TOOL_BAR + kdDebug () << "kpTransparentColorCell::kpTransparentColorCell()" << endl; +#endif + + setFrameStyle (QFrame::Panel | QFrame::Sunken); +#if DEBUG_KP_COLOR_TOOL_BAR && 0 + kdDebug () << "\tdefault line width=" << lineWidth () + << " frame width=" << frameWidth () << endl; +#endif + //setLineWidth (2); +#if DEBUG_KP_COLOR_TOOL_BAR && 0 + kdDebug () << "\tline width=" << lineWidth () + << " frame width=" << frameWidth () << endl; +#endif + + m_pixmap = UserIcon ("color_transparent_26x26"); + + QToolTip::add (this, i18n ("Transparent")); +} + +kpTransparentColorCell::~kpTransparentColorCell () +{ +} + + +// public virtual [base QWidget] +QSize kpTransparentColorCell::sizeHint () const +{ + return QSize (m_pixmap.width () + frameWidth () * 2, + m_pixmap.height () + frameWidth () * 2); +} + +// protected virtual [base QWidget] +void kpTransparentColorCell::mousePressEvent (QMouseEvent * /*e*/) +{ + // eat right-mouse click to prevent it from getting to the toolbar +} + +// protected virtual [base QWidget] +void kpTransparentColorCell::mouseReleaseEvent (QMouseEvent *e) +{ + if (rect ().contains (e->pos ())) + { + if (e->button () == Qt::LeftButton) + { + emit transparentColorSelected (0); + emit foregroundColorChanged (kpColor::transparent); + } + else if (e->button () == Qt::RightButton) + { + emit transparentColorSelected (1); + emit backgroundColorChanged (kpColor::transparent); + } + } +} + +// protected virtual [base QFrame] +void kpTransparentColorCell::drawContents (QPainter *p) +{ + QFrame::drawContents (p); + if (isEnabled ()) + { + #if DEBUG_KP_COLOR_TOOL_BAR + kdDebug () << "kpTransparentColorCell::drawContents() contentsRect=" + << contentsRect () + << endl; + #endif + p->drawPixmap (contentsRect (), m_pixmap); + } +} + + +/* + * kpColorPalette + */ + +kpColorPalette::kpColorPalette (QWidget *parent, + Qt::Orientation o, + const char *name) + : QWidget (parent, name), + m_boxLayout (0) +{ +#if DEBUG_KP_COLOR_TOOL_BAR + kdDebug () << "kpColorPalette::kpColorPalette()" << endl; +#endif + + m_transparentColorCell = new kpTransparentColorCell (this); + m_transparentColorCell->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed); + connect (m_transparentColorCell, SIGNAL (foregroundColorChanged (const kpColor &)), + this, SIGNAL (foregroundColorChanged (const kpColor &))); + connect (m_transparentColorCell, SIGNAL (backgroundColorChanged (const kpColor &)), + this, SIGNAL (backgroundColorChanged (const kpColor &))); + + m_colorCells = new kpColorCells (this); + connect (m_colorCells, SIGNAL (foregroundColorChanged (const kpColor &)), + this, SIGNAL (foregroundColorChanged (const kpColor &))); + connect (m_colorCells, SIGNAL (backgroundColorChanged (const kpColor &)), + this, SIGNAL (backgroundColorChanged (const kpColor &))); + + setOrientation (o); +} + +kpColorPalette::~kpColorPalette () +{ +} + +// public +Qt::Orientation kpColorPalette::orientation () const +{ + return m_orientation; +} + +void kpColorPalette::setOrientation (Qt::Orientation o) +{ + m_colorCells->setOrientation (o); + + delete m_boxLayout; + + if (o == Qt::Horizontal) + { + m_boxLayout = new QBoxLayout (this, QBoxLayout::LeftToRight, 0/*margin*/, 5/*spacing*/); + m_boxLayout->addWidget (m_transparentColorCell, 0/*stretch*/, Qt::AlignVCenter); + m_boxLayout->addWidget (m_colorCells); + } + else + { + m_boxLayout = new QBoxLayout (this, QBoxLayout::TopToBottom, 0/*margin*/, 5/*spacing*/); + m_boxLayout->addWidget (m_transparentColorCell, 0/*stretch*/, Qt::AlignHCenter); + m_boxLayout->addWidget (m_colorCells); + } + + m_orientation = o; +} + + +/* + * kpColorSimilarityToolBarItem + */ + +kpColorSimilarityToolBarItem::kpColorSimilarityToolBarItem (kpMainWindow *mainWindow, + QWidget *parent, + const char *name) + : kpColorSimilarityCube (kpColorSimilarityCube::Depressed | + kpColorSimilarityCube::DoubleClickInstructions, + mainWindow, parent, name), + m_mainWindow (mainWindow), + m_processedColorSimilarity (kpColor::Exact) +{ + setColorSimilarity (mainWindow->configColorSimilarity ()); +} + +kpColorSimilarityToolBarItem::~kpColorSimilarityToolBarItem () +{ +} + + +// public +int kpColorSimilarityToolBarItem::processedColorSimilarity () const +{ + return m_processedColorSimilarity; +} + + +// public slot +void kpColorSimilarityToolBarItem::setColorSimilarity (double similarity) +{ + m_oldColorSimilarity = colorSimilarity (); + + kpColorSimilarityCube::setColorSimilarity (similarity); + if (similarity > 0) + QToolTip::add (this, i18n ("Color similarity: %1%").arg (qRound (similarity * 100))); + else + QToolTip::add (this, i18n ("Color similarity: Exact")); + + m_processedColorSimilarity = kpColor::processSimilarity (colorSimilarity ()); + + m_mainWindow->configSetColorSimilarity (colorSimilarity ()); + + emit colorSimilarityChanged (colorSimilarity (), m_processedColorSimilarity); +} + +// public +double kpColorSimilarityToolBarItem::oldColorSimilarity () const +{ + return m_oldColorSimilarity; +} + + +// private virtual [base QWidget] +void kpColorSimilarityToolBarItem::mousePressEvent (QMouseEvent * /*e*/) +{ + // eat right-mouse click to prevent it from getting to the toolbar +} + +// private virtual [base QWidget] +void kpColorSimilarityToolBarItem::mouseDoubleClickEvent (QMouseEvent * /*e*/) +{ + kpColorSimilarityDialog dialog (m_mainWindow, this); + dialog.setColorSimilarity (colorSimilarity ()); + if (dialog.exec ()) + { + setColorSimilarity (dialog.colorSimilarity ()); + } +} + + +/* + * kpColorToolBar + */ + +kpColorToolBar::kpColorToolBar (const QString &label, kpMainWindow *mainWindow, const char *name) + : KToolBar (mainWindow, name), + m_mainWindow (mainWindow) +{ + setText (label); + + + QWidget *base = new QWidget (this); + m_boxLayout = new QBoxLayout (base, QBoxLayout::LeftToRight, + 5/*margin*/, (10 * 4)/*spacing*/); + + m_dualColorButton = new kpDualColorButton (mainWindow, base); + m_dualColorButton->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed); + connect (m_dualColorButton, SIGNAL (colorsSwapped (const kpColor &, const kpColor &)), + this, SIGNAL (colorsSwapped (const kpColor &, const kpColor &))); + connect (m_dualColorButton, SIGNAL (foregroundColorChanged (const kpColor &)), + this, SIGNAL (foregroundColorChanged (const kpColor &))); + connect (m_dualColorButton, SIGNAL (backgroundColorChanged (const kpColor &)), + this, SIGNAL (backgroundColorChanged (const kpColor &))); + m_boxLayout->addWidget (m_dualColorButton, 0/*stretch*/); + + m_colorPalette = new kpColorPalette (base); + connect (m_colorPalette, SIGNAL (foregroundColorChanged (const kpColor &)), + m_dualColorButton, SLOT (setForegroundColor (const kpColor &))); + connect (m_colorPalette, SIGNAL (backgroundColorChanged (const kpColor &)), + m_dualColorButton, SLOT (setBackgroundColor (const kpColor &))); + m_boxLayout->addWidget (m_colorPalette, 0/*stretch*/); + + m_colorSimilarityToolBarItem = new kpColorSimilarityToolBarItem (mainWindow, base); + m_colorSimilarityToolBarItem->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed); + connect (m_colorSimilarityToolBarItem, SIGNAL (colorSimilarityChanged (double, int)), + this, SIGNAL (colorSimilarityChanged (double, int))); + m_boxLayout->addWidget (m_colorSimilarityToolBarItem, 0/*stretch*/); + + // HACK: couldn't get QSpacerItem to work + QWidget *fakeSpacer = new QWidget (base); + m_boxLayout->addWidget (fakeSpacer, 1/*stretch*/); + + m_lastDockedOrientationSet = false; + setOrientation (orientation ()); + + KToolBar::insertWidget (0, base->width (), base); +} + +// virtual +void kpColorToolBar::setOrientation (Qt::Orientation o) +{ + // (QDockWindow::undock() calls us) + bool isOutsideDock = (place () == QDockWindow::OutsideDock); + + if (!m_lastDockedOrientationSet || !isOutsideDock) + { + m_lastDockedOrientation = o; + m_lastDockedOrientationSet = true; + } + + if (isOutsideDock) + { + //kdDebug () << "\toutside dock, forcing orientation to last" << endl; + o = m_lastDockedOrientation; + } + + if (o == Qt::Horizontal) + { + m_boxLayout->setDirection (QBoxLayout::LeftToRight); + } + else + { + m_boxLayout->setDirection (QBoxLayout::TopToBottom); + } + + m_colorPalette->setOrientation (o); + + KToolBar::setOrientation (o); +} + +kpColorToolBar::~kpColorToolBar () +{ +} + +kpColor kpColorToolBar::color (int which) const +{ + if (which < 0 || which > 1) + { + kdWarning () << "kpColorToolBar::color (" << which + << ") - out of range" << endl; + which = 0; + } + + return m_dualColorButton->color (which); +} + +void kpColorToolBar::setColor (int which, const kpColor &color) +{ + if (which < 0 || which > 1) + { + kdWarning () << "kpColorToolBar::setColor (" << which + << ") - out of range" << endl; + which = 0; + } + + m_dualColorButton->setColor (which, color); +} + +kpColor kpColorToolBar::foregroundColor () const +{ + return m_dualColorButton->foregroundColor (); +} + +void kpColorToolBar::setForegroundColor (const kpColor &color) +{ + m_dualColorButton->setForegroundColor (color); +} + +kpColor kpColorToolBar::backgroundColor () const +{ + return m_dualColorButton->backgroundColor (); +} + +void kpColorToolBar::setBackgroundColor (const kpColor &color) +{ + m_dualColorButton->setBackgroundColor (color); +} + + +kpColor kpColorToolBar::oldForegroundColor () const +{ + return m_dualColorButton->oldForegroundColor (); +} + +kpColor kpColorToolBar::oldBackgroundColor () const +{ + return m_dualColorButton->oldBackgroundColor (); +} + +double kpColorToolBar::oldColorSimilarity () const +{ + return m_colorSimilarityToolBarItem->oldColorSimilarity (); +} + + +double kpColorToolBar::colorSimilarity () const +{ + return m_colorSimilarityToolBarItem->colorSimilarity (); +} + +void kpColorToolBar::setColorSimilarity (double similarity) +{ + m_colorSimilarityToolBarItem->setColorSimilarity (similarity); +} + +int kpColorToolBar::processedColorSimilarity () const +{ + return m_colorSimilarityToolBarItem->processedColorSimilarity (); +} + + +#include <kpcolortoolbar.moc> diff --git a/kolourpaint/widgets/kpcolortoolbar.h b/kolourpaint/widgets/kpcolortoolbar.h new file mode 100644 index 00000000..b4a77bfb --- /dev/null +++ b/kolourpaint/widgets/kpcolortoolbar.h @@ -0,0 +1,297 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef __kp_color_toolbar_h__ +#define __kp_color_toolbar_h__ + + +#include <qframe.h> +#include <qwidget.h> + +#include <kcolordialog.h> +#include <ktoolbar.h> + +#include <kpcolor.h> +#include <kpcolorsimilaritycube.h> + + +class QGridLayout; +class KColorButton; + +class kpColorSimilarityCube; +class kpMainWindow; + + +// +// Widget similar to KDualColorButton. +// Main differences: +// - more consistent feel with other KolourPaint widgets +// (esp. kpColorPalette) +// - displays the transparent colour using the special pixmap +// used by kpTransparentColorCell +// - no obscure "current" colour +// +class kpDualColorButton : public QFrame +{ +Q_OBJECT + +public: + kpDualColorButton (kpMainWindow *mainWindow, + QWidget *parent, const char *name = 0); + virtual ~kpDualColorButton (); + + kpColor color (int which) const; + kpColor foregroundColor () const; + kpColor backgroundColor () const; + +public slots: + void setColor (int which, const kpColor &color); + void setForegroundColor (const kpColor &color); + void setBackgroundColor (const kpColor &color); + +signals: + // If you connect to this signal, ignore the following + // foregroundColorChanged() and backgroundColorChanged() signals + void colorsSwapped (const kpColor &newForegroundColor, + const kpColor &newBackgroundColor); + + void foregroundColorChanged (const kpColor &color); + void backgroundColorChanged (const kpColor &color); + +public: + // (only valid in slots connected to foregroundColorChanged()) + kpColor oldForegroundColor () const; + // (only valid in slots connected to backgroundColorChanged()) + kpColor oldBackgroundColor () const; + +public: + virtual QSize sizeHint () const; + +protected: + QRect swapPixmapRect () const; + QRect foregroundBackgroundRect () const; + QRect foregroundRect () const; + QRect backgroundRect () const; + + //virtual void dragEnterEvent (QDragEnterEvent *e); + virtual void dragMoveEvent (QDragMoveEvent *e); + virtual void dropEvent (QDropEvent *e); + + virtual void mousePressEvent (QMouseEvent *e); + virtual void mouseDoubleClickEvent (QMouseEvent *e); + virtual void mouseReleaseEvent (QMouseEvent *e); + + virtual void drawContents (QPainter *p); + + kpMainWindow *m_mainWindow; + kpColor m_color [2]; + kpColor m_oldColor [2]; + QPixmap *m_backBuffer; +}; + + +class kpColorCells : public KColorCells +{ +Q_OBJECT + +public: + kpColorCells (QWidget *parent, + Qt::Orientation o = Qt::Horizontal, + const char *name = 0); + virtual ~kpColorCells (); + + Qt::Orientation orientation () const; + void setOrientation (Qt::Orientation o); + +signals: + void foregroundColorChanged (const QColor &color); + void backgroundColorChanged (const QColor &color); + + // lazy + void foregroundColorChanged (const kpColor &color); + void backgroundColorChanged (const kpColor &color); + +protected: + Qt::Orientation m_orientation; + + virtual void dropEvent (QDropEvent *e); + virtual void paintCell (QPainter *painter, int row, int col); + virtual void mouseReleaseEvent (QMouseEvent *e); + virtual void resizeEvent (QResizeEvent *e); + + int m_mouseButton; + +protected slots: + void slotColorSelected (int cell); + void slotColorDoubleClicked (int cell); +}; + + +class kpTransparentColorCell : public QFrame +{ +Q_OBJECT + +public: + kpTransparentColorCell (QWidget *parent, const char *name = 0); + virtual ~kpTransparentColorCell (); + + virtual QSize sizeHint () const; + +signals: + void transparentColorSelected (int mouseButton); + + // lazy + void foregroundColorChanged (const kpColor &color); + void backgroundColorChanged (const kpColor &color); + +protected: + virtual void mousePressEvent (QMouseEvent *e); + virtual void mouseReleaseEvent (QMouseEvent *e); + + virtual void drawContents (QPainter *p); + + QPixmap m_pixmap; +}; + + +class kpColorPalette : public QWidget +{ +Q_OBJECT + +public: + kpColorPalette (QWidget *parent, + Qt::Orientation o = Qt::Horizontal, + const char *name = 0); + virtual ~kpColorPalette (); + + Qt::Orientation orientation () const; + void setOrientation (Qt::Orientation o); + +signals: + void foregroundColorChanged (const kpColor &color); + void backgroundColorChanged (const kpColor &color); + +protected: + Qt::Orientation m_orientation; + + QBoxLayout *m_boxLayout; + kpTransparentColorCell *m_transparentColorCell; + kpColorCells *m_colorCells; +}; + + +class kpColorSimilarityToolBarItem : public kpColorSimilarityCube +{ +Q_OBJECT + +public: + kpColorSimilarityToolBarItem (kpMainWindow *mainWindow, + QWidget *parent, + const char *name = 0); + virtual ~kpColorSimilarityToolBarItem (); + +public: + int processedColorSimilarity () const; + +public slots: + void setColorSimilarity (double similarity); + +signals: + void colorSimilarityChanged (double similarity, int processedSimilarity); + +public: + // (only valid in slots connected to colorSimilarityChanged()); + double oldColorSimilarity () const; + +private: + virtual void mousePressEvent (QMouseEvent *e); + virtual void mouseDoubleClickEvent (QMouseEvent *e); + +private: + kpMainWindow *m_mainWindow; + + double m_oldColorSimilarity; + int m_processedColorSimilarity; +}; + + +class kpColorToolBar : public KToolBar +{ +Q_OBJECT + +public: + kpColorToolBar (const QString &label, kpMainWindow *mainWindow, const char *name = 0); + virtual ~kpColorToolBar (); + + kpColor color (int which) const; + void setColor (int which, const kpColor &color); + + kpColor foregroundColor () const; + kpColor backgroundColor () const; + + double colorSimilarity () const; + void setColorSimilarity (double similarity); + int processedColorSimilarity () const; + +signals: + // If you connect to this signal, ignore the following + // foregroundColorChanged() and backgroundColorChanged() signals + void colorsSwapped (const kpColor &newForegroundColor, + const kpColor &newBackgroundColor); + + void foregroundColorChanged (const kpColor &color); + void backgroundColorChanged (const kpColor &color); + void colorSimilarityChanged (double similarity, int processedSimilarity); + +public: + // (only valid in slots connected to foregroundColorChanged()) + kpColor oldForegroundColor () const; + // (only valid in slots connected to backgroundColorChanged()) + kpColor oldBackgroundColor () const; + + // (only valid in slots connected to colorSimilarityChanged()) + double oldColorSimilarity () const; + +public slots: + void setForegroundColor (const kpColor &color); + void setBackgroundColor (const kpColor &color); + +private: + kpMainWindow *m_mainWindow; + + Qt::Orientation m_lastDockedOrientation; + bool m_lastDockedOrientationSet; + virtual void setOrientation (Qt::Orientation o); + + QBoxLayout *m_boxLayout; + kpDualColorButton *m_dualColorButton; + kpColorPalette *m_colorPalette; + kpColorSimilarityToolBarItem *m_colorSimilarityToolBarItem; +}; + +#endif // __kp_color_toolbar_h__ diff --git a/kolourpaint/widgets/kpresizesignallinglabel.cpp b/kolourpaint/widgets/kpresizesignallinglabel.cpp new file mode 100644 index 00000000..77d0ad2b --- /dev/null +++ b/kolourpaint/widgets/kpresizesignallinglabel.cpp @@ -0,0 +1,67 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define DEBUG_KP_RESIZE_SIGNALLING_LABEL 0 + + +#include <kpresizesignallinglabel.h> + +#include <kdebug.h> + + +kpResizeSignallingLabel::kpResizeSignallingLabel (const QString &string, + QWidget *parent, + const char *name) + : QLabel (string, parent, name) +{ +} + +kpResizeSignallingLabel::kpResizeSignallingLabel (QWidget *parent, + const char *name) + : QLabel (parent, name) +{ +} + +kpResizeSignallingLabel::~kpResizeSignallingLabel () +{ +} + + +// protected virtual [base QLabel] +void kpResizeSignallingLabel::resizeEvent (QResizeEvent *e) +{ +#if DEBUG_KP_RESIZE_SIGNALLING_LABEL + kdDebug () << "kpResizeSignallingLabel::resizeEvent() newSize=" << e->size () + << " oldSize=" << e->oldSize () << endl; +#endif + QLabel::resizeEvent (e); + + emit resized (); +} + + +#include <kpresizesignallinglabel.moc> diff --git a/kolourpaint/widgets/kpresizesignallinglabel.h b/kolourpaint/widgets/kpresizesignallinglabel.h new file mode 100644 index 00000000..6cd3beba --- /dev/null +++ b/kolourpaint/widgets/kpresizesignallinglabel.h @@ -0,0 +1,52 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef KP_RESIZE_SIGNALLING_LABEL +#define KP_RESIZE_SIGNALLING_LABEL + + +#include <qlabel.h> + + +class kpResizeSignallingLabel : public QLabel +{ +Q_OBJECT + +public: + kpResizeSignallingLabel (const QString &string, QWidget *parent, const char *name = 0); + kpResizeSignallingLabel (QWidget *parent, const char *name = 0); + virtual ~kpResizeSignallingLabel (); + +signals: + void resized (); + +protected: + virtual void resizeEvent (QResizeEvent *e); +}; + + +#endif // KP_RESIZE_SIGNALLING_LABEL diff --git a/kolourpaint/widgets/kpsqueezedtextlabel.cpp b/kolourpaint/widgets/kpsqueezedtextlabel.cpp new file mode 100644 index 00000000..53fd85c9 --- /dev/null +++ b/kolourpaint/widgets/kpsqueezedtextlabel.cpp @@ -0,0 +1,215 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define DEBUG_KP_SQUEEZED_TEXT_LABEL 0 + + +#include <kpsqueezedtextlabel.h> + +#include <qfont.h> +#include <qfontmetrics.h> +#include <qstring.h> + +#include <kdebug.h> +#include <klocale.h> + + +kpSqueezedTextLabel::kpSqueezedTextLabel (QWidget *parent, const char *name) + : QLabel (parent, name), + m_showEllipsis (true) +{ +} + +kpSqueezedTextLabel::kpSqueezedTextLabel (const QString &text, QWidget *parent, const char *name) + : QLabel (parent, name), + m_showEllipsis (true) +{ + setText (text); +} + + +// public virtual +QSize kpSqueezedTextLabel::minimumSizeHint () const +{ +#if DEBUG_KP_SQUEEZED_TEXT_LABEL && 1 + kdDebug () << "kpSqueezedTextLabel::minimumSizeHint() qLabel prefers" + << QLabel::minimumSizeHint () << endl; +#endif + return QSize (-1/*no minimum width*/, QLabel::minimumHeight ()); +} + + +// public +QString kpSqueezedTextLabel::fullText () const +{ + return m_fullText; +} + + +// public +bool kpSqueezedTextLabel::showEllipsis () const +{ + return m_showEllipsis; +} + +// public +void kpSqueezedTextLabel::setShowEllipsis (bool yes) +{ + if (m_showEllipsis == yes) + return; + + m_showEllipsis = yes; + + squeezeText (); +} + + +// public slots virtual [base QLabel] +void kpSqueezedTextLabel::setText (const QString &text) +{ + m_fullText = text; + squeezeText (); +} + + +// protected virtual [base QWidget] +void kpSqueezedTextLabel::resizeEvent (QResizeEvent *e) +{ +#if DEBUG_KP_SQUEEZED_TEXT_LABEL && 1 + kdDebug () << "kpSqueezedTextLabeL::resizeEvent() size=" << e->size () + << " oldSize=" << e->oldSize () + << endl; +#endif + squeezeText (); +} + + +// protected +QString kpSqueezedTextLabel::ellipsisText () const +{ + return m_showEllipsis ? i18n ("...") : QString::null; +} + +// protected +void kpSqueezedTextLabel::squeezeText () +{ +#if DEBUG_KP_SQUEEZED_TEXT_LABEL && 1 + kdDebug () << "kpSqueezedTextLabeL::squeezeText" << endl; +#endif + + QFontMetrics fontMetrics (font ()); + int fullTextWidth = fontMetrics.width (m_fullText); +#if DEBUG_KP_SQUEEZED_TEXT_LABEL && 1 + kdDebug () << "\tfullText=" << m_fullText + << " fullTextWidth=" << fullTextWidth + << " labelWidth=" << width () + << endl; +#endif + + if (fullTextWidth <= width ()) + { + #if DEBUG_KP_SQUEEZED_TEXT_LABEL && 1 + kdDebug () << "\tfullText will fit - display" << endl; + #endif + QLabel::setText (m_fullText); + } + else + { + #if DEBUG_KP_SQUEEZED_TEXT_LABEL && 1 + kdDebug () << "\tfullText won't fit :( - squeeze" << endl; + kdDebug () << "\t\twidth of \"...\"=" + << fontMetrics.width (ellipsisText ()) + << endl; + + #endif + if (fontMetrics.width (ellipsisText ()) > width ()) + { + #if DEBUG_KP_SQUEEZED_TEXT_LABEL && 1 + kdDebug () << "\t\t\tcan't even fit \"...\" - forget it" << endl; + #endif + QLabel::setText (QString::null); + return; + } + + // Binary search our way to fit squeezed text + int numLettersToUseLo = 0; + int numLettersToUseHi = m_fullText.length (); + int numLettersToUse = 0; + + while (numLettersToUseLo <= numLettersToUseHi) + { + int numLettersToUseMid = (numLettersToUseLo + numLettersToUseHi) / 2; + int squeezedWidth = fontMetrics.width (m_fullText.left (numLettersToUseMid) + ellipsisText ()); + #if DEBUG_KP_SQUEEZED_TEXT_LABEL && 1 + kdDebug () << "\tbsearch: lo=" << numLettersToUseLo + << " hi=" << numLettersToUseHi + << " mid=" << numLettersToUseMid + << " acceptable=" << numLettersToUse + << " squeezedWidth=" << squeezedWidth + << endl; + #endif + + if (squeezedWidth == width ()) + { + #if DEBUG_KP_SQUEEZED_TEXT_LABEL && 1 + kdDebug () << "\t\tperfect match!" << endl; + #endif + numLettersToUse = numLettersToUseMid; + break; + } + else if (squeezedWidth < width ()) + { + #if DEBUG_KP_SQUEEZED_TEXT_LABEL && 1 + kdDebug () << "\t\tsmall enough - numLettersToUse=" + << numLettersToUse << endl; + #endif + if (numLettersToUseMid > numLettersToUse) + { + numLettersToUse = numLettersToUseMid; + #if DEBUG_KP_SQUEEZED_TEXT_LABEL && 1 + kdDebug () << "\t\t\tset numLettersToUse=" + << numLettersToUse + << endl; + #endif + } + + numLettersToUseLo = numLettersToUseMid + 1; + } + else + { + #if DEBUG_KP_SQUEEZED_TEXT_LABEL && 1 + kdDebug () << "\t\ttoo big" << endl; + #endif + numLettersToUseHi = numLettersToUseMid - 1; + } + } + + QLabel::setText (m_fullText.left (numLettersToUse) + ellipsisText ()); + } +} + +#include <kpsqueezedtextlabel.moc> diff --git a/kolourpaint/widgets/kpsqueezedtextlabel.h b/kolourpaint/widgets/kpsqueezedtextlabel.h new file mode 100644 index 00000000..57aa7b2f --- /dev/null +++ b/kolourpaint/widgets/kpsqueezedtextlabel.h @@ -0,0 +1,65 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef __kp_squeezed_text_label_h__ +#define __kp_squeezed_text_label_h__ + +#include <qlabel.h> +#include <qstring.h> + + +// KSqueezedTextLabel done properly - squeeze at the end of the string, +// not the middle. +class kpSqueezedTextLabel : public QLabel +{ +Q_OBJECT + +public: + kpSqueezedTextLabel (QWidget *parent, const char *name = 0); + kpSqueezedTextLabel (const QString &text, QWidget *parent, const char *name = 0); + + virtual QSize minimumSizeHint () const; + + // TODO: maybe text() should return the full text? + QString fullText () const; + + bool showEllipsis () const; + void setShowEllipsis (bool yes = true); + +public slots: + virtual void setText (const QString &text); + +protected: + virtual void resizeEvent (QResizeEvent *); + QString ellipsisText () const; + void squeezeText (); + + QString m_fullText; + bool m_showEllipsis; +}; + +#endif // __kp_squeezed_text_label_h__ diff --git a/kolourpaint/widgets/kptooltoolbar.cpp b/kolourpaint/widgets/kptooltoolbar.cpp new file mode 100644 index 00000000..b8d1985c --- /dev/null +++ b/kolourpaint/widgets/kptooltoolbar.cpp @@ -0,0 +1,640 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define DEBUG_KP_TOOL_TOOL_BAR 0 + + +#include <kptooltoolbar.h> + +#include <qbuttongroup.h> +#include <qlayout.h> +#include <qdatetime.h> +#include <qtoolbutton.h> +#include <qtooltip.h> +#include <qwidget.h> +#include <qwhatsthis.h> + +#include <kconfig.h> +#include <kdebug.h> +#include <kglobalsettings.h> +#include <kicontheme.h> + +#include <kpdefs.h> +#include <kptool.h> +#include <kptoolaction.h> +#include <kptoolwidgetbrush.h> +#include <kptoolwidgeterasersize.h> +#include <kptoolwidgetfillstyle.h> +#include <kptoolwidgetlinewidth.h> +#include <kptoolwidgetopaqueortransparent.h> +#include <kptoolwidgetspraycansize.h> + + +class kpToolButton : public QToolButton +{ +public: + kpToolButton (kpTool *tool, QWidget *parent) + : QToolButton (parent), + m_tool (tool) + { + } + + virtual ~kpToolButton () + { + } + +protected: + // virtual [base QWidget] + void mouseDoubleClickEvent (QMouseEvent *e) + { + if (e->button () == Qt::LeftButton && m_tool) + m_tool->globalDraw (); + } + + kpTool *m_tool; +}; + + +kpToolToolBar::kpToolToolBar (const QString &label, kpMainWindow *mainWindow, int colsOrRows, const char *name) + : KToolBar ((QWidget *) mainWindow, name, false/*don't use global toolBar settings*/, true/*readConfig*/), + m_vertCols (colsOrRows), + m_buttonGroup (0), + m_baseWidget (0), + m_baseLayout (0), + m_toolLayout (0), + m_previousTool (0), m_currentTool (0), + m_defaultIconSize (0) +{ + setText (label); + + + // With these lines enabled, mousePressEvent's weren't being generated + // when right clicking in empty part of the toolbar (each call affects + // the toolbar in its respective orientation). They don't seem to be + // needed anyway since !isResizeEnabled(). + + //setHorizontallyStretchable (false); + //setVerticallyStretchable (false); + + + m_baseWidget = new QWidget (this); + +#if DEBUG_KP_TOOL_TOOL_BAR + QTime timer; + timer.start (); +#endif + + m_toolWidgets.append (m_toolWidgetBrush = + new kpToolWidgetBrush (m_baseWidget, "Tool Widget Brush")); + m_toolWidgets.append (m_toolWidgetEraserSize = + new kpToolWidgetEraserSize (m_baseWidget, "Tool Widget Eraser Size")); + m_toolWidgets.append (m_toolWidgetFillStyle = + new kpToolWidgetFillStyle (m_baseWidget, "Tool Widget Fill Style")); + m_toolWidgets.append (m_toolWidgetLineWidth = + new kpToolWidgetLineWidth (m_baseWidget, "Tool Widget Line Width")); + m_toolWidgets.append (m_toolWidgetOpaqueOrTransparent = + new kpToolWidgetOpaqueOrTransparent (m_baseWidget, "Tool Widget Opaque/Transparent")); + m_toolWidgets.append (m_toolWidgetSpraycanSize = + new kpToolWidgetSpraycanSize (m_baseWidget, "Tool Widget Spraycan Size")); + +#if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "kpToolToolBar::<ctor> create tool widgets msec=" + << timer.restart () << endl; +#endif + + for (QValueVector <kpToolWidgetBase *>::const_iterator it = m_toolWidgets.begin (); + it != m_toolWidgets.end (); + it++) + { + connect (*it, SIGNAL (optionSelected (int, int)), + this, SIGNAL (toolWidgetOptionSelected ())); + } + +#if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "kpToolToolBar::<ctor> connect widgets msec=" + << timer.restart () << endl; +#endif + + m_lastDockedOrientationSet = false; + setOrientation (orientation ()); + +#if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "kpToolToolBar::<ctor> layout tool widgets msec=" + << timer.elapsed () << endl; +#endif + + m_buttonGroup = new QButtonGroup (); // invisible + m_buttonGroup->setExclusive (true); + + connect (m_buttonGroup, SIGNAL (clicked (int)), SLOT (slotToolButtonClicked ())); + + hideAllToolWidgets (); +} + +kpToolToolBar::~kpToolToolBar () +{ + unregisterAllTools (); + delete m_buttonGroup; +} + + +// private +int kpToolToolBar::defaultIconSize () +{ + // Cached? + if (m_defaultIconSize > 0) + return m_defaultIconSize; + +#if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "kpToolToolBar::defaultIconSize()" << endl; +#endif + + + KConfigGroupSaver cfgGroupSaver (KGlobal::config (), + kpSettingsGroupTools); + KConfigBase *cfg = cfgGroupSaver.config (); + + if (cfg->hasKey (kpSettingToolBoxIconSize)) + { + m_defaultIconSize = cfg->readNumEntry (kpSettingToolBoxIconSize); + #if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "\tread: " << m_defaultIconSize << endl; + #endif + } + else + { + m_defaultIconSize = -1; +#if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "\tfirst time - writing default: " << m_defaultIconSize << endl; +#endif + cfg->writeEntry (kpSettingToolBoxIconSize, m_defaultIconSize); + cfg->sync (); + } + + + if (m_defaultIconSize <= 0) + { + // Adapt according to screen geometry + const QRect desktopSize = KGlobalSettings::desktopGeometry (this); + #if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "\tadapting to screen size=" << desktopSize << endl; + #endif + + if (desktopSize.width () >= 1024 && desktopSize.height () >= 768) + m_defaultIconSize = KIcon::SizeSmallMedium/*22x22*/; + else + m_defaultIconSize = KIcon::SizeSmall/*16x16*/; + } + + +#if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "\treturning " << m_defaultIconSize << endl; +#endif + return m_defaultIconSize; +} + +// public +void kpToolToolBar::registerTool (kpTool *tool) +{ + for (QValueVector <kpButtonToolPair>::const_iterator it = m_buttonToolPairs.begin (); + it != m_buttonToolPairs.end (); + it++) + { + if ((*it).m_tool == tool) + return; + } + int num = m_buttonToolPairs.count (); + + QToolButton *b = new kpToolButton (tool, m_baseWidget); + b->setAutoRaise (true); + b->setUsesBigPixmap (false); + b->setUsesTextLabel (false); + b->setToggleButton (true); + + b->setText (tool->text ()); + b->setIconSet (tool->iconSet (defaultIconSize ())); + QToolTip::add (b, tool->toolTip ()); + QWhatsThis::add (b, tool->description ()); + + m_buttonGroup->insert (b); + addButton (b, orientation (), num); + + m_buttonToolPairs.append (kpButtonToolPair (b, tool)); + + + connect (tool, SIGNAL (actionActivated ()), + this, SLOT (slotToolActionActivated ())); + connect (tool, SIGNAL (actionToolTipChanged (const QString &)), + this, SLOT (slotToolActionToolTipChanged ())); +} + +// public +void kpToolToolBar::unregisterTool (kpTool *tool) +{ + for (QValueVector <kpButtonToolPair>::iterator it = m_buttonToolPairs.begin (); + it != m_buttonToolPairs.end (); + it++) + { + if ((*it).m_tool == tool) + { + delete ((*it).m_button); + m_buttonToolPairs.erase (it); + + disconnect (tool, SIGNAL (actionActivated ()), + this, SLOT (slotToolActionActivated ())); + disconnect (tool, SIGNAL (actionToolTipChanged (const QString &)), + this, SLOT (slotToolActionToolTipChanged ())); + break; + } + } +} + +// public +void kpToolToolBar::unregisterAllTools () +{ + for (QValueVector <kpButtonToolPair>::iterator it = m_buttonToolPairs.begin (); + it != m_buttonToolPairs.end (); + it++) + { + delete ((*it).m_button); + } + + m_buttonToolPairs.clear (); +} + + +// public +kpTool *kpToolToolBar::tool () const +{ + return m_currentTool; +} + +// public +void kpToolToolBar::selectTool (const kpTool *tool, bool reselectIfSameTool) +{ +#if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "kpToolToolBar::selectTool (tool=" << tool + << ") currentTool=" << m_currentTool + << endl; +#endif + + if (!reselectIfSameTool && tool == m_currentTool) + return; + + if (tool) + { + for (QValueVector <kpButtonToolPair>::iterator it = m_buttonToolPairs.begin (); + it != m_buttonToolPairs.end (); + it++) + { + if ((*it).m_tool == tool) + { + m_buttonGroup->setButton (m_buttonGroup->id ((*it).m_button)); + slotToolButtonClicked (); + break; + } + } + } + else + { + QButton *b = m_buttonGroup->selected (); + #if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "\twant to select no tool - button selected=" << b << endl; + #endif + if (b) + { + b->toggle (); + slotToolButtonClicked (); + } + } +} + + +// public +kpTool *kpToolToolBar::previousTool () const +{ + return m_previousTool; +} + +// public +void kpToolToolBar::selectPreviousTool () +{ + selectTool (m_previousTool); +} + + +// public +void kpToolToolBar::hideAllToolWidgets () +{ + for (QValueVector <kpToolWidgetBase *>::const_iterator it = m_toolWidgets.begin (); + it != m_toolWidgets.end (); + it++) + { + (*it)->hide (); + } +} + +// public +int kpToolToolBar::numShownToolWidgets () const +{ +#if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "kpToolToolBar::numShownToolWidgets()" << endl; +#endif + + int ret = 0; + + for (QValueVector <kpToolWidgetBase *>::const_iterator it = m_toolWidgets.begin (); + it != m_toolWidgets.end (); + it++) + { + #if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "\t" << (*it)->name () + << " isShown=" << (*it)->isShown () + << endl; + #endif + if ((*it)->isShown ()) + ret++; + } + + return ret; +} + +// public +kpToolWidgetBase *kpToolToolBar::shownToolWidget (int which) const +{ + int uptoVisibleWidget = 0; + + for (QValueVector <kpToolWidgetBase *>::const_iterator it = m_toolWidgets.begin (); + it != m_toolWidgets.end (); + it++) + { + if ((*it)->isShown ()) + { + if (which == uptoVisibleWidget) + return *it; + + uptoVisibleWidget++; + } + } + + return 0; +} + + +// public +bool kpToolToolBar::toolsSingleKeyTriggersEnabled () const +{ + for (QValueVector <kpButtonToolPair>::const_iterator it = m_buttonToolPairs.begin (); + it != m_buttonToolPairs.end (); + it++) + { + if (!(*it).m_tool->singleKeyTriggersEnabled ()) + return false; + } + + return true; +} + +// public +void kpToolToolBar::enableToolsSingleKeyTriggers (bool enable) +{ +#if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "kpToolToolBar::enableToolsSingleKeyTriggers(" << enable << ")" << endl; +#endif + + for (QValueVector <kpButtonToolPair>::const_iterator it = m_buttonToolPairs.begin (); + it != m_buttonToolPairs.end (); + it++) + { + (*it).m_tool->enableSingleKeyTriggers (enable); + } +} + + +// private slot +void kpToolToolBar::slotToolButtonClicked () +{ + QButton *b = m_buttonGroup->selected (); + +#if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "kpToolToolBar::slotToolButtonClicked() button=" << b << endl; +#endif + + kpTool *tool = 0; + for (QValueVector <kpButtonToolPair>::iterator it = m_buttonToolPairs.begin (); + it != m_buttonToolPairs.end (); + it++) + { + if ((*it).m_button == b) + { + tool = (*it).m_tool; + break; + } + } + +#if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "\ttool=" << tool + << " currentTool=" << m_currentTool + << endl; +#endif + + if (tool == m_currentTool) + { + if (m_currentTool) + m_currentTool->reselect (); + + return; + } + + if (m_currentTool) + m_currentTool->endInternal (); + + m_previousTool = m_currentTool; + m_currentTool = tool; + + if (m_currentTool) + { + kpToolAction *action = m_currentTool->action (); + if (action) + { + action->setChecked (true); + } + + m_currentTool->beginInternal (); + } + + emit sigToolSelected (m_currentTool); +} + + +#define CONST_KP_TOOL_SENDER() (dynamic_cast <const kpTool *> (sender ())) + +// private slot +void kpToolToolBar::slotToolActionActivated () +{ + const kpTool *tool = CONST_KP_TOOL_SENDER (); + +#if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "kpToolToolBar::slotToolActionActivated() tool=" + << (tool ? tool->name () : "null") + << endl; +#endif + + if (m_currentTool) + { + // If the user clicks on the same KToggleAction, it unchecks it + // - this is inconsistent with the Tool Box so always make sure it's + // checked. + kpToolAction *action = m_currentTool->action (); + if (action) + { + action->setChecked (true); + } + } + + selectTool (tool, true/*reselect if same tool*/); +} + +// private slot +void kpToolToolBar::slotToolActionToolTipChanged () +{ + const kpTool *tool = CONST_KP_TOOL_SENDER (); + +#if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "kpToolToolBar::slotToolActionToolTipChanged() tool=" + << (tool ? tool->name () : "null") + << endl; +#endif + + if (!tool) + return; + + for (QValueVector <kpButtonToolPair>::const_iterator it = m_buttonToolPairs.begin (); + it != m_buttonToolPairs.end (); + it++) + { + if (tool == (*it).m_tool) + { + QToolTip::add ((*it).m_button, tool->toolTip ()); + return; + } + } +} + + +// public slot virtual [base QDockWindow] +void kpToolToolBar::setOrientation (Qt::Orientation o) +{ +#if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "kpToolToolBar::setOrientation(" + << (o == Qt::Vertical ? "vertical" : "horizontal") + << ") called!" << endl; +#endif + + // (QDockWindow::undock() calls us) + bool isOutsideDock = (place () == QDockWindow::OutsideDock); + + if (!m_lastDockedOrientationSet || !isOutsideDock) + { + m_lastDockedOrientation = o; + m_lastDockedOrientationSet = true; + } + + if (isOutsideDock) + { + #if DEBUG_KP_TOOL_TOOL_BAR + kdDebug () << "\toutside dock, forcing orientation to last" << endl; + #endif + o = m_lastDockedOrientation; + } + + delete m_toolLayout; + delete m_baseLayout; + if (o == Qt::Vertical) + { + m_baseLayout = new QBoxLayout (m_baseWidget, QBoxLayout::TopToBottom, + 5/*margin*/, + 10/*spacing*/); + m_toolLayout = new QGridLayout (m_baseLayout, + 5/*arbitrary rows since toolBar auto-expands*/, + m_vertCols, + 0/*margin*/, + 0/*spacing*/); + } + else // if (o == Qt::Horizontal) + { + m_baseLayout = new QBoxLayout (m_baseWidget, QBoxLayout::LeftToRight, + 5/*margin*/, + 10/*spacing*/); + m_toolLayout = new QGridLayout (m_baseLayout, + m_vertCols/*rows in this case, since horiz*/, + 5/*arbitrary cols since toolBar auto-expands*/, + 0/*margin*/, + 0/*spacing*/); + } + + int num = 0; + + for (QValueVector <kpButtonToolPair>::iterator it = m_buttonToolPairs.begin (); + it != m_buttonToolPairs.end (); + it++) + { + addButton ((*it).m_button, o, num); + num++; + } + + for (QValueVector <kpToolWidgetBase *>::const_iterator it = m_toolWidgets.begin (); + it != m_toolWidgets.end (); + it++) + { + if (*it) + { + m_baseLayout->addWidget (*it, + 0/*stretch*/, + o == Qt::Vertical ? Qt::AlignHCenter : Qt::AlignVCenter); + } + } + + KToolBar::setOrientation (o); +} + +// private +void kpToolToolBar::addButton (QButton *button, Qt::Orientation o, int num) +{ + if (o == Qt::Vertical) + m_toolLayout->addWidget (button, num / m_vertCols, num % m_vertCols); + else + { + // maps Left (o = vertical) to Bottom (o = horizontal) + int row = (m_vertCols - 1) - (num % m_vertCols); + m_toolLayout->addWidget (button, row, num / m_vertCols); + } +} + + +#include <kptooltoolbar.moc> diff --git a/kolourpaint/widgets/kptooltoolbar.h b/kolourpaint/widgets/kptooltoolbar.h new file mode 100644 index 00000000..c3a7d1b7 --- /dev/null +++ b/kolourpaint/widgets/kptooltoolbar.h @@ -0,0 +1,155 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef __kp_tool_tool_bar_h__ +#define __kp_tool_tool_bar_h__ + +#include <qvaluevector.h> + +#include <ktoolbar.h> + + +class QBoxLayout; +class QButton; +class QButtonGroup; +class QWidget; +class QGridLayout; + +class kpMainWindow; +class kpTool; + +class kpToolWidgetBase; +class kpToolWidgetBrush; +class kpToolWidgetEraserSize; +class kpToolWidgetFillStyle; +class kpToolWidgetLineWidth; +class kpToolWidgetOpaqueOrTransparent; +class kpToolWidgetSpraycanSize; + +class kpToolToolBar : public KToolBar +{ +Q_OBJECT + +public: + kpToolToolBar (const QString &label, kpMainWindow *mainWindow, int colsOrRows = 2, const char *name = 0); + virtual ~kpToolToolBar (); + +private: + int defaultIconSize (); +public: + void registerTool (kpTool *tool); + void unregisterTool (kpTool *tool); + void unregisterAllTools (); + + kpTool *tool () const; + void selectTool (const kpTool *tool, bool reselectIfSameTool = false); + + kpTool *previousTool () const; + void selectPreviousTool (); + + void hideAllToolWidgets (); + // could this be cleaner (the tools have to access them individually somehow)? + kpToolWidgetBrush *toolWidgetBrush () const { return m_toolWidgetBrush; } + kpToolWidgetEraserSize *toolWidgetEraserSize () const { return m_toolWidgetEraserSize; } + kpToolWidgetFillStyle *toolWidgetFillStyle () const { return m_toolWidgetFillStyle; } + kpToolWidgetLineWidth *toolWidgetLineWidth () const { return m_toolWidgetLineWidth; } + kpToolWidgetOpaqueOrTransparent *toolWidgetOpaqueOrTransparent () const { return m_toolWidgetOpaqueOrTransparent; } + kpToolWidgetSpraycanSize *toolWidgetSpraycanSize () const { return m_toolWidgetSpraycanSize; } + +public: + int numShownToolWidgets () const; + kpToolWidgetBase *shownToolWidget (int which) const; + + bool toolsSingleKeyTriggersEnabled () const; + void enableToolsSingleKeyTriggers (bool enable); + +signals: + void sigToolSelected (kpTool *tool); // tool may be 0 + void toolWidgetOptionSelected (); + +private slots: + void slotToolButtonClicked (); + + void slotToolActionActivated (); + void slotToolActionToolTipChanged (); + +public slots: + virtual void setOrientation (Qt::Orientation o); + +private: + void addButton (QButton *button, Qt::Orientation o, int num); + + Qt::Orientation m_lastDockedOrientation; + bool m_lastDockedOrientationSet; + int m_vertCols; + + QButtonGroup *m_buttonGroup; + QWidget *m_baseWidget; + QBoxLayout *m_baseLayout; + QGridLayout *m_toolLayout; + + kpToolWidgetBrush *m_toolWidgetBrush; + kpToolWidgetEraserSize *m_toolWidgetEraserSize; + kpToolWidgetFillStyle *m_toolWidgetFillStyle; + kpToolWidgetLineWidth *m_toolWidgetLineWidth; + kpToolWidgetOpaqueOrTransparent *m_toolWidgetOpaqueOrTransparent; + kpToolWidgetSpraycanSize *m_toolWidgetSpraycanSize; + + QValueVector <kpToolWidgetBase *> m_toolWidgets; + +private: + struct kpButtonToolPair + { + kpButtonToolPair (QButton *button, kpTool *tool) + : m_button (button), m_tool (tool) + { + } + + kpButtonToolPair () + : m_button (0), m_tool (0) + { + } + + QButton *m_button; + kpTool *m_tool; + }; + + QValueVector <kpButtonToolPair> m_buttonToolPairs; + + kpTool *m_previousTool, *m_currentTool; + + int m_defaultIconSize; + +private: + // There is no need to maintain binary compatibility at this stage. + // The d-pointer is just so that you can experiment without recompiling + // the kitchen sink. + class kpToolToolBarPrivate *d; +}; + +#endif // __kp_tool_tool_bar_h__ diff --git a/kolourpaint/widgets/kptoolwidgetbase.cpp b/kolourpaint/widgets/kptoolwidgetbase.cpp new file mode 100644 index 00000000..a0042dbc --- /dev/null +++ b/kolourpaint/widgets/kptoolwidgetbase.cpp @@ -0,0 +1,608 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define DEBUG_KP_TOOL_WIDGET_BASE 0 + + +#include <kptoolwidgetbase.h> + +#include <qbitmap.h> +#include <qcolor.h> +#include <qimage.h> +#include <qpainter.h> +#include <qtooltip.h> + +#include <kapplication.h> +#include <kconfig.h> +#include <kdebug.h> + +#include <kpdefs.h> +#include <kpeffectinvert.h> + + +kpToolWidgetBase::kpToolWidgetBase (QWidget *parent, const char *name) + : QFrame (parent, name), + m_invertSelectedPixmap (true), + m_selectedRow (-1), m_selectedCol (-1) +{ + if (!name) + kdError () << "kpToolWidgetBase::kpToolWidgetBase() without name" << endl; + + setFrameStyle (QFrame::Panel | QFrame::Sunken); + setFixedSize (44, 66); +} + +kpToolWidgetBase::~kpToolWidgetBase () +{ +} + + +// public +void kpToolWidgetBase::addOption (const QPixmap &pixmap, const QString &toolTip) +{ + if (m_pixmaps.isEmpty ()) + startNewOptionRow (); + + m_pixmaps.last ().append (pixmap); + m_pixmapRects.last ().append (QRect ()); + m_toolTips.last ().append (toolTip); +} + +// public +void kpToolWidgetBase::startNewOptionRow () +{ + m_pixmaps.resize (m_pixmaps.count () + 1); + m_pixmapRects.resize (m_pixmapRects.count () + 1); + m_toolTips.resize (m_toolTips.count () + 1); +} + +// public +void kpToolWidgetBase::finishConstruction (int fallBackRow, int fallBackCol) +{ +#if DEBUG_KP_TOOL_WIDGET_BASE + kdDebug () << "kpToolWidgetBase(" << name () + << ")::kpToolWidgetBase(fallBack:row=" << fallBackRow + << ",col=" << fallBackCol + << ")" + << endl; +#endif + + relayoutOptions (); + + const QPair <int, int> rowColPair = defaultSelectedRowAndCol (); + if (!setSelected (rowColPair.first, rowColPair.second, false/*don't save*/)) + { + if (!setSelected (fallBackRow, fallBackCol)) + { + if (!setSelected (0, 0)) + { + kdError () << "kpToolWidgetBase::finishConstruction() " + "can't even fall back to setSelected(row=0,col=0)" << endl; + } + } + } +} + + +// private +QValueVector <int> kpToolWidgetBase::spreadOutElements (const QValueVector <int> &sizes, int max) +{ + if (sizes.count () == 0) + return QValueVector <int> (); + else if (sizes.count () == 1) + return QValueVector <int> (1, sizes.first () > max ? 0 : 1/*margin*/); + + QValueVector <int> retOffsets (sizes.count ()); + + int totalSize = 0; + for (int i = 0; i < (int) sizes.count (); i++) + totalSize += sizes [i]; + + int margin = 1; + + // if don't fit with margin, then just return elements + // packed right next to each other + if (totalSize + margin * 2 > max) + { + retOffsets [0] = 0; + for (int i = 1; i < (int) sizes.count (); i++) + retOffsets [i] = retOffsets [i - 1] + sizes [i - 1]; + + return retOffsets; + } + + int maxLeftOver = max - (totalSize + margin * 2); + + int startCompensating = -1; + int numCompensate = 0; + + int spacing = 0; + + spacing = maxLeftOver / (sizes.count () - 1); + if (spacing * int (sizes.count () - 1) < maxLeftOver) + { + numCompensate = maxLeftOver - spacing * (sizes.count () - 1); + startCompensating = ((sizes.count () - 1) - numCompensate) / 2; + } + + retOffsets [0] = margin; + for (int i = 1; i < (int) sizes.count (); i++) + { + retOffsets [i] += retOffsets [i - 1] + + sizes [i - 1] + + spacing + + ((numCompensate && + i >= startCompensating && + i < startCompensating + numCompensate) ? 1 : 0); + } + + return retOffsets; +} + + +// public +QPair <int, int> kpToolWidgetBase::defaultSelectedRowAndCol () const +{ + int row = -1, col = -1; + + if (name ()) + { + KConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupTools); + KConfigBase *cfg = cfgGroupSaver.config (); + + QString nameString = QString::fromLatin1 (name ()); + + row = cfg->readNumEntry (nameString + QString::fromLatin1 (" Row"), -1); + col = cfg->readNumEntry (nameString + QString::fromLatin1 (" Col"), -1); + } + +#if DEBUG_KP_TOOL_WIDGET_BASE + kdDebug () << "kpToolWidgetBase(" << name () + << ")::defaultSelectedRowAndCol() returning row=" << row + << " col=" << col + << endl; +#endif + + return qMakePair (row, col); +} + +// public +int kpToolWidgetBase::defaultSelectedRow () const +{ + return defaultSelectedRowAndCol ().first; +} + +// public +int kpToolWidgetBase::defaultSelectedCol () const +{ + return defaultSelectedRowAndCol ().second; +} + +// public +void kpToolWidgetBase::saveSelectedAsDefault () const +{ +#if DEBUG_KP_TOOL_WIDGET_BASE + kdDebug () << "kpToolWidgetBase(" << name () + << ")::saveSelectedAsDefault() row=" << m_selectedRow + << " col=" << m_selectedCol << endl; +#endif + + if (!name ()) + return; + + KConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupTools); + KConfigBase *cfg = cfgGroupSaver.config (); + + QString nameString = QString::fromLatin1 (name ()); + cfg->writeEntry (nameString + QString::fromLatin1 (" Row"), m_selectedRow); + cfg->writeEntry (nameString + QString::fromLatin1 (" Col"), m_selectedCol); + cfg->sync (); +} + + +// public +void kpToolWidgetBase::relayoutOptions () +{ +#if DEBUG_KP_TOOL_WIDGET_BASE + kdDebug () << "kpToolWidgetBase::relayoutOptions()" << endl; +#endif + + while (!m_pixmaps.isEmpty () && m_pixmaps.last ().count () == 0) + { + #if DEBUG_KP_TOOL_WIDGET_BASE + kdDebug () << "\tkilling #" << m_pixmaps.count () - 1 << endl; + #endif + m_pixmaps.resize (m_pixmaps.count () - 1); + m_pixmapRects.resize (m_pixmapRects.count () - 1); + m_toolTips.resize (m_toolTips.count () - 1); + } + + if (m_pixmaps.isEmpty ()) + return; + +#if DEBUG_KP_TOOL_WIDGET_BASE + kdDebug () << "\tsurvived killing of empty rows" << endl; + kdDebug () << "\tfinding heights of rows:" << endl; +#endif + + QValueVector <int> maxHeightOfRow (m_pixmaps.count ()); + + for (int r = 0; r < (int) m_pixmaps.count (); r++) + { + for (int c = 0; c < (int) m_pixmaps [r].count (); c++) + { + if (c == 0 || m_pixmaps [r][c].height () > maxHeightOfRow [r]) + maxHeightOfRow [r] = m_pixmaps [r][c].height (); + } + #if DEBUG_KP_TOOL_WIDGET_BASE + kdDebug () << "\t\t" << r << ": " << maxHeightOfRow [r] << endl; + #endif + } + + QValueVector <int> rowYOffset = spreadOutElements (maxHeightOfRow, height ()); +#if DEBUG_KP_TOOL_WIDGET_BASE + kdDebug () << "\tspread out offsets of rows:" << endl; + for (int r = 0; r < (int) rowYOffset.count (); r++) + kdDebug () << "\t\t" << r << ": " << rowYOffset [r] << endl; +#endif + + for (int r = 0; r < (int) m_pixmaps.count (); r++) + { + #if DEBUG_KP_TOOL_WIDGET_BASE + kdDebug () << "\tlaying out row " << r << ":" << endl; + #endif + + QValueVector <int> widths (m_pixmaps [r].count ()); + for (int c = 0; c < (int) m_pixmaps [r].count (); c++) + widths [c] = m_pixmaps [r][c].width (); + #if DEBUG_KP_TOOL_WIDGET_BASE + kdDebug () << "\t\twidths of cols:" << endl; + for (int c = 0; c < (int) m_pixmaps [r].count (); c++) + kdDebug () << "\t\t\t" << c << ": " << widths [c] << endl; + #endif + + QValueVector <int> colXOffset = spreadOutElements (widths, width ()); + #if DEBUG_KP_TOOL_WIDGET_BASE + kdDebug () << "\t\tspread out offsets of cols:" << endl; + for (int c = 0; c < (int) colXOffset.count (); c++) + kdDebug () << "\t\t\t" << c << ": " << colXOffset [c] << endl; + #endif + + for (int c = 0; c < (int) colXOffset.count (); c++) + { + int x = colXOffset [c]; + int y = rowYOffset [r]; + int w, h; + + if (c == (int) colXOffset.count () - 1) + { + if (x + m_pixmaps [r][c].width () >= width ()) + w = m_pixmaps [r][c].width (); + else + w = width () - 1 - x; + } + else + w = colXOffset [c + 1] - x; + + if (r == (int) m_pixmaps.count () - 1) + { + if (y + m_pixmaps [r][c].height () >= height ()) + h = m_pixmaps [r][c].height (); + else + h = height () - 1 - y; + } + else + h = rowYOffset [r + 1] - y; + + m_pixmapRects [r][c] = QRect (x, y, w, h); + + if (!m_toolTips [r][c].isEmpty ()) + QToolTip::add (this, m_pixmapRects [r][c], m_toolTips [r][c]); + } + } + + update (); +} + + +// public +int kpToolWidgetBase::selectedRow () const +{ + return m_selectedRow; +} + +// public +int kpToolWidgetBase::selectedCol () const +{ + return m_selectedCol; +} + +// public +int kpToolWidgetBase::selected () const +{ + if (m_selectedRow < 0 || + m_selectedRow >= (int) m_pixmaps.count () || + m_selectedCol < 0) + { + return -1; + } + + int upto = 0; + for (int y = 0; y < m_selectedRow; y++) + upto += m_pixmaps [y].count (); + + if (m_selectedCol >= (int) m_pixmaps [m_selectedRow].count ()) + return -1; + + upto += m_selectedCol; + + return upto; +} + + +// public +bool kpToolWidgetBase::hasPreviousOption (int *row, int *col) const +{ +#if DEBUG_KP_TOOL_WIDGET_BASE + kdDebug () << "kpToolWidgetBase" << name () + << "::hasPreviousOption() current row=" << m_selectedRow + << " col=" << m_selectedCol + << endl; +#endif + if (row) + *row = -1; + if (col) + *col = -1; + + + if (m_selectedRow < 0 || m_selectedCol < 0) + return false; + + int newRow = m_selectedRow, + newCol = m_selectedCol; + + newCol--; + if (newCol < 0) + { + newRow--; + if (newRow < 0) + return false; + + newCol = m_pixmaps [newRow].count () - 1; + if (newCol < 0) + return false; + } + + + if (row) + *row = newRow; + if (col) + *col = newCol; + + return true; +} + +// public +bool kpToolWidgetBase::hasNextOption (int *row, int *col) const +{ +#if DEBUG_KP_TOOL_WIDGET_BASE + kdDebug () << "kpToolWidgetBase" << name () + << "::hasNextOption() current row=" << m_selectedRow + << " col=" << m_selectedCol + << endl; +#endif + + if (row) + *row = -1; + if (col) + *col = -1; + + + if (m_selectedRow < 0 || m_selectedCol < 0) + return false; + + int newRow = m_selectedRow, + newCol = m_selectedCol; + + newCol++; + if (newCol >= (int) m_pixmaps [newRow].count ()) + { + newRow++; + if (newRow >= (int) m_pixmaps.count ()) + return false; + + newCol = 0; + if (newCol >= (int) m_pixmaps [newRow].count ()) + return false; + } + + + if (row) + *row = newRow; + if (col) + *col = newCol; + + return true; +} + + +// public slot virtual +bool kpToolWidgetBase::setSelected (int row, int col, bool saveAsDefault) +{ +#if DEBUG_KP_TOOL_WIDGET_BASE + kdDebug () << "kpToolWidgetBase::setSelected(row=" << row + << ",col=" << col + << ",saveAsDefault=" << saveAsDefault + << ")" + << endl; +#endif + + if (row < 0 || col < 0 || + row >= (int) m_pixmapRects.count () || col >= (int) m_pixmapRects [row].count ()) + { + #if DEBUG_KP_TOOL_WIDGET_BASE + kdDebug () << "\tout of range" << endl; + #endif + return false; + } + + if (row == m_selectedRow && col == m_selectedCol) + { + #if DEBUG_KP_TOOL_WIDGET_BASE + kdDebug () << "\tNOP" << endl; + #endif + + if (saveAsDefault) + saveSelectedAsDefault (); + + return true; + } + + const int wasSelectedRow = m_selectedRow; + const int wasSelectedCol = m_selectedCol; + + m_selectedRow = row, m_selectedCol = col; + + if (wasSelectedRow >= 0 && wasSelectedCol >= 0) + { + // unhighlight old option + update (m_pixmapRects [wasSelectedRow][wasSelectedCol]); + } + + // highlight new option + update (m_pixmapRects [row][col]); + +#if DEBUG_KP_TOOL_WIDGET_BASE + kdDebug () << "\tOK" << endl; +#endif + + if (saveAsDefault) + saveSelectedAsDefault (); + + emit optionSelected (row, col); + return true; +} + +// public slot +bool kpToolWidgetBase::setSelected (int row, int col) +{ + return setSelected (row, col, true/*set as default*/); +} + + +// public slot +bool kpToolWidgetBase::selectPreviousOption () +{ + int newRow, newCol; + if (!hasPreviousOption (&newRow, &newCol)) + return false; + + return setSelected (newRow, newCol); +} + +// public slot +bool kpToolWidgetBase::selectNextOption () +{ + int newRow, newCol; + if (!hasNextOption (&newRow, &newCol)) + return false; + + return setSelected (newRow, newCol); +} + + +// protected virtual [base QWidget] +void kpToolWidgetBase::mousePressEvent (QMouseEvent *e) +{ + e->ignore (); + + if (e->button () != Qt::LeftButton) + return; + + + for (int i = 0; i < (int) m_pixmapRects.count (); i++) + { + for (int j = 0; j < (int) m_pixmapRects [i].count (); j++) + { + if (m_pixmapRects [i][j].contains (e->pos ())) + { + setSelected (i, j); + e->accept (); + return; + } + } + } +} + +// protected virtual [base QFrame] +void kpToolWidgetBase::drawContents (QPainter *painter) +{ +#if DEBUG_KP_TOOL_WIDGET_BASE && 1 + kdDebug () << "kpToolWidgetBase::drawContents(): rect=" << contentsRect () << endl; +#endif + + for (int i = 0; i < (int) m_pixmaps.count (); i++) + { + #if DEBUG_KP_TOOL_WIDGET_BASE && 1 + kdDebug () << "\tRow: " << i << endl; + #endif + + for (int j = 0; j < (int) m_pixmaps [i].count (); j++) + { + QRect rect = m_pixmapRects [i][j]; + QPixmap pixmap = m_pixmaps [i][j]; + + #if DEBUG_KP_TOOL_WIDGET_BASE && 1 + kdDebug () << "\t\tCol: " << j << " rect=" << rect << endl; + #endif + + if (i == m_selectedRow && j == m_selectedCol) + { + painter->fillRect (rect, Qt::blue/*selection color*/); + + if (m_invertSelectedPixmap) + kpEffectInvertCommand::apply (&pixmap); + } + + #if DEBUG_KP_TOOL_WIDGET_BASE && 1 + kdDebug () << "\t\t\tdraw pixmap @ x=" + << rect.x () + (rect.width () - pixmap.width ()) / 2 + << " y=" + << rect.y () + (rect.height () - pixmap.height ()) / 2 + << endl; + + #endif + + painter->drawPixmap (QPoint (rect.x () + (rect.width () - pixmap.width ()) / 2, + rect.y () + (rect.height () - pixmap.height ()) / 2), + pixmap); + } + } +} + +#include <kptoolwidgetbase.moc> diff --git a/kolourpaint/widgets/kptoolwidgetbase.h b/kolourpaint/widgets/kptoolwidgetbase.h new file mode 100644 index 00000000..a23f9a16 --- /dev/null +++ b/kolourpaint/widgets/kptoolwidgetbase.h @@ -0,0 +1,112 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef __kp_tool_widget_base_h__ +#define __kp_tool_widget_base_h__ + +#include <qframe.h> +#include <qpair.h> +#include <qpixmap.h> +#include <qrect.h> +#include <qvaluevector.h> +#include <qwidget.h> + + +class QPainter; + + +// TODO: frame becomes a combobox when its parent kpToolToolBar becomes too small +class kpToolWidgetBase : public QFrame +{ +Q_OBJECT + +public: + kpToolWidgetBase (QWidget *parent, const char *name); // must provide a name for config to work + virtual ~kpToolWidgetBase (); + +public: + void addOption (const QPixmap &pixmap, const QString &toolTip = QString::null); + void startNewOptionRow (); + + // Call this at the end of your constructor. + // If the default row & col could not be read from the config, + // <fallBackRow> & <fallBackCol> are passed to setSelected(). + void finishConstruction (int fallBackRow, int fallBackCol); + +private: + QValueVector <int> spreadOutElements (const QValueVector <int> &sizes, int maxSize); + +public: // (only have to use these if you don't use finishConstruction()) + // (rereads from config file) + QPair <int, int> defaultSelectedRowAndCol () const; + int defaultSelectedRow () const; + int defaultSelectedCol () const; + + void saveSelectedAsDefault () const; + + void relayoutOptions (); + +public: + int selectedRow () const; + int selectedCol () const; + + int selected () const; + + bool hasPreviousOption (int *row = 0, int *col = 0) const; + bool hasNextOption (int *row = 0, int *col = 0) const; + +public slots: + // (returns whether <row> and <col> were in range) + virtual bool setSelected (int row, int col, bool saveAsDefault); + bool setSelected (int row, int col); + + bool selectPreviousOption (); + bool selectNextOption (); + +signals: + void optionSelected (int row, int col); + +protected: + virtual void mousePressEvent (QMouseEvent *e); + virtual void drawContents (QPainter *painter); + + void setInvertSelectedPixmap (bool yes = true) { m_invertSelectedPixmap = yes; } + bool m_invertSelectedPixmap; + + // coulbe be a QFrame or a ComboBox + QWidget *m_baseWidget; + + QValueVector < QValueVector <QPixmap> > m_pixmaps; + QValueVector < QValueVector <QString> > m_toolTips; + + QValueVector < QValueVector <QRect> > m_pixmapRects; + + int m_selectedRow, m_selectedCol; +}; + +#endif // __kp_tool_widget_base_h__ diff --git a/kolourpaint/widgets/kptoolwidgetbrush.cpp b/kolourpaint/widgets/kptoolwidgetbrush.cpp new file mode 100644 index 00000000..046dc8b5 --- /dev/null +++ b/kolourpaint/widgets/kptoolwidgetbrush.cpp @@ -0,0 +1,184 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define DEBUG_KP_TOOL_WIDGET_BRUSH 0 + + +#include <kptoolwidgetbrush.h> + +#include <qbitmap.h> +#include <qpainter.h> + +#include <kdebug.h> +#include <klocale.h> + +#include <kpdefs.h> + + +/* sync: <brushes> */ +static int brushSize [][3] = +{ + {8, 4, 1/*like Pen*/}, + {9, 5, 2}, + {9, 5, 2}, + {9, 5, 2} +}; + +#define BRUSH_SIZE_NUM_COLS (int (sizeof (brushSize [0]) / sizeof (brushSize [0][0]))) +#define BRUSH_SIZE_NUM_ROWS (int (sizeof (brushSize) / sizeof (brushSize [0]))) + +kpToolWidgetBrush::kpToolWidgetBrush (QWidget *parent, const char *name) + : kpToolWidgetBase (parent, name) +{ + setInvertSelectedPixmap (); + + QPixmap *pm = m_brushBitmaps; + + for (int shape = 0; shape < BRUSH_SIZE_NUM_ROWS; shape++) + { + for (int i = 0; i < BRUSH_SIZE_NUM_COLS; i++) + { + int w = (width () - 2/*margin*/ - 2/*spacing*/) / BRUSH_SIZE_NUM_COLS; + int h = (height () - 2/*margin*/ - 3/*spacing*/) / BRUSH_SIZE_NUM_ROWS; + pm->resize ((w <= 0 ? width () : w), + (h <= 0 ? height () : h)); + + const int s = brushSize [shape][i]; + QRect rect; + + if (s >= pm->width () || s >= pm->height ()) + rect = QRect (0, 0, pm->width (), pm->height ()); + else + { + rect = QRect ((pm->width () - s) / 2, + (pm->height () - s) / 2, + s, + s); + } + + #if DEBUG_KP_TOOL_WIDGET_BRUSH + kdDebug () << "kpToolWidgetBrush::kpToolWidgetBrush() rect=" << rect << endl; + #endif + + pm->fill (Qt::white); + + QPainter painter (pm); + painter.setPen (Qt::black); + painter.setBrush (Qt::black); + + // sync: <brushes> + switch (shape) + { + case 0: + painter.drawEllipse (rect); + break; + case 1: + painter.drawRect (rect); + break; + case 2: + painter.drawLine (rect.topRight (), rect.bottomLeft ()); + break; + case 3: + painter.drawLine (rect.topLeft (), rect.bottomRight ()); + break; + } + painter.end (); + + pm->setMask (pm->createHeuristicMask ()); + addOption (*pm, brushName (shape, i)/*tooltip*/); + + pm++; + } + + startNewOptionRow (); + } + + finishConstruction (0, 0); +} + +kpToolWidgetBrush::~kpToolWidgetBrush () +{ +} + + +// private +QString kpToolWidgetBrush::brushName (int shape, int whichSize) +{ + int s = brushSize [shape][whichSize]; + + if (s == 1) + return i18n ("1x1"); + + QString shapeName; + + // sync: <brushes> + switch (shape) + { + case 0: + shapeName = i18n ("Circle"); + break; + case 1: + shapeName = i18n ("Square"); + break; + case 2: + // TODO: is this really the name of a shape? :) + shapeName = i18n ("Slash"); + break; + case 3: + // TODO: is this really the name of a shape? :) + shapeName = i18n ("Backslash"); + break; + } + + if (shapeName.isEmpty ()) + return QString::null; + + return i18n ("%1x%2 %3").arg (s).arg (s).arg (shapeName); +} + +QPixmap kpToolWidgetBrush::brush () const +{ + return m_brushBitmaps [selectedRow () * BRUSH_SIZE_NUM_COLS + selectedCol ()]; +} + +bool kpToolWidgetBrush::brushIsDiagonalLine () const +{ + // sync: <brushes> + return (selectedRow () >= 2); +} + +// virtual protected slot [base kpToolWidgetBase] +bool kpToolWidgetBrush::setSelected (int row, int col, bool saveAsDefault) +{ + const bool ret = kpToolWidgetBase::setSelected (row, col, saveAsDefault); + if (ret) + emit brushChanged (brush (), brushIsDiagonalLine ()); + return ret; +} + +#include <kptoolwidgetbrush.moc> diff --git a/kolourpaint/widgets/kptoolwidgetbrush.h b/kolourpaint/widgets/kptoolwidgetbrush.h new file mode 100644 index 00000000..db222e79 --- /dev/null +++ b/kolourpaint/widgets/kptoolwidgetbrush.h @@ -0,0 +1,61 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef __kptoolwidgetbrush_h__ +#define __kptoolwidgetbrush_h__ + +#include <qpixmap.h> + +#include <kptoolwidgetbase.h> + +class kpToolWidgetBrush : public kpToolWidgetBase +{ +Q_OBJECT + +public: + kpToolWidgetBrush (QWidget *parent, const char *name); + virtual ~kpToolWidgetBrush (); + +private: + QString brushName (int shape, int whichSize); + +public: + QPixmap brush () const; + bool brushIsDiagonalLine () const; + +signals: + void brushChanged (const QPixmap &pixmap, bool isDiagonalLine); + +protected slots: + virtual bool setSelected (int row, int col, bool saveAsDefault); + +private: + QPixmap m_brushBitmaps [16]; +}; + +#endif // __kptoolwidgetbrush_h__ diff --git a/kolourpaint/widgets/kptoolwidgeterasersize.cpp b/kolourpaint/widgets/kptoolwidgeterasersize.cpp new file mode 100644 index 00000000..cc58c0d1 --- /dev/null +++ b/kolourpaint/widgets/kptoolwidgeterasersize.cpp @@ -0,0 +1,161 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define DEBUG_KP_TOOL_WIDGET_ERASER_SIZE 0 + + +#include <kptoolwidgeterasersize.h> + +#include <qbitmap.h> +#include <qpainter.h> + +#include <kdebug.h> +#include <klocale.h> + +#include <kpcolor.h> +#include <kptool.h> + + +static int eraserSizes [] = {2, 3, 5, 9, 17, 29}; +static const int numEraserSizes = int (sizeof (eraserSizes) / sizeof (eraserSizes [0])); + + +kpToolWidgetEraserSize::kpToolWidgetEraserSize (QWidget *parent, const char *name) + : kpToolWidgetBase (parent, name) +{ + setInvertSelectedPixmap (); + + m_cursorPixmaps = new QPixmap [numEraserSizes]; + QPixmap *cursorPixmap = m_cursorPixmaps; + + for (int i = 0; i < numEraserSizes; i++) + { + if (i == 3 || i == 5) + startNewOptionRow (); + + int s = eraserSizes [i]; + + cursorPixmap->resize (s, s); + cursorPixmap->fill (Qt::black); + + + QPixmap previewPixmap (s, s); + if (i < 3) + { + // HACK: kpToolWidgetBase's layout code sucks and gives uneven spacing + previewPixmap.resize ((width () - 4) / 3, 9); + } + + QPainter painter (&previewPixmap); + QRect rect ((previewPixmap.width () - s) / 2, (previewPixmap.height () - s) / 2, s, s); + painter.fillRect (rect, Qt::black); + painter.end (); + + QBitmap mask (previewPixmap.width (), previewPixmap.height ()); + mask.fill (Qt::color0/*transparent*/); + + QPainter maskPainter (&mask); + maskPainter.fillRect (rect, Qt::color1/*opaque*/); + maskPainter.end (); + + previewPixmap.setMask (mask); + + + addOption (previewPixmap, i18n ("%1x%2").arg (s).arg (s)/*tooltip*/); + + + cursorPixmap++; + } + + finishConstruction (1, 0); +} + +kpToolWidgetEraserSize::~kpToolWidgetEraserSize () +{ + delete [] m_cursorPixmaps; +} + +int kpToolWidgetEraserSize::eraserSize () const +{ + return eraserSizes [selected ()]; +} + +QPixmap kpToolWidgetEraserSize::cursorPixmap (const kpColor &color) const +{ +#if DEBUG_KP_TOOL_WIDGET_ERASER_SIZE + kdDebug () << "kpToolWidgetEraseSize::cursorPixmap() selected=" << selected () + << " numEraserSizes=" << numEraserSizes + << endl; +#endif + + // TODO: why are we even storing m_cursorPixmaps? + QPixmap pixmap = m_cursorPixmaps [selected ()]; + if (color.isOpaque ()) + pixmap.fill (color.toQColor ()); + + + bool showBorder = (pixmap.width () > 2 && pixmap.height () > 2); + + if (showBorder) + { + QPainter painter (&pixmap); + painter.setPen (Qt::black); + painter.drawRect (pixmap.rect ()); + } + + + if (color.isTransparent ()) + { + QBitmap maskBitmap (pixmap.width (), pixmap.height ()); + maskBitmap.fill (Qt::color0/*transparent*/); + + + if (showBorder) + { + QPainter maskBitmapPainter (&maskBitmap); + maskBitmapPainter.setPen (Qt::color1/*opaque*/); + maskBitmapPainter.drawRect (maskBitmap.rect ()); + } + + + pixmap.setMask (maskBitmap); + } + + + return pixmap; +} + +// virtual protected slot [base kpToolWidgetBase] +bool kpToolWidgetEraserSize::setSelected (int row, int col, bool saveAsDefault) +{ + const bool ret = kpToolWidgetBase::setSelected (row, col, saveAsDefault); + if (ret) + emit eraserSizeChanged (eraserSize ()); + return ret; +} + +#include <kptoolwidgeterasersize.moc> diff --git a/kolourpaint/widgets/kptoolwidgeterasersize.h b/kolourpaint/widgets/kptoolwidgeterasersize.h new file mode 100644 index 00000000..71093fd6 --- /dev/null +++ b/kolourpaint/widgets/kptoolwidgeterasersize.h @@ -0,0 +1,59 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef __kptoolwidgeterasersize_h__ +#define __kptoolwidgeterasersize_h__ + +#include <qpixmap.h> +#include <kptoolwidgetbase.h> + + +class kpColor; + +class kpToolWidgetEraserSize : public kpToolWidgetBase +{ +Q_OBJECT + +public: + kpToolWidgetEraserSize (QWidget *parent, const char *name); + virtual ~kpToolWidgetEraserSize (); + + int eraserSize () const; + QPixmap cursorPixmap (const kpColor &color) const; + +signals: + void eraserSizeChanged (int size); + +protected slots: + virtual bool setSelected (int row, int col, bool saveAsDefault); + +private: + QPixmap *m_cursorPixmaps; +}; + +#endif // __kptoolwidgeterasersize_h__ diff --git a/kolourpaint/widgets/kptoolwidgetfillstyle.cpp b/kolourpaint/widgets/kptoolwidgetfillstyle.cpp new file mode 100644 index 00000000..74c174ce --- /dev/null +++ b/kolourpaint/widgets/kptoolwidgetfillstyle.cpp @@ -0,0 +1,222 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define DEBUG_KP_TOOL_WIDGET_FILL_STYLE 0 + + +#include <kptoolwidgetfillstyle.h> + +#include <qbitmap.h> +#include <qbrush.h> +#include <qpainter.h> + +#include <kdebug.h> +#include <klocale.h> + +#include <kpcolor.h> +#include <kpdefs.h> +#include <kptool.h> + + +kpToolWidgetFillStyle::kpToolWidgetFillStyle (QWidget *parent, const char *name) + : kpToolWidgetBase (parent, name) +{ + setInvertSelectedPixmap (); + + for (int i = 0; i < (int) FillStyleNum; i++) + { + QPixmap pixmap; + + pixmap = fillStylePixmap ((FillStyle) i, + (width () - 2/*margin*/) * 3 / 4, + (height () - 2/*margin*/ - 2/*spacing*/) * 3 / (3 * 4)); + addOption (pixmap, fillStyleName ((FillStyle) i)/*tooltip*/); + + startNewOptionRow (); + } + + finishConstruction (0, 0); +} + +kpToolWidgetFillStyle::~kpToolWidgetFillStyle () +{ +} + + +// private +QPixmap kpToolWidgetFillStyle::fillStylePixmap (FillStyle fs, int w, int h) +{ + QPixmap pixmap ((w <= 0 ? width () : w), (h <= 0 ? height () : h)); + pixmap.fill (Qt::white); + + QPainter painter (&pixmap); + + painter.setPen (QPen (Qt::black, 2)); + painter.setBrush (brushForFillStyle (fs, + kpColor (Qt::black.rgb ())/*foreground*/, + kpColor (Qt::gray.rgb ())/*background*/)); + + painter.drawRect (2, 2, w - 3, h - 3); + + painter.end (); + + + QBitmap mask (pixmap.width (), pixmap.height ()); + mask.fill (Qt::color0); + + painter.begin (&mask); + painter.setPen (QPen (Qt::color1, 2)); + + if (fs == FillWithBackground || fs == FillWithForeground) + painter.setBrush (Qt::color1); + + painter.drawRect (2, 2, w - 3, h - 3); + + painter.end (); + + pixmap.setMask (mask); + + return pixmap; +} + +// private +QString kpToolWidgetFillStyle::fillStyleName (FillStyle fs) const +{ + // do not complain about the "useless" breaks + // as the return statements might not be return statements one day + + switch (fs) + { + case NoFill: + return i18n ("No Fill"); + break; + case FillWithBackground: + return i18n ("Fill with Background Color"); + break; + case FillWithForeground: + return i18n ("Fill with Foreground Color"); + break; + default: + return QString::null; + break; + } +} + + +// public +kpToolWidgetFillStyle::FillStyle kpToolWidgetFillStyle::fillStyle () const +{ +#if DEBUG_KP_TOOL_WIDGET_FILL_STYLE + kdDebug () << "kpToolWidgetFillStyle::fillStyle() selected=" + << selectedRow () + << endl; +#endif + return (FillStyle) selectedRow (); +} + +// public static +QBrush kpToolWidgetFillStyle::maskBrushForFillStyle (FillStyle fs, + const kpColor &foregroundColor, + const kpColor &backgroundColor) +{ + // do not complain about the "useless" breaks + // as the return statements might not be return statements one day + + switch (fs) + { + case NoFill: + return Qt::NoBrush; + break; + case FillWithBackground: + return QBrush (backgroundColor.maskColor ()); + break; + case FillWithForeground: + return QBrush (foregroundColor.maskColor ()); + break; + default: + return Qt::NoBrush; + break; + } +} + +QBrush kpToolWidgetFillStyle::maskBrush (const kpColor &foregroundColor, + const kpColor &backgroundColor) +{ + return maskBrushForFillStyle (fillStyle (), foregroundColor, backgroundColor); +} + +// public static +QBrush kpToolWidgetFillStyle::brushForFillStyle (FillStyle fs, + const kpColor &foregroundColor, + const kpColor &backgroundColor) +{ + // do not complain about the "useless" breaks + // as the return statements might not be return statements one day + + // sync: kptoolpolygon.cpp pixmap() + + switch (fs) + { + case NoFill: + return Qt::NoBrush; + break; + case FillWithBackground: + if (backgroundColor.isOpaque ()) + return QBrush (backgroundColor.toQColor ()); + else + return Qt::NoBrush; + break; + case FillWithForeground: + if (foregroundColor.isOpaque ()) + return QBrush (foregroundColor.toQColor ()); + else + return Qt::NoBrush; + break; + default: + return Qt::NoBrush; + break; + } +} + +// public +QBrush kpToolWidgetFillStyle::brush (const kpColor &foregroundColor, + const kpColor &backgroundColor) +{ + return brushForFillStyle (fillStyle (), foregroundColor, backgroundColor); +} + + +// virtual protected slot [base kpToolWidgetBase] +bool kpToolWidgetFillStyle::setSelected (int row, int col, bool saveAsDefault) +{ + const bool ret = kpToolWidgetBase::setSelected (row, col, saveAsDefault); + if (ret) + emit fillStyleChanged (fillStyle ()); + return ret; +} + +#include <kptoolwidgetfillstyle.moc> diff --git a/kolourpaint/widgets/kptoolwidgetfillstyle.h b/kolourpaint/widgets/kptoolwidgetfillstyle.h new file mode 100644 index 00000000..219d47f2 --- /dev/null +++ b/kolourpaint/widgets/kptoolwidgetfillstyle.h @@ -0,0 +1,80 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef __kptoolwidgetfillstyle_h__ +#define __kptoolwidgetfillstyle_h__ + +#include <kptoolwidgetbase.h> + +class QBrush; + +class kpColor; + +class kpToolWidgetFillStyle : public kpToolWidgetBase +{ +Q_OBJECT + +public: + kpToolWidgetFillStyle (QWidget *parent, const char *name); + virtual ~kpToolWidgetFillStyle (); + + enum FillStyle + { + NoFill, + FillWithBackground, + FillWithForeground, + FillStyleNum /* not (a valid FillStyle) */ + }; + +private: + QPixmap fillStylePixmap (FillStyle fs, int width, int height); + QString fillStyleName (FillStyle fs) const; + +public: + FillStyle fillStyle () const; + + static QBrush maskBrushForFillStyle (FillStyle fs, + const kpColor &foregroundColor, + const kpColor &backgroundColor); + QBrush maskBrush (const kpColor &foregroundColor, + const kpColor &backgroundColor); + + static QBrush brushForFillStyle (FillStyle fs, + const kpColor &foregroundColor, + const kpColor &backgroundColor); + QBrush brush (const kpColor &foregroundColor, + const kpColor &backgroundColor); + +signals: + void fillStyleChanged (kpToolWidgetFillStyle::FillStyle fillStyle); + +protected slots: + virtual bool setSelected (int row, int col, bool saveAsDefault); +}; + +#endif // __kptoolwidgetfillstyle_h__ diff --git a/kolourpaint/widgets/kptoolwidgetlinewidth.cpp b/kolourpaint/widgets/kptoolwidgetlinewidth.cpp new file mode 100644 index 00000000..27e34ecb --- /dev/null +++ b/kolourpaint/widgets/kptoolwidgetlinewidth.cpp @@ -0,0 +1,97 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include <kptoolwidgetlinewidth.h> + +#include <qbitmap.h> +#include <qpainter.h> + +#include <klocale.h> + + +static int lineWidths [] = {1, 2, 3, 5, 8}; + +kpToolWidgetLineWidth::kpToolWidgetLineWidth (QWidget *parent, const char *name) + : kpToolWidgetBase (parent, name) +{ + setInvertSelectedPixmap (); + + int numLineWidths = sizeof (lineWidths) / sizeof (lineWidths [0]); + + int w = (width () - 2/*margin*/) * 3 / 4; + int h = (height () - 2/*margin*/ - (numLineWidths - 1)/*spacing*/) * 3 / (numLineWidths * 4); + + for (int i = 0; i < numLineWidths; i++) + { + QPixmap pixmap ((w <= 0 ? width () : w), + (h <= 0 ? height () : h)); + pixmap.fill (Qt::white); + + QBitmap maskBitmap (pixmap.width (), pixmap.height ()); + maskBitmap.fill (Qt::color0/*transparent*/); + + + QPainter painter (&pixmap), maskPainter (&maskBitmap); + painter.setPen (Qt::black), maskPainter.setPen (Qt::color1/*opaque*/); + painter.setBrush (Qt::black), maskPainter.setBrush (Qt::color1/*opaque*/); + + QRect rect = QRect (0, (pixmap.height () - lineWidths [i]) / 2, + pixmap.width (), lineWidths [i]); + painter.drawRect (rect), maskPainter.drawRect (rect); + + painter.end (), maskPainter.end (); + + + pixmap.setMask (maskBitmap); + + addOption (pixmap, QString::number (lineWidths [i])); + startNewOptionRow (); + } + + finishConstruction (0, 0); +} + +kpToolWidgetLineWidth::~kpToolWidgetLineWidth () +{ +} + +int kpToolWidgetLineWidth::lineWidth () const +{ + return lineWidths [selectedRow ()]; +} + +// virtual protected slot [base kpToolWidgetBase] +bool kpToolWidgetLineWidth::setSelected (int row, int col, bool saveAsDefault) +{ + const bool ret = kpToolWidgetBase::setSelected (row, col, saveAsDefault); + if (ret) + emit lineWidthChanged (lineWidth ()); + return ret; +} + +#include <kptoolwidgetlinewidth.moc> diff --git a/kolourpaint/widgets/kptoolwidgetlinewidth.h b/kolourpaint/widgets/kptoolwidgetlinewidth.h new file mode 100644 index 00000000..3255e443 --- /dev/null +++ b/kolourpaint/widgets/kptoolwidgetlinewidth.h @@ -0,0 +1,51 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef __kptoolwidgetlinewidth_h__ +#define __kptoolwidgetlinewidth_h__ + +#include <kptoolwidgetbase.h> + +class kpToolWidgetLineWidth : public kpToolWidgetBase +{ +Q_OBJECT + +public: + kpToolWidgetLineWidth (QWidget *parent, const char *name); + virtual ~kpToolWidgetLineWidth (); + + int lineWidth () const; + +signals: + void lineWidthChanged (int width); + +protected slots: + virtual bool setSelected (int row, int col, bool saveAsDefault); +}; + +#endif // __kptoolwidgetlinewidth_h__ diff --git a/kolourpaint/widgets/kptoolwidgetopaqueortransparent.cpp b/kolourpaint/widgets/kptoolwidgetopaqueortransparent.cpp new file mode 100644 index 00000000..41b55d0f --- /dev/null +++ b/kolourpaint/widgets/kptoolwidgetopaqueortransparent.cpp @@ -0,0 +1,100 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define DEBUG_KP_TOOL_WIDGET_OPAQUE_OR_TRANSPARENT 0 + + +#include <kptoolwidgetopaqueortransparent.h> + +#include <kdebug.h> +#include <kiconloader.h> +#include <klocale.h> + + +kpToolWidgetOpaqueOrTransparent::kpToolWidgetOpaqueOrTransparent (QWidget *parent, const char *name) + : kpToolWidgetBase (parent, name) +{ + setInvertSelectedPixmap (false); + + addOption (UserIcon ("option_opaque"), i18n ("Opaque")/*tooltip*/); + startNewOptionRow (); + addOption (UserIcon ("option_transparent"), i18n ("Transparent")/*tooltip*/); + + finishConstruction (0, 0); +} + +kpToolWidgetOpaqueOrTransparent::~kpToolWidgetOpaqueOrTransparent () +{ +} + + +// public +bool kpToolWidgetOpaqueOrTransparent::isOpaque () const +{ + return (selected () == 0); +} + +// public +bool kpToolWidgetOpaqueOrTransparent::isTransparent () const +{ + return (!isOpaque ()); +} + +// public +void kpToolWidgetOpaqueOrTransparent::setOpaque (bool yes) +{ +#if DEBUG_KP_TOOL_WIDGET_OPAQUE_OR_TRANSPARENT && 1 + kdDebug () << "kpToolWidgetOpaqueOrTransparent::setOpaque(" << yes << ")" << endl; +#endif + setSelected (yes ? 0 : 1, 0, false/*don't save*/); +} + +// public +void kpToolWidgetOpaqueOrTransparent::setTransparent (bool yes) +{ +#if DEBUG_KP_TOOL_WIDGET_OPAQUE_OR_TRANSPARENT && 1 + kdDebug () << "kpToolWidgetOpaqueOrTransparent::setTransparent(" << yes << ")" << endl; +#endif + setSelected (yes ? 1 : 0, 0, false/*don't save*/); +} + + +// protected slot virtual [base kpToolWidgetBase] +bool kpToolWidgetOpaqueOrTransparent::setSelected (int row, int col, bool saveAsDefault) +{ +#if DEBUG_KP_TOOL_WIDGET_OPAQUE_OR_TRANSPARENT && 1 + kdDebug () << "kpToolWidgetOpaqueOrTransparent::setSelected(" + << row << "," << col << ")" << endl; +#endif + const bool ret = kpToolWidgetBase::setSelected (row, col, saveAsDefault); + if (ret) + emit isOpaqueChanged (isOpaque ()); + return ret; +} + + +#include <kptoolwidgetopaqueortransparent.moc> diff --git a/kolourpaint/widgets/kptoolwidgetopaqueortransparent.h b/kolourpaint/widgets/kptoolwidgetopaqueortransparent.h new file mode 100644 index 00000000..c24cd308 --- /dev/null +++ b/kolourpaint/widgets/kptoolwidgetopaqueortransparent.h @@ -0,0 +1,56 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef __kp_tool_widget_opaque_or_transparent_h__ +#define __kp_tool_widget_opaque_or_transparent_h__ + + +#include <kptoolwidgetbase.h> + +class kpToolWidgetOpaqueOrTransparent : public kpToolWidgetBase +{ +Q_OBJECT + +public: + kpToolWidgetOpaqueOrTransparent (QWidget *parent, const char *name); + virtual ~kpToolWidgetOpaqueOrTransparent (); + + bool isOpaque () const; + bool isTransparent () const; + void setOpaque (bool yes = true); + void setTransparent (bool yes = true); + +signals: + void isOpaqueChanged (bool isOpaque_); + +protected slots: + virtual bool setSelected (int row, int col, bool saveAsDefault); +}; + + +#endif // kp_tool_widget_opaque_or_transparent_h__ diff --git a/kolourpaint/widgets/kptoolwidgetspraycansize.cpp b/kolourpaint/widgets/kptoolwidgetspraycansize.cpp new file mode 100644 index 00000000..161e5015 --- /dev/null +++ b/kolourpaint/widgets/kptoolwidgetspraycansize.cpp @@ -0,0 +1,119 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#define DEBUG_KP_TOOL_WIDGET_SPRAYCAN_SIZE 0 + + +#include <kptoolwidgetspraycansize.h> + +#include <qbitmap.h> +#include <qimage.h> +#include <qpainter.h> + +#include <kdebug.h> +#include <kiconloader.h> +#include <klocale.h> + +#include <kppixmapfx.h> + + +static int spraycanSizes [] = {9, 17, 29}; + +kpToolWidgetSpraycanSize::kpToolWidgetSpraycanSize (QWidget *parent, const char *name) + : kpToolWidgetBase (parent, name) +{ +#if DEBUG_KP_TOOL_WIDGET_SPRAYCAN_SIZE + kdDebug () << "kpToolWidgetSpraycanSize::kpToolWidgetSpraycanSize() CALLED!" << endl; +#endif + + for (int i = 0; i < int (sizeof (spraycanSizes) / sizeof (spraycanSizes [0])); i++) + { + int s = spraycanSizes [i]; + QString iconName = QString ("tool_spraycan_%1x%1").arg (s).arg(s); + + #if DEBUG_KP_TOOL_WIDGET_SPRAYCAN_SIZE + kdDebug () << "\ticonName=" << iconName << endl; + #endif + + QPixmap pixmap (s, s); + pixmap.fill (Qt::white); + + QPainter painter (&pixmap); + painter.drawPixmap (0, 0, UserIcon (iconName)); + painter.end (); + + QImage image = kpPixmapFX::convertToImage (pixmap); + + QBitmap mask (pixmap.width (), pixmap.height ()); + mask.fill (Qt::color0); + + painter.begin (&mask); + painter.setPen (Qt::color1); + + for (int y = 0; y < image.height (); y++) + { + for (int x = 0; x < image.width (); x++) + { + if ((image.pixel (x, y) & RGB_MASK) == 0/*black*/) + painter.drawPoint (x, y); // mark as opaque + } + } + + painter.end (); + + pixmap.setMask (mask); + + addOption (pixmap, i18n ("%1x%2").arg (s).arg (s)/*tooltip*/); + if (i == 1) + startNewOptionRow (); + } + + finishConstruction (0, 0); +} + +kpToolWidgetSpraycanSize::~kpToolWidgetSpraycanSize () +{ +} + + +// public +int kpToolWidgetSpraycanSize::spraycanSize () const +{ + return spraycanSizes [selected ()]; +} + +// protected slot virtual [base kpToolWidgetBase] +bool kpToolWidgetSpraycanSize::setSelected (int row, int col, bool saveAsDefault) +{ + const bool ret = kpToolWidgetBase::setSelected (row, col, saveAsDefault); + if (ret) + emit spraycanSizeChanged (spraycanSize ()); + return ret; +} + +#include <kptoolwidgetspraycansize.moc> diff --git a/kolourpaint/widgets/kptoolwidgetspraycansize.h b/kolourpaint/widgets/kptoolwidgetspraycansize.h new file mode 100644 index 00000000..b4233a80 --- /dev/null +++ b/kolourpaint/widgets/kptoolwidgetspraycansize.h @@ -0,0 +1,51 @@ + +/* + Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org> + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#ifndef __kptoolwidgetspraycansize_h__ +#define __kptoolwidgetspraycansize_h__ + +#include <kptoolwidgetbase.h> + +class kpToolWidgetSpraycanSize : public kpToolWidgetBase +{ +Q_OBJECT + +public: + kpToolWidgetSpraycanSize (QWidget *parent, const char *name); + virtual ~kpToolWidgetSpraycanSize (); + + int spraycanSize () const; + +signals: + void spraycanSizeChanged (int size); + +protected slots: + virtual bool setSelected (int row, int col, bool saveAsDefault); +}; + +#endif // __kptoolwidgetspraycansize_h__ |