KDDockWidgets API Documentation 1.7
Loading...
Searching...
No Matches
SegmentedIndicators.cpp
Go to the documentation of this file.
1/*
2 This file is part of KDDockWidgets.
3
4 SPDX-FileCopyrightText: 2019-2023 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
5 Author: SĂ©rgio Martins <sergio.martins@kdab.com>
6
7 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
8
9 Contact KDAB at <info@kdab.com> for commercial licensing options.
10*/
11
12#include "SegmentedIndicators_p.h"
13#include "../DropArea_p.h"
14#include "Config.h"
15
16#include <QPainter>
17#include <QPainterPath>
18
19using namespace KDDockWidgets;
20
21int SegmentedIndicators::s_segmentGirth = 50;
22int SegmentedIndicators::s_segmentPenWidth = 4;
23qreal SegmentedIndicators::s_draggedWindowOpacity = 0.7;
24QColor SegmentedIndicators::s_segmentPenColor = Qt::black;
25QColor SegmentedIndicators::s_segmentBrushColor = QColor(0xbb, 0xd5, 0xee, /*alpha=*/200);
26QColor SegmentedIndicators::s_hoveredSegmentBrushColor = QColor(0x3574c5);
27int SegmentedIndicators::s_centralIndicatorMaxWidth = 300;
28int SegmentedIndicators::s_centralIndicatorMaxHeight = 160;
29
30
31SegmentedIndicators::SegmentedIndicators(DropArea *dropArea)
32 : DropIndicatorOverlayInterface(dropArea)
33{
34 // If the app didn't choose opacity then we choose a suitable default value.
35 // ClassicIndicators works fine with an opaque dragged window because the indicators have higher Z,
36 // However for SegmentedIndicators the indicators are in the main window, so lower Z. Make the
37 // dragged window translucent a bit, so we can see the indicators
38 const bool userChoseOpacity = !qIsNaN(Config::self().draggedWindowOpacity());
39 if (!userChoseOpacity)
40 Config::self().setDraggedWindowOpacity(s_draggedWindowOpacity);
41}
42
43SegmentedIndicators::~SegmentedIndicators()
44{
45}
46
47DropLocation SegmentedIndicators::hover_impl(QPoint pt)
48{
49 m_hoveredPt = mapFromGlobal(pt);
50 updateSegments();
51 setCurrentDropLocation(dropLocationForPos(m_hoveredPt));
52
53 return currentDropLocation();
54}
55
56DropLocation SegmentedIndicators::dropLocationForPos(QPoint pos) const
57{
58 for (auto it = m_segments.cbegin(), end = m_segments.cend(); it != end; ++it) {
59 if (it.value().containsPoint(pos, Qt::OddEvenFill)) {
60 return it.key();
61 }
62 }
63
64 return DropLocation_None;
65}
66
67void SegmentedIndicators::paintEvent(QPaintEvent *)
68{
69 QPainter p(this);
70 p.setRenderHint(QPainter::Antialiasing, true);
71 drawSegments(&p);
72}
73
74QHash<DropLocation, QPolygon> SegmentedIndicators::segmentsForRect(QRect r, bool inner, bool useOffset) const
75{
76 const int halfPenWidth = s_segmentPenWidth / 2;
77
78 const int l = s_segmentGirth;
79 const int top = (r.y() == 0 && useOffset) ? l : r.y();
80 const int left = (r.x() == 0 && useOffset) ? l : r.x();
81 const int right = (rect().right() == r.right() && useOffset) ? r.right() - l : r.right();
82 const int bottom = (rect().bottom() == r.bottom() && useOffset) ? r.bottom() - l : r.bottom();
83 const QPoint topLeft = { left + halfPenWidth, top + halfPenWidth };
84 const QPoint topRight = { right, top + halfPenWidth };
85 const QPoint bottomLeft = { left + halfPenWidth, bottom };
86 const QPoint bottomRight = { right, bottom };
87
88 const QVector<QPoint> leftPoints = { topLeft, bottomLeft,
89 QPoint(left, bottom) + QPoint(l, -l),
90 topLeft + QPoint(l, l), topLeft };
91
92 const QVector<QPoint> rightPoints = { topRight, bottomRight,
93 bottomRight + QPoint(-l, -l),
94 topRight + QPoint(-l, l) };
95
96 const QVector<QPoint> topPoints = { topLeft, topRight,
97 topRight + QPoint(-l, l),
98 topLeft + QPoint(l, l) };
99
100 const QVector<QPoint> bottomPoints = { bottomLeft, bottomRight,
101 bottomRight + QPoint(-l, -l),
102 bottomLeft + QPoint(l, -l) };
103
104 if (inner) {
105 QPolygon bounds = QVector<QPoint> { topLeft + QPoint(l, l),
106 topRight + QPoint(-l, l),
107 bottomRight + QPoint(-l, -l),
108 bottomLeft + QPoint(l, -l) };
109 const int maxWidth = bounds.boundingRect().width();
110 const QPoint centerPos = bounds.boundingRect().center();
111
112 // Build the center
113 const int indicatorWidth = qMin(s_centralIndicatorMaxWidth, maxWidth - 100);
114 const int indicatorHeight = qMin(s_centralIndicatorMaxHeight, int(indicatorWidth * 0.60));
115 const int tabWidth = int(indicatorWidth * 0.267);
116 const int tabHeight = int(indicatorHeight * 0.187);
117 const int centerRectLeft = centerPos.x() - indicatorWidth / 2;
118 const int centerRectRight = centerPos.x() + indicatorWidth / 2;
119 const int centerRectBottom = centerPos.y() + indicatorHeight / 2;
120 const int centerRectTop = centerPos.y() - indicatorHeight / 2;
121
122
123 const auto center = QVector<QPoint> {
124 { centerRectLeft, centerRectTop },
125 { centerRectLeft + tabWidth, centerRectTop },
126 { centerRectLeft + tabWidth, centerRectTop + tabHeight },
127 { centerRectRight, centerRectTop + tabHeight },
128 { centerRectRight, centerRectBottom },
129 { centerRectLeft, centerRectBottom },
130 };
131
132 return {
133 { DropLocation_Left, leftPoints },
134 { DropLocation_Top, topPoints },
135 { DropLocation_Right, rightPoints },
136 { DropLocation_Bottom, bottomPoints },
138 };
139 } else {
140 return {
141 { DropLocation_OutterLeft, leftPoints },
142 { DropLocation_OutterTop, topPoints },
143 { DropLocation_OutterRight, rightPoints },
144 { DropLocation_OutterBottom, bottomPoints }
145 };
146 }
147}
148
149void SegmentedIndicators::updateSegments()
150{
151 m_segments.clear();
152
153 const auto outterSegments = segmentsForRect(rect(), /*inner=*/false);
154
156 if (dropIndicatorVisible(indicator)) {
157 m_segments.insert(indicator, outterSegments.value(indicator));
158 }
159 }
160
161 const bool hasOutter = !m_segments.isEmpty();
162 const bool useOffset = hasOutter;
163 const auto innerSegments = segmentsForRect(hoveredFrameRect(), /*inner=*/true, useOffset);
164
166 if (dropIndicatorVisible(indicator)) {
167 m_segments.insert(indicator, innerSegments.value(indicator));
168 }
169 }
170
171 update();
172}
173
174void SegmentedIndicators::drawSegments(QPainter *p)
175{
176 for (DropLocation loc : { DropLocation_Left,
185 drawSegment(p, m_segments.value(loc));
186}
187
188void SegmentedIndicators::drawSegment(QPainter *p, const QPolygon &segment)
189{
190 if (segment.isEmpty())
191 return;
192
193 QPen pen(s_segmentPenColor);
194 pen.setWidth(s_segmentPenWidth);
195 p->setPen(pen);
196 QColor brush(s_segmentBrushColor);
197
198 if (segment.containsPoint(m_hoveredPt, Qt::OddEvenFill))
199 brush = s_hoveredSegmentBrushColor;
200
201 p->setBrush(brush);
202 p->drawPolygon(segment);
203}
204
205QPoint KDDockWidgets::SegmentedIndicators::posForIndicator(DropLocation) const
206{
208 return {};
209}
Application-wide config to tune certain behaviours of the framework.
void setDraggedWindowOpacity(qreal opacity)
sets the dragged window opacity 1.0 is fully opaque while 0.0 is fully transparent
Definition Config.cpp:165
static Config & self()
returns the singleton Config instance
Definition Config.cpp:84
DropLocation
Enum describing the different drop indicator types.
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
void setBrush(const QBrush &brush)
void setPen(const QColor &color)
int x() const const
int y() const const
QRect boundingRect() const const
bool containsPoint(const QPoint &point, Qt::FillRule fillRule) const const
int bottom() const const
QPoint center() const const
int right() const const
int width() const const
int x() const const
int y() const const
OddEvenFill
QTextStream & center(QTextStream &stream)
QTextStream & left(QTextStream &stream)
QTextStream & right(QTextStream &stream)
void clear()
bool isEmpty() const const

© 2019-2023 Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
KDDockWidgets
Advanced Dock Widget Framework for Qt
https://www.kdab.com/development-resources/qt-tools/kddockwidgets/
Generated on Wed Nov 1 2023 00:02:31 for KDDockWidgets API Documentation by doxygen 1.9.8