31#include <QTabletEvent>
36#include <klocalizedstring.h>
37#include <ktoggleaction.h>
38#include <kconfiggroup.h>
42#include <QApplication>
44#include <QPainterPath>
126 d->m_viewManager = viewManager;
139 for (
int i = 0; i < data.length(); i++) {
142 connect(
button, &QAbstractButton::clicked,
d->m_selectionManager, buttonData.
slot);
147 d->sapPinButtonIndex = i;
148 button->setCheckable(
true);
153 connect(
d->m_handleWidget, SIGNAL(customContextMenuRequested(QPoint)),
this, SLOT(
showContextMenu(QPoint)));
155 d->disable_action =
new KisAction(i18n(
"Disable selection actions bar"));
166 KConfigGroup cfg = KSharedConfig::openConfig()->group(
"");
167 d->m_dragHandle.dragOffset = cfg.readEntry(
d->dragOffsetConfigName, QPoint(0, 0));
181 if (!selection || !
d->m_enabled || !
d->m_visible) {
185 if (
d->m_viewManager->canvas()) {
190 if (
d->m_pressed &&
d->behavior == Behavior::FreeFloating) {
198 button->draw(painter, displayRendererInterface);
201 if (
d->m_handleWidget->isEnabled()) {
202 d->m_handleWidget->draw(painter, displayRendererInterface);
209 d->orientation = mode;
210 d->m_handleWidget->setOrientation(mode);
214 QWidget *canvasWidget =
dynamic_cast<QWidget *
>(
d->m_viewManager->canvas());
223 if (enabled && !
d->m_handleWidget->isEnabled()) {
224 d->m_handleWidget->setEnabled(enabled);
228 if (!enabled &&
d->m_handleWidget->isEnabled()) {
229 d->m_handleWidget->setEnabled(enabled);
237 QWidget *canvasWidget =
dynamic_cast<QWidget *
>(
d->m_viewManager->canvas());
242 QRect canvasBounds = canvasWidget->rect();
243 QPoint result = QPoint();
245 switch (
d->position) {
247 result.setY(canvasBounds.bottom());
248 result.setX((canvasBounds.width() -
d->m_actionBarWidth) / 2);
251 result.setY(canvasBounds.bottom());
252 result.setX(canvasBounds.left());
255 result.setY(canvasBounds.bottom());
256 result.setX(canvasBounds.right());
259 result.setY((canvasBounds.height() -
d->m_actionBarHeight) / 2);
260 result.setX(canvasBounds.left());
263 result.setY((canvasBounds.height() -
d->m_actionBarHeight) / 2);
264 result.setX(canvasBounds.right());
267 result.setY(canvasBounds.top());
268 result.setX((canvasBounds.width() -
d->m_actionBarWidth) / 2);
271 result.setY(canvasBounds.top());
272 result.setX(canvasBounds.left());
275 result.setY(canvasBounds.top());
276 result.setX(canvasBounds.right());
285 if (!
d->m_handleWidget)
return;
287 if (
d->orientation == Orientation::Horizontal) {
288 d->m_innerActionBarHeight =
d->m_actionBarHeight =
BUTTON_SIZE;
289 d->m_innerActionBarWidth =
d->m_actionBarWidth =
BUTTON_SIZE *
d->m_buttonCount;
290 if (
d->m_handleWidget->isEnabled()) {
291 d->m_innerActionBarWidth =
BUTTON_SIZE * (
d->m_buttonCount - 1);
293 }
else if (
d->orientation == Orientation::Vertical) {
294 d->m_innerActionBarHeight =
d->m_actionBarHeight =
BUTTON_SIZE *
d->m_buttonCount;
295 d->m_innerActionBarWidth =
d->m_actionBarWidth =
BUTTON_SIZE;
296 if (
d->m_handleWidget->isEnabled()) {
297 d->m_innerActionBarHeight =
BUTTON_SIZE * (
d->m_buttonCount - 1);
306 QWidget *canvasWidget =
dynamic_cast<QWidget *
>(
d->m_viewManager->canvas());
311 p_visible &=
d->m_enabled;
313 const bool VISIBILITY_CHANGED =
d->m_visible != p_visible;
314 if (!VISIBILITY_CHANGED) {
318 d->configure_action->setVisible(p_visible &&
d->m_viewManager->selection());
320 if (
d->m_viewManager->selection() && p_visible) {
321 d->m_handleWidget->installEventFilter(
this);
325 d->m_handleWidget->removeEventFilter(
this);
330 d->m_handleWidget->hide();
332 d->m_pressed =
false;
335 d->m_visible = p_visible;
341 bool configurationChanged = enabled !=
d->m_enabled;
343 d->configure_action->setVisible(enabled &&
d->m_viewManager->selection());
345 d->m_enabled = enabled;
346 if (configurationChanged) {
356 switch (event->type()) {
357 case QEvent::MouseButtonPress: {
358 const QMouseEvent *mouseEvent =
static_cast<QMouseEvent *
>(event);
361 case QEvent::TabletPress: {
362 const QTabletEvent *tabletEvent =
static_cast<QTabletEvent *
>(event);
365 case QEvent::TouchBegin: {
366 const QTouchEvent *touchEvent =
static_cast<QTouchEvent *
>(event);
374 case QEvent::MouseMove:
376 const QMouseEvent *mouseEvent =
static_cast<QMouseEvent *
>(event);
380 case QEvent::TabletMove:
382 const QTabletEvent *tabletEvent =
static_cast<QTabletEvent *
>(event);
386 case QEvent::TouchUpdate:
388 const QTouchEvent *touchEvent =
static_cast<QTouchEvent *
>(event);
396 case QEvent::MouseButtonRelease:
397 case QEvent::TabletRelease:
398 case QEvent::TouchEnd:
399 case QEvent::TouchCancel:
415 Q_FOREACH(QWidget* btn,
d->m_buttons) {
416 btn->setParent(canvas->
widget());
420 d->m_handleWidget->setParent(canvas->
widget());
421 d->m_handleWidget->show();
426 QRect canvasBounds = canvasWidget->rect();
428 const int ACTION_BAR_WIDTH =
d->m_actionBarWidth;
429 const int ACTION_BAR_HEIGHT =
d->m_actionBarHeight;
432 int pos_x_max = canvasBounds.right() - ACTION_BAR_WIDTH -
BUFFER_SPACE;
435 int pos_y_max = canvasBounds.bottom() - ACTION_BAR_HEIGHT -
BUFFER_SPACE;
439 if (pos_x_max < pos_x_min) {
440 pos_x_max = pos_x_min;
444 if (pos_y_max < pos_y_min) {
445 pos_y_max = pos_y_min;
448 position.setX(qBound(pos_x_min, position.x(), pos_x_max));
449 position.setY(qBound(pos_y_min, position.y(), pos_y_max));
458 QPoint anchor = selection.center();
459 QPoint offsetted = selection.center();
460 qreal barHorizontalOffset =
d->m_actionBarWidth;
461 qreal barVerticalOffset =
d->m_actionBarHeight;
465 case Position::Bottom:
466 anchor = QPoint(selection.center().x(), 0);
467 offsetted = anchor - QPoint(barHorizontalOffset/2, 0);
469 case Position::TopLeft:
470 case Position::BottomLeft:
471 anchor = QPoint(selection.left(), 0);
474 case Position::TopRight:
475 case Position::BottomRight:
476 anchor = QPoint(selection.right(), 0);
477 offsetted = anchor - QPoint(barHorizontalOffset, 0);
482 anchor = QPoint(selection.left(), 0);
486 case Position::Right:
487 anchor = QPoint(selection.right(), 0);
494 case Position::TopLeft:
495 case Position::TopRight:
496 anchor += QPoint(0, selection.top());
499 case Position::Bottom:
500 case Position::BottomLeft:
501 case Position::BottomRight:
502 anchor += QPoint(0, selection.bottom());
507 case Position::Right:
508 anchor += QPoint(0, selection.center().y());
509 offsetted += QPoint(0, selection.center().y() - barVerticalOffset/2);
514 if (calculateOnlyAnchor) {
525 QPoint anchor = selection.center();
526 QPoint offsetted = selection.center();
527 qreal barVerticalOffset =
d->m_actionBarHeight;
528 qreal barHorizontalOffset =
d->m_actionBarWidth;
532 case Position::Right:
533 anchor = QPoint(0, selection.center().y());
534 offsetted = -QPoint(0, barVerticalOffset/2);
536 case Position::TopLeft:
537 case Position::TopRight:
538 anchor = QPoint(0, selection.top());
539 offsetted = QPoint();
541 case Position::BottomLeft:
542 case Position::BottomRight:
543 anchor = QPoint(0, selection.bottom());
544 offsetted = -QPoint(0, barVerticalOffset);
548 anchor = QPoint(0, selection.top());
552 case Position::Bottom:
553 anchor = QPoint(0, selection.bottom());
560 case Position::TopLeft:
561 case Position::BottomLeft:
562 anchor += QPoint(selection.left(), 0);
565 case Position::Right:
566 case Position::TopRight:
567 case Position::BottomRight:
568 anchor += QPoint(selection.right(), 0);
573 case Position::Bottom:
574 anchor += QPoint(selection.center().x(), 0);
575 offsetted += QPoint(- barHorizontalOffset/2, 0);
579 if (calculateOnlyAnchor) {
582 return anchor + offsetted;
587 if (!
d->m_viewManager) {
594 if (!canvas || !selection) {
598 QPainterPath selectionOutline = selection->
outlineCache();
605 QRectF selectionBoundsWidget = converter->
imageToWidget(selectionOutline).boundingRect();
607 return selectionBoundsWidget;
612 if (
d->orientation == Orientation::Horizontal) {
621 if (
d->behavior == Behavior::Fixed) {
626 widgetTopLeftPosition +=
d->m_dragHandle.dragOffset;
635 QPen pen = painter.pen();
636 pen.setStyle(Qt::CustomDashLine);
637 pen.setDashPattern({6, 6});
638 pen.setColor(Qt::darkGray);
641 QPoint offset = QPoint(
d->m_actionBarWidth/2,
d->m_actionBarHeight/2);
642 painter.drawLine(QLine(initial,
d->m_dragHandle.position + offset));
645 pen.setStyle(Qt::SolidLine);
648 painter.drawLine(initial + QPoint(xSize, xSize), initial - QPoint(xSize, xSize));
649 painter.drawLine(initial + QPoint(xSize, -xSize), initial + QPoint(-xSize, xSize));
656 const int cornerRadius = 4;
657 QColor outlineColor = qApp->palette().window().color();
659 QColor bgColor = qApp->palette().window().color();
663 bgColor = bgColor.lighter(120);
675 QColor bgColorTrans = bgColor;
676 bgColorTrans.setAlpha(80);
677 const int outline_width = 4;
680 QRectF contrastOutline(
d->m_dragHandle.position - QPoint(outline_width + 1,outline_width + 1), QSize(
d->m_actionBarWidth,
d->m_actionBarHeight) +QSize(outline_width + 1,outline_width + 1) * 2);
681 QRectF midOutline(
d->m_dragHandle.position - QPoint(outline_width,outline_width), QSize(
d->m_actionBarWidth,
d->m_actionBarHeight) +QSize(outline_width,outline_width) * 2);
683 QRectF centerBackground(
d->m_dragHandle.position - QPoint(outline_width,outline_width) / 2, QSize(
d->m_innerActionBarWidth,
d->m_innerActionBarHeight) +QSize(outline_width,outline_width));
685 QPainterPath outlinePath;
686 QPainterPath contrastOutlinePath;
688 bgPath.addRoundedRect(centerBackground, cornerRadius, cornerRadius);
689 outlinePath.addRoundedRect(midOutline, cornerRadius, cornerRadius);
690 contrastOutlinePath.addRoundedRect(contrastOutline, cornerRadius, cornerRadius);
692 painter.fillPath(contrastOutlinePath, bgColorTrans);
693 painter.fillPath(outlinePath, outlineColor);
694 painter.fillPath(bgPath, bgColor);
704 if (
button == Qt::LeftButton) {
706 d->m_dragHandle.dragOrigin = pos -
d->m_dragHandle.dragOffset;
707 d->m_handleWidget->set_held(
true);
718 QWidget *canvasWidget =
d->m_viewManager->canvas();
719 QPoint newPos = pos -
d->m_dragHandle.dragOrigin;
720 d->m_dragHandle.dragOffset = newPos;
723 canvasWidget->update();
730 d->m_handleWidget->set_held(
false);
731 d->m_pressed =
false;
734 KConfigGroup cfg = KSharedConfig::openConfig()->group(
"");
735 cfg.writeEntry(
d->dragOffsetConfigName,
d->m_dragHandle.dragOffset);
743 if (!
d->m_handleWidget)
746 if (
d->orientation == Orientation::Vertical) {
747 d->m_handleWidget->move(
d->m_dragHandle.position.x(),
748 d->m_dragHandle.position.y() +
d->m_buttons.size() *
BUTTON_SIZE);
749 }
else if (
d->orientation == Orientation::Horizontal) {
750 d->m_handleWidget->move(
d->m_dragHandle.position.x() +
d->m_buttons.size() *
BUTTON_SIZE,
751 d->m_dragHandle.position.y());
753 d->m_handleWidget->show();
759 if (
d->orientation == Orientation::Vertical) {
760 button->move(
d->m_dragHandle.position.x(),
d->m_dragHandle.position.y() + buttonPosition);
761 }
else if (
d->orientation == Orientation::Horizontal) {
762 button->move(
d->m_dragHandle.position.x() + buttonPosition,
d->m_dragHandle.position.y());
772#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
781#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
790#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
791 if (touchEvent->pointCount() < 1) {
799 if (touchPoints.isEmpty()) {
809 return d->m_dragHandle.position + pos;
814 QMenu menu = QMenu();
815 menu.addAction(
d->disable_action);
816 menu.addAction(
d->configure_action);
839 KConfigGroup silentCfg = KSharedConfig::openConfig()->group(
"");
844 bool resetOffset =
false;
855 if (resetOffset && !skipResettingOffset) {
856 d->m_dragHandle.dragOffset = QPoint();
857 silentCfg.writeEntry(
d->dragOffsetConfigName, QPoint());
860 if (
d->behavior == Behavior::Fixed) {
865 if (
d->sapPinButtonIndex >= 0 &&
d->m_buttons[
d->sapPinButtonIndex] &&
d->m_buttons[
d->sapPinButtonIndex]->isCheckable()) {
872 if (
d->behavior == Behavior::Fixed) {
887 d->m_handleWidget->themeChanged();
894 d->position = position;
895 QBrush brush(Qt::cyan);
897 brush.setColor(QColor(100 + 20*(
int)position, 100, 100, 150));
898 painter.setBrush(brush);
899 painter.drawRect(QRect(
p, QSize(
d->m_actionBarWidth,
d->m_actionBarHeight)));
909 for (
int position = 0; position < 8; position++) {
914 d->position = remember;
KisAction * actionByName(const QString &name) const
KisActionManager * actionManager
static KisConfigNotifier * instance()
void notifyConfigChanged(void)
SelectionActionsBarOrientation selectionActionBarOrientation(bool defaultValue=false) const
SelectionActionsBarPosition
SelectionActionsBarBehavior
SelectionActionsBarBehavior selectionActionBarBehavior(bool defaultValue=false) const
void setSelectionActionBarOrientation(SelectionActionsBarOrientation value)
SelectionActionsBarOrientation
SelectionActionsBarPosition selectionActionBarPosition(bool defaultValue=false) const
void setSelectionActionBarPosition(SelectionActionsBarPosition value)
void setSelectionActionBar(bool value)
_Private::Traits< T >::Result imageToWidget(const T &obj) const
static KisPart * instance()
void showContextMenu(const QPoint &pos)
void disableSelectionActionsPanel()
void setVisible(bool visible)
void drawAnchorWhileMoving(QPainter &painter) const
End of positioning ///.
bool handlePress(QEvent *event, const QPoint &pos, Qt::MouseButton button=Qt::LeftButton)
void recalculateDimensions()
void movePanelWidgets()
Moves all the widgets that are a part of the panel.
QScopedPointer< Private > d
void drawDebugRectangle(QPainter &painter, Position position)
void setOrientation(Orientation orientation)
void configChanged(bool skipResettingOffset=false)
bool eventFilter(QObject *obj, QEvent *event) override
void configureSelectionActionsPanel()
QPoint currentTopLeftPosition() const
bool handleRelease(QEvent *event)
KisSelectionActionsPanel()=delete
QPoint tabletEventPos(const QTabletEvent *tabletEvent)
QPoint transformHandleCoords(QPoint pos)
void canvasStateChanged()
void setHandleEnabled(bool enabled)
bool handleMove(QEvent *event, const QPoint &pos)
QPoint verticalFreeFloatingTopLeftPosition(bool calculateOnlyAnchor=false) const
QPoint horizontalFreeFloatingTopLeftPosition(bool calculateOnlyAnchor=false) const
QPoint getFixedPosition() const
Positioning ///.
QPoint clipPositionToCanvasBoundaries(QPoint position, QWidget *canvasWidget) const
QPoint mouseEventPos(const QMouseEvent *mouseEvent)
void canvasWidgetChanged(KisCanvasWidgetBase *canvas)
void draw(QPainter &painter, const KoColorDisplayRendererInterface *displayRendererInterface)
bool touchEventPos(const QTouchEvent *touchEvent, QPoint &outPos)
void drawDebugRectanglesForFreeFloatingBehaviour(QPainter &painter)
void drawActionBarBackground(QPainter &gc, const KoColorDisplayRendererInterface *displayRendererInterface) const
void setEnabled(bool enabled)
~KisSelectionActionsPanel()
QPoint freeFloatingInitialTopLeftPosition(bool calculateOnlyAnchor=false) const
QRectF getWidgetSelectionRect() const
void imageResizeToSelection()
void fillForegroundColor()
void copySelectionToNewLayer()
KisActionManager * actionManager() const
QWidget * canvas() const
Return the actual widget that is displaying the current image.
KisSelectionManager * selectionManager()
virtual QColor convertColorToDisplayColorSpace(const KoColor color) const =0
convertColorToDisplayColorSpace
void fromQColor(const QColor &c)
Convenient function for converting from a QColor.
typedef void(QOPENGLF_APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC)(GLuint buffer)
static constexpr int BIG_BUFFER_SPACE_X
static constexpr int BUFFER_SPACE
static constexpr int BIG_BUFFER_SPACE_Y
static constexpr int BUTTON_SIZE
QString button(const QWheelEvent &ev)
void updateIcon(QAbstractButton *button)
void dragColor(QColor *color, const QColor &baseColor, qreal threshold)
KisSelectionManager * m_selectionManager
KisSelectionActionsPanelHandle * m_handleWidget
int m_innerActionBarWidth
const QString dragOffsetConfigName
QList< KisSelectionActionsPanelButton * > m_buttons
KisAction * configure_action
KisViewManager * m_viewManager
KisAction * disable_action
static const QVector< ActionButtonData > & buttonData()
int m_innerActionBarHeight
QPainterPath outlineCache() const