diff --git a/libs/ui/widgets/kis_color_label_button.cpp b/libs/ui/widgets/kis_color_label_button.cpp index 354baf3064..1a9b36c74d 100644 --- a/libs/ui/widgets/kis_color_label_button.cpp +++ b/libs/ui/widgets/kis_color_label_button.cpp @@ -1,372 +1,372 @@ /* * 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 #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()) && (m_d->selectionVis == FillIn)) { fillColor.setAlpha(32); } else if ((!isChecked() || !isEnabled()) && (m_d->selectionVis == Outline)) { fillColor.setAlpha(192); } QBrush brush = QBrush(fillColor); painter.fillRect(fillRect, brush); 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(200,200,200); QColor outlineColor = grey; if ((!isChecked() || !isEnabled()) && (m_d->selectionVis == FillIn)) { white.setAlpha(32); grey.setAlpha(32); } else if ((!isChecked() || !isEnabled()) && (m_d->selectionVis == Outline)) { white.setAlpha(192); grey = QColor(125,125,125,192); } 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() && (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* 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(const 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); } } void KisColorLabelFilterGroup::setViableLabels(const QList &viableLabels) { setViableLabels(QSet::fromList(viableLabels)); } 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); } } KisColorLabelMouseDragFilter::KisColorLabelMouseDragFilter(QObject* parent) : QObject(parent) { lastKnownMousePosition = QPoint(0,0); currentState = Idle; } bool KisColorLabelMouseDragFilter::eventFilter(QObject *obj, QEvent *event) { - if (event->type() == QEvent::MouseButtonPress) { + if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick) { QMouseEvent* mouseEvent = static_cast(event); currentState = WaitingForDragLeave; lastKnownMousePosition = mouseEvent->globalPos(); return true; } else if (event->type() == QEvent::MouseButtonRelease) { QMouseEvent* mouseEvent = static_cast(event); QAbstractButton* startingButton = static_cast(obj); //If we never left, toggle the original button. if( currentState == WaitingForDragLeave ) { if ( startingButton->group() && (mouseEvent->modifiers() & Qt::SHIFT)) { KisColorLabelFilterGroup* const group = static_cast(startingButton->group()); const QList viableCheckedButtons = group->checkedViableButtons(); const int buttonsEnabled = viableCheckedButtons.count(); const bool shouldChangeIsolation = (buttonsEnabled == 1) && (viableCheckedButtons.first() == startingButton); const bool shouldIsolate = (buttonsEnabled != 1) || !shouldChangeIsolation; Q_FOREACH(QAbstractButton* otherBtn, group->viableButtons()) { if (otherBtn == startingButton){ startingButton->setChecked(true); } else { otherBtn->setChecked(!shouldIsolate); } } } else { startingButton->click(); } } currentState = Idle; lastKnownMousePosition = mouseEvent->globalPos(); return true; } else if (event->type() == QEvent::MouseMove) { if (currentState == WaitingForDragLeave) { QMouseEvent* mouseEvent = static_cast(event); QWidget* firstClicked = static_cast(obj); const QPointF localPosition = mouseEvent->localPos(); if (!firstClicked->rect().contains(localPosition.x(), localPosition.y())) { QAbstractButton* btn = static_cast(obj); btn->click(); checkSlideOverNeighborButtons(mouseEvent, btn); currentState = WaitingForDragEnter; } lastKnownMousePosition = mouseEvent->globalPos(); return true; } else if (currentState == WaitingForDragEnter) { QMouseEvent* mouseEvent = static_cast(event); QAbstractButton* startingButton = static_cast(obj); const QPoint currentPosition = mouseEvent->globalPos(); checkSlideOverNeighborButtons(mouseEvent, startingButton); lastKnownMousePosition = currentPosition; return true; } } return false; } void KisColorLabelMouseDragFilter::checkSlideOverNeighborButtons(QMouseEvent* mouseEvent, QAbstractButton* startingButton) { const QPoint currentPosition = mouseEvent->globalPos(); if (startingButton->group()) { QList allButtons = startingButton->group()->buttons(); Q_FOREACH(QAbstractButton* button, allButtons) { const QRect bounds = QRect(button->mapToGlobal(QPoint(0,0)), button->size()); const QPoint upperLeft = QPoint(qMin(lastKnownMousePosition.x(), currentPosition.x()), qMin(lastKnownMousePosition.y(), currentPosition.y())); const QPoint lowerRight = QPoint(qMax(lastKnownMousePosition.x(), currentPosition.x()), qMax(lastKnownMousePosition.y(), currentPosition.y())); const QRect mouseMovement = QRect(upperLeft, lowerRight); if( bounds.intersects(mouseMovement) && !bounds.contains(lastKnownMousePosition)) { button->click(); } } } }