diff --git a/libs/ui/widgets/kis_color_label_button.cpp b/libs/ui/widgets/kis_color_label_button.cpp index 8615e34059..d31d856d63 100644 --- a/libs/ui/widgets/kis_color_label_button.cpp +++ b/libs/ui/widgets/kis_color_label_button.cpp @@ -1,247 +1,257 @@ /* * Copyright (c) 2020 Eoin O'Neill * Copyright (c) 2020 Emmet O'Neill * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_color_label_button.h" #include #include #include #include "kis_global.h" #include "kis_debug.h" #include "krita_container_utils.h" struct KisColorLabelButton::Private { const QColor m_color; const uint m_sizeSquared; + KisColorLabelButton::SelectionIndicationType selectionVis; Private(QColor color, uint sizeSquared) : m_color(color) , m_sizeSquared(sizeSquared) + , selectionVis(KisColorLabelButton::FillIn) { } Private(const Private& rhs) : m_color(rhs.m_color) , m_sizeSquared(rhs.m_sizeSquared) { } }; KisColorLabelButton::KisColorLabelButton(QColor color, uint sizeSquared, QWidget *parent) : QAbstractButton(parent), m_d(new Private(color, sizeSquared)) { setCheckable(true); setChecked(true); setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); } KisColorLabelButton::~KisColorLabelButton() {} void KisColorLabelButton::paintEvent(QPaintEvent *event) { QWidget::paintEvent(event); QStylePainter painter(this); QStyleOption styleOption; styleOption.initFrom(this); if (isDown() || isChecked()){ styleOption.state |= QStyle::State_On; } // Draw fill.. QRect fillRect = kisGrowRect(rect(), -2); QRect outlineRect = kisGrowRect(fillRect, -1); if (!isEnabled()) { fillRect -= QMargins(sizeHint().width() / 4, sizeHint().height() / 4, sizeHint().width() / 4, sizeHint().height() / 4); } else { fillRect = kisGrowRect(fillRect, -3); } fillRect.width(); if (m_d->m_color.alpha() > 0) { QColor fillColor = m_d->m_color; - if (!isChecked() || !isEnabled()) { + if ((!isChecked() || !isEnabled()) && (m_d->selectionVis == FillIn)) { fillColor.setAlpha(32); } QBrush brush = QBrush(fillColor); painter.fillRect(fillRect, brush); - if (isEnabled()) { + if ((isEnabled() && (m_d->selectionVis == FillIn)) || + (isChecked() && (m_d->selectionVis == Outline))) { painter.setPen(QPen(m_d->m_color, 2)); painter.drawRect(outlineRect); } } else { // draw an X for no color for the first item /*const int shortestEdge = std::min(fillRect.width(), fillRect.height()); const int longestEdge = std::max(fillRect.width(), fillRect.height()); bool horizontalIsShortest = (shortestEdge == fillRect.width()); QRect srcRect = horizontalIsShortest ? fillRect.adjusted(0, (longestEdge / 2) - (shortestEdge / 2), 0, (shortestEdge / 2) - (longestEdge / 2)) : fillRect.adjusted((longestEdge / 2) - (shortestEdge / 2), 0, (shortestEdge / 2) - (longestEdge / 2), 0); QRect crossRect = kisGrowRect(srcRect, -1); QColor shade = styleOption.palette.text().color(); if (!isChecked() || !isEnabled()) { shade.setAlpha(64); } QPen pen = QPen(shade, 2); painter.setPen(pen); painter.drawLine(crossRect.topLeft(), crossRect.bottomRight()); painter.drawLine(crossRect.bottomLeft(), crossRect.topRight());*/ QColor white = QColor(255,255,255); - QColor grey = QColor(220,220,220); + QColor grey = QColor(200,200,200); QColor outlineColor = grey; - if (!isChecked() || !isEnabled()) { + if ((!isChecked() || !isEnabled()) && (m_d->selectionVis == FillIn)) { white.setAlpha(32); grey.setAlpha(32); } QBrush whiteBrush = QBrush(white); QBrush greyBrush = QBrush(grey); QRect upperLeftGrey = fillRect - QMargins(0, 0, fillRect.size().width() / 2, fillRect.size().height() /2); QRect lowerRightGrey = fillRect - QMargins(fillRect.size().width() / 2, fillRect.size().height() / 2, 0, 0); painter.fillRect(fillRect, whiteBrush); painter.fillRect(upperLeftGrey, greyBrush); painter.fillRect(lowerRightGrey, greyBrush); - if (isEnabled()) { + if ((isEnabled() && (m_d->selectionVis == FillIn)) || + (isChecked() && (m_d->selectionVis == Outline))) { painter.setPen(QPen(outlineColor, 2)); painter.drawRect(outlineRect); } } } QSize KisColorLabelButton::sizeHint() const { return QSize(m_d->m_sizeSquared,m_d->m_sizeSquared); } +void KisColorLabelButton::setSelectionVisType(KisColorLabelButton::SelectionIndicationType type) +{ + m_d->selectionVis = type; +} + void KisColorLabelButton::nextCheckState() { - KisColorLabelFilterGroup* colorLabelButtonGroup = dynamic_cast(group()); - if (colorLabelButtonGroup && (colorLabelButtonGroup->countCheckedViableButtons() > 1 || !isChecked())) { + KisColorLabelFilterGroup* colorLabelFilterGroup = dynamic_cast(group()); + + if (!colorLabelFilterGroup || (colorLabelFilterGroup->countCheckedViableButtons() > 1 || !isChecked())) { setChecked(!isChecked()); } else { setChecked(isChecked()); } } KisColorLabelFilterGroup::KisColorLabelFilterGroup(QObject *parent) : QButtonGroup(parent) { } KisColorLabelFilterGroup::~KisColorLabelFilterGroup() { } QList KisColorLabelFilterGroup::viableButtons() const { QList viableButtons; Q_FOREACH( int index, viableColorLabels ) { viableButtons.append(button(index)); } return viableButtons; } void KisColorLabelFilterGroup::setViableLabels(QSet &labels) { setAllVisibility(false); disableAll(); QSet removed = viableColorLabels.subtract(labels); viableColorLabels = labels; if (viableColorLabels.count() > 1) { setAllVisibility(true); Q_FOREACH( int index, viableColorLabels) { if (button(index)) { button(index)->setEnabled(true); } } } Q_FOREACH( int index, removed ) { button(index)->setChecked(true); } } QSet KisColorLabelFilterGroup::getActiveLabels() const { QSet checkedLabels = QSet(); Q_FOREACH( int index, viableColorLabels ) { if (button(index)->isChecked()) { checkedLabels.insert(index); } } return checkedLabels.count() == viableColorLabels.count() ? QSet() : checkedLabels; } QList KisColorLabelFilterGroup::checkedViableButtons() const { QList checkedButtons = viableButtons(); KritaUtils::filterContainer(checkedButtons, [](QAbstractButton* btn){ return (btn->isChecked()); }); return checkedButtons; } int KisColorLabelFilterGroup::countCheckedViableButtons() const { return checkedViableButtons().count(); } int KisColorLabelFilterGroup::countViableButtons() const { return viableColorLabels.count(); } void KisColorLabelFilterGroup::reset() { Q_FOREACH( QAbstractButton* btn, viableButtons() ) { btn->setChecked(true); } } void KisColorLabelFilterGroup::disableAll() { Q_FOREACH( QAbstractButton* btn, buttons() ) { btn->setDisabled(true); } } void KisColorLabelFilterGroup::setAllVisibility(const bool vis) { Q_FOREACH( QAbstractButton* btn, buttons() ) { btn->setVisible(vis); } } diff --git a/libs/ui/widgets/kis_color_label_button.h b/libs/ui/widgets/kis_color_label_button.h index e5f275e7ec..fc50131e18 100644 --- a/libs/ui/widgets/kis_color_label_button.h +++ b/libs/ui/widgets/kis_color_label_button.h @@ -1,69 +1,75 @@ /* * Copyright (c) 2020 Eoin O'Neill * Copyright (c) 2020 Emmet O'Neill * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KISCOLORLABELBUTTON_H #define KISCOLORLABELBUTTON_H #include #include #include #include "kritaui_export.h" class KRITAUI_EXPORT KisColorLabelButton : public QAbstractButton { Q_OBJECT public: + enum SelectionIndicationType { + FillIn, + Outline + }; + KisColorLabelButton(QColor color, uint sizeSquared = 32, QWidget *parent = nullptr); ~KisColorLabelButton(); void paintEvent(QPaintEvent* event) override; QSize sizeHint() const override; + void setSelectionVisType( SelectionIndicationType type ); virtual void nextCheckState() override; private: struct Private; const QScopedPointer m_d; }; class KRITAUI_EXPORT KisColorLabelFilterGroup : public QButtonGroup { Q_OBJECT public: KisColorLabelFilterGroup(QObject* parent); ~KisColorLabelFilterGroup(); QList viableButtons() const; void setViableLabels(QSet &buttons); QSet getActiveLabels() const; QList checkedViableButtons() const; int countCheckedViableButtons() const; int countViableButtons() const; void reset(); private: void disableAll(); void setAllVisibility(const bool vis); QSet viableColorLabels; }; #endif // KISCOLORLABELBUTTON_H diff --git a/libs/ui/widgets/kis_color_label_selector_widget.cpp b/libs/ui/widgets/kis_color_label_selector_widget.cpp index c27f60783d..481c2355c2 100644 --- a/libs/ui/widgets/kis_color_label_selector_widget.cpp +++ b/libs/ui/widgets/kis_color_label_selector_widget.cpp @@ -1,340 +1,102 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_color_label_selector_widget.h" #include "kis_debug.h" #include "kis_global.h" #include #include #include -#include #include #include -#include -#include - -#include -#include +#include +#include "kis_color_label_button.h" #include "kis_node_view_color_scheme.h" -struct KisColorLabelSelectorWidget::Private +struct Private { Private(KisColorLabelSelectorWidget *_q) - : q(_q), - xMenuOffset(0), - yCenteringOffset(0), - realItemSize(0), - realItemSpacing(0), - hoveringItem(-1), - selectedItem(0) + : q(_q) { } KisColorLabelSelectorWidget *q; QVector colors; - - - const int minHeight = 12 + 4; - const int minSpacing = 1; - const int maxSpacing = 3; - const int border = 2; - - int xMenuOffset; - int yCenteringOffset; - int realItemSize; - int realItemSpacing; - - int hoveringItem; - int selectedItem; - - QRect itemRect(int index) const; - int indexFromPos(const QPoint &pos); - void updateItem(int index); - - int widthForHeight(int height, int spacing) const; - int heightForWidth(int width, int spacing) const; - void updateItemSizes(const QSize &widgetSize); + QButtonGroup* group; }; KisColorLabelSelectorWidget::KisColorLabelSelectorWidget(QWidget *parent) - : QWidget(parent), - m_d(new Private(this)) + : QWidget(parent) + , m_d(new Private(this)) { KisNodeViewColorScheme scm; m_d->colors = scm.allColorLabels(); - setMouseTracking(true); -} - -KisColorLabelSelectorWidget::~KisColorLabelSelectorWidget() -{ -} -int KisColorLabelSelectorWidget::currentIndex() const -{ - return m_d->selectedItem; -} - -void KisColorLabelSelectorWidget::setCurrentIndex(int index) -{ - if (index == m_d->selectedItem) return; + QHBoxLayout *layout = new QHBoxLayout(this); - const int oldItem = m_d->selectedItem; - m_d->selectedItem = index; - m_d->updateItem(oldItem); - m_d->updateItem(m_d->selectedItem); - m_d->hoveringItem = index; + this->setLayout(layout); + layout->setContentsMargins(0,0,0,0); + layout->setAlignment(Qt::AlignCenter); - emit currentIndexChanged(m_d->selectedItem); -} - -QSize KisColorLabelSelectorWidget::minimumSizeHint() const -{ - return QSize(m_d->widthForHeight(m_d->minHeight, m_d->minSpacing), m_d->minHeight); -} - -QSize KisColorLabelSelectorWidget::sizeHint() const -{ - const int preferredHeight = 22 + 2 * m_d->border; - return QSize(m_d->widthForHeight(preferredHeight, m_d->maxSpacing), preferredHeight); -} - -void KisColorLabelSelectorWidget::resizeEvent(QResizeEvent *e) -{ - m_d->xMenuOffset = 0; - - bool hasWideItems = false; - QMenu *menu = qobject_cast(parent()); - if (menu) { - Q_FOREACH(QAction *action, menu->actions()) { - if (action->isCheckable() || - !action->icon().isNull()) { - - hasWideItems = true; - break; - } + { + m_d->group = new QButtonGroup(this); + m_d->group->setExclusive(true); + + for (int id = 0; id < m_d->colors.count(); id++) { + KisColorLabelButton* btn = new KisColorLabelButton(m_d->colors[id], 24, this); + btn->setChecked(false); + btn->setSelectionVisType(KisColorLabelButton::Outline); + m_d->group->addButton(btn, id); + layout->addWidget(btn); } - } - if (hasWideItems) { - QStyleOption opt; - opt.init(this); - // some copy-pasted code from QFusionStyle style - const int hmargin = style()->pixelMetric(QStyle::PM_MenuHMargin, &opt, this); - const int icone = style()->pixelMetric(QStyle::PM_SmallIconSize, &opt, this); - m_d->xMenuOffset = hmargin + icone + 6; + connect(m_d->group, SIGNAL(buttonToggled(int,bool)), this, SLOT(groupButtonChecked(int,bool))); } - - m_d->updateItemSizes(e->size()); - QWidget::resizeEvent(e); -} - -int KisColorLabelSelectorWidget::Private::widthForHeight(int height, int spacing) const -{ - return height * colors.size() + spacing * (colors.size() - 1) + 2 * border + xMenuOffset; } -int KisColorLabelSelectorWidget::Private::heightForWidth(int width, int spacing) const -{ - const int numItems = colors.size(); - return qRound(qreal(width - spacing * (numItems - 1) - 2 * border - xMenuOffset) / numItems); -} - -void KisColorLabelSelectorWidget::Private::updateItemSizes(const QSize &widgetSize) -{ - const int height = qBound(minHeight, - heightForWidth(widgetSize.width(), minSpacing), - widgetSize.height()); - - const int size = height - 2 * border; - const int numItems = colors.size(); - - const int rest = widgetSize.width() - size * numItems - 2 * border - xMenuOffset; - const int spacing = qBound(minSpacing, - rest / (numItems - 1), - maxSpacing); - - realItemSize = size; - realItemSpacing = spacing; - yCenteringOffset = qMax(0, (widgetSize.height() - height) / 2); -} - -QRect KisColorLabelSelectorWidget::Private::itemRect(int index) const -{ - const int x = xMenuOffset + border + index * realItemSize + index * realItemSpacing; - const int y = border + yCenteringOffset; - - return QRect(x, y, realItemSize, realItemSize); -} - -int KisColorLabelSelectorWidget::Private::indexFromPos(const QPoint &pos) +KisColorLabelSelectorWidget::~KisColorLabelSelectorWidget() { - const int x = pos.x() - border - xMenuOffset; - const int y = pos.y() - border - yCenteringOffset; - if (y < 0 || y >= realItemSize || x < 0) return -1; - int idx = (x + realItemSpacing) / (realItemSize + realItemSpacing); - - if (idx < 0 || idx >= colors.size()) { - idx = -1; - } - - return idx; } -void KisColorLabelSelectorWidget::Private::updateItem(int index) +int KisColorLabelSelectorWidget::currentIndex() const { - if (index >= 0 && index < colors.size()) { - q->update(kisGrowRect(itemRect(index), border)); - } + return m_d->group->checkedId(); } -enum State { - NORMAL = 0, - HOVER, - CHECKED, - DISABLED -}; - -void drawToolButton(QWidget *widget, const QRect &rc, State state, const QColor &color, int border) +void KisColorLabelSelectorWidget::groupButtonChecked(int index, bool state) { - QStylePainter p(widget); - QStyleOption opt; - opt.initFrom(widget); - opt.rect = kisGrowRect(rc, border); - - switch (state) { - case DISABLED: - case NORMAL: - opt.state &= ~QStyle::State_Raised; - break; - case HOVER: - opt.state |= QStyle::State_Raised; - break; - case CHECKED: - opt.state |= QStyle::State_On; - break; - }; - - - if (opt.state & (QStyle::State_Sunken | QStyle::State_On | QStyle::State_Raised)) { - - const QRect borderRect = kisGrowRect(rc, 1); - p.setPen(QPen(opt.palette.text().color(), 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); - p.drawRect(borderRect); - } - - const int offset = qMax(1, rc.height() / 10); - const QRect colorBlobRect = kisGrowRect(rc, -offset); - if (color.alpha() > 0) { - QColor fillColor = color; - - if (state == DISABLED) { - fillColor.setHsl(0, 0, color.lightness()); - } - - p.fillRect(colorBlobRect, fillColor); - } else { - - // draw an X for no color for the first item - QRect crossRect = kisGrowRect(colorBlobRect, -offset); - - QColor shade = opt.palette.text().color(); - p.setPen(QPen(shade, 2)); - p.drawLine(crossRect.topLeft(), crossRect.bottomRight()); - p.drawLine(crossRect.bottomLeft(), crossRect.topRight()); + if (state == true) { + emit currentIndexChanged(index); } } -void KisColorLabelSelectorWidget::paintEvent(QPaintEvent *e) +void KisColorLabelSelectorWidget::setCurrentIndex(int index) { - QWidget::paintEvent(e); - if (isEnabled()) { - for (int i = 0; i < m_d->colors.size(); i++) { - if (i == m_d->selectedItem || i == m_d->hoveringItem) { - continue; - } - drawToolButton(this, m_d->itemRect(i), NORMAL, m_d->colors[i], m_d->border); - } - - if (m_d->selectedItem >= 0) { - drawToolButton(this, m_d->itemRect(m_d->selectedItem), CHECKED, m_d->colors[m_d->selectedItem], m_d->border); + if (index != m_d->group->checkedId()) { + QAbstractButton* btn = m_d->group->button(index); + if (btn) { + btn->setChecked(true); } - - if (m_d->hoveringItem >= 0 && m_d->hoveringItem != m_d->selectedItem) { - drawToolButton(this, m_d->itemRect(m_d->hoveringItem), HOVER, m_d->colors[m_d->hoveringItem], m_d->border); - } - } else { - for (int i = 0; i < m_d->colors.size(); i++) { - drawToolButton(this, m_d->itemRect(i), DISABLED, m_d->colors[i], m_d->border); - } - } -} - -void KisColorLabelSelectorWidget::keyPressEvent(QKeyEvent *e) -{ - if (e->key() == Qt::Key_Right || e->key() == Qt::Key_Up) { - int newItem = (m_d->selectedItem + 1) % m_d->colors.size(); - setCurrentIndex(newItem); - } else if (e->key() == Qt::Key_Left || e->key() == Qt::Key_Down) { - int newItem = m_d->selectedItem < 0 ? m_d->colors.size() - 1 : - (m_d->selectedItem + m_d->colors.size() - 1) % m_d->colors.size(); - setCurrentIndex(newItem); } - QWidget::keyPressEvent(e); -} - -void KisColorLabelSelectorWidget::mousePressEvent(QMouseEvent *e) -{ - QWidget::mousePressEvent(e); -} - -void KisColorLabelSelectorWidget::mouseReleaseEvent(QMouseEvent *e) -{ - const int newItem = m_d->indexFromPos(e->pos()); - - if (newItem >= 0 && - (e->button() == Qt::LeftButton || - e->button() == Qt::RightButton)) { - - setCurrentIndex(newItem); - } - QWidget::mouseReleaseEvent(e); -} - -void KisColorLabelSelectorWidget::mouseMoveEvent(QMouseEvent *e) -{ - const int oldItem = m_d->hoveringItem; - m_d->hoveringItem = m_d->indexFromPos(e->pos()); - m_d->updateItem(oldItem); - m_d->updateItem(m_d->hoveringItem); - - update(); - QWidget::mouseMoveEvent(e); -} - -void KisColorLabelSelectorWidget::leaveEvent(QEvent *e) -{ - const int oldItem = m_d->hoveringItem; - m_d->hoveringItem = -1; - m_d->updateItem(oldItem); - QWidget::leaveEvent(e); + emit currentIndexChanged(index); } diff --git a/libs/ui/widgets/kis_color_label_selector_widget.h b/libs/ui/widgets/kis_color_label_selector_widget.h index 4acbb55234..d60dd39aa7 100644 --- a/libs/ui/widgets/kis_color_label_selector_widget.h +++ b/libs/ui/widgets/kis_color_label_selector_widget.h @@ -1,62 +1,49 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_COLOR_LABEL_SELECTOR_WIDGET_H #define __KIS_COLOR_LABEL_SELECTOR_WIDGET_H #include #include #include "kritaui_export.h" class KRITAUI_EXPORT KisColorLabelSelectorWidget : public QWidget { Q_OBJECT public: KisColorLabelSelectorWidget(QWidget *parent); ~KisColorLabelSelectorWidget() override; - QSize minimumSizeHint() const override; - QSize sizeHint() const override; - int currentIndex() const; public Q_SLOTS: + void groupButtonChecked(int index, bool state); void setCurrentIndex(int index); Q_SIGNALS: void currentIndexChanged(int index); -protected: - - void resizeEvent(QResizeEvent *e) override; - void paintEvent(QPaintEvent *e) override; - void keyPressEvent(QKeyEvent *e) override; - void mousePressEvent(QMouseEvent *e) override; - void mouseReleaseEvent(QMouseEvent *e) override; - void mouseMoveEvent(QMouseEvent *e) override; - void leaveEvent(QEvent *e) override; - private: - struct Private; - const QScopedPointer m_d; + class Private* m_d; }; #endif /* __KIS_COLOR_LABEL_SELECTOR_WIDGET_H */