KDDockWidgets API Documentation  1.5
SegmentedIndicators.cpp
Go to the documentation of this file.
1 /*
2  This file is part of KDDockWidgets.
3 
4  SPDX-FileCopyrightText: 2019-2022 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 
19 using namespace KDDockWidgets;
20 
21 int SegmentedIndicators::s_segmentGirth = 50;
22 int SegmentedIndicators::s_segmentPenWidth = 4;
23 qreal SegmentedIndicators::s_draggedWindowOpacity = 0.7;
24 QColor SegmentedIndicators::s_segmentPenColor = Qt::black;
25 QColor SegmentedIndicators::s_segmentBrushColor = QColor(0xbb, 0xd5, 0xee, /*alpha=*/200);
26 QColor SegmentedIndicators::s_hoveredSegmentBrushColor = QColor(0x3574c5);
27 
28 
29 SegmentedIndicators::SegmentedIndicators(DropArea *dropArea)
30  : DropIndicatorOverlayInterface(dropArea)
31 {
32  // If the app didn't choose opacity then we choose a suitable default value.
33  // ClassicIndicators works fine with an opaque dragged window because the indicators have higher Z,
34  // However for SegmentedIndicators the indicators are in the main window, so lower Z. Make the
35  // dragged window translucent a bit, so we can see the indicators
36  const bool userChoseOpacity = !qIsNaN(Config::self().draggedWindowOpacity());
37  if (!userChoseOpacity)
38  Config::self().setDraggedWindowOpacity(s_draggedWindowOpacity);
39 }
40 
41 SegmentedIndicators::~SegmentedIndicators()
42 {
43 }
44 
45 DropIndicatorOverlayInterface::DropLocation SegmentedIndicators::hover_impl(QPoint pt)
46 {
47  m_hoveredPt = mapFromGlobal(pt);
48  updateSegments();
49  setCurrentDropLocation(dropLocationForPos(m_hoveredPt));
50 
51  return currentDropLocation();
52 }
53 
54 DropIndicatorOverlayInterface::DropLocation SegmentedIndicators::dropLocationForPos(QPoint pos) const
55 {
56  for (auto it = m_segments.cbegin(), end = m_segments.cend(); it != end; ++it) {
57  if (it.value().containsPoint(pos, Qt::OddEvenFill)) {
58  return it.key();
59  }
60  }
61 
62  return DropLocation_None;
63 }
64 
65 void SegmentedIndicators::paintEvent(QPaintEvent *)
66 {
67  QPainter p(this);
68  p.setRenderHint(QPainter::Antialiasing, true);
69  drawSegments(&p);
70 }
71 
72 QVector<QPolygon> SegmentedIndicators::segmentsForRect(QRect r, QPolygon &center, bool useOffset) const
73 {
74  const int halfPenWidth = s_segmentPenWidth / 2;
75 
76  const int l = s_segmentGirth;
77  const int top = (r.y() == 0 && useOffset) ? l : r.y();
78  const int left = (r.x() == 0 && useOffset) ? l : r.x();
79  const int right = (rect().right() == r.right() && useOffset) ? r.right() - l : r.right();
80  const int bottom = (rect().bottom() == r.bottom() && useOffset) ? r.bottom() - l : r.bottom();
81  const QPoint topLeft = { left + halfPenWidth, top + halfPenWidth };
82  const QPoint topRight = { right, top + halfPenWidth };
83  const QPoint bottomLeft = { left + halfPenWidth, bottom };
84  const QPoint bottomRight = { right, bottom };
85 
86  const QVector<QPoint> leftPoints = { topLeft, bottomLeft,
87  QPoint(left, bottom) + QPoint(l, -l),
88  topLeft + QPoint(l, l), topLeft };
89 
90  const QVector<QPoint> rightPoints = { topRight, bottomRight,
91  bottomRight + QPoint(-l, -l),
92  topRight + QPoint(-l, l) };
93 
94  const QVector<QPoint> topPoints = { topLeft, topRight,
95  topRight + QPoint(-l, l),
96  topLeft + QPoint(l, l) };
97 
98  const QVector<QPoint> bottomPoints = { bottomLeft, bottomRight,
99  bottomRight + QPoint(-l, -l),
100  bottomLeft + QPoint(l, -l) };
101 
102  {
103 
104  QPolygon bounds = QVector<QPoint> { topLeft + QPoint(l, l),
105  topRight + QPoint(-l, l),
106  bottomRight + QPoint(-l, -l),
107  bottomLeft + QPoint(l, -l) };
108  const int maxWidth = bounds.boundingRect().width();
109  const QPoint centerPos = bounds.boundingRect().center();
110 
111  // Build the center
112  const int indicatorWidth = qMin(300, maxWidth - 100);
113  const int indicatorHeight = qMin(160, int(indicatorWidth * 0.60));
114  const int tabWidth = int(indicatorWidth * 0.267);
115  const int tabHeight = int(indicatorHeight * 0.187);
116  const int centerRectLeft = centerPos.x() - indicatorWidth / 2;
117  const int centerRectRight = centerPos.x() + indicatorWidth / 2;
118  const int centerRectBottom = centerPos.y() + indicatorHeight / 2;
119  const int centerRectTop = centerPos.y() - indicatorHeight / 2;
120 
121 
123  { centerRectLeft, centerRectTop },
124  { centerRectLeft + tabWidth, centerRectTop },
125  { centerRectLeft + tabWidth, centerRectTop + tabHeight },
126  { centerRectRight, centerRectTop + tabHeight },
127  { centerRectRight, centerRectBottom },
128  { centerRectLeft, centerRectBottom },
129  };
130  }
131 
132  return { leftPoints, topPoints, rightPoints, bottomPoints };
133 }
134 
135 void SegmentedIndicators::updateSegments()
136 {
137  m_segments.clear();
138 
139  const bool hasMultipleFrames = m_dropArea->visibleCount() > 1;
140  const bool needsOutterIndicators = true; // Can't think of a reason not to show them
141  const bool needsInnerIndicators = needsOutterIndicators && hasMultipleFrames && hoveredFrameRect().isValid();
142 
144 
145  if (needsInnerIndicators) {
146  const bool useOffset = needsOutterIndicators;
147  auto segments = segmentsForRect(hoveredFrameRect(), /*by-ref*/ center, useOffset);
148  for (int i = 0; i < 4; ++i)
149  m_segments.insert(DropLocation(DropLocation_Left + i), segments[i]);
150 
151  m_segments.insert(DropLocation_Center, center);
152  }
153 
154  if (needsOutterIndicators) {
155  auto segments = segmentsForRect(rect(), /*unused*/ center);
156  for (int i = 0; i < 4; ++i)
157  m_segments.insert(DropLocation(DropLocation_OutterLeft + i), segments[i]);
158  }
159 
160  update();
161 }
162 
163 void SegmentedIndicators::drawSegments(QPainter *p)
164 {
165  for (int i = DropLocation_First; i <= DropLocation_Last; ++i)
166  drawSegment(p, m_segments.value(DropLocation(i)));
167 }
168 
169 void SegmentedIndicators::drawSegment(QPainter *p, const QPolygon &segment)
170 {
171  if (segment.isEmpty())
172  return;
173 
174  QPen pen(s_segmentPenColor);
175  pen.setWidth(s_segmentPenWidth);
176  p->setPen(pen);
177  QColor brush(s_segmentBrushColor);
178 
179  if (segment.containsPoint(m_hoveredPt, Qt::OddEvenFill))
180  brush = s_hoveredSegmentBrushColor;
181 
182  p->setBrush(brush);
183  p->drawPolygon(segment);
184 }
185 
186 QPoint KDDockWidgets::SegmentedIndicators::posForIndicator(DropIndicatorOverlayInterface::DropLocation) const
187 {
189  return {};
190 }
QPainter::Antialiasing
Antialiasing
QColor
Qt::right
QTextStream & right(QTextStream &stream)
QVector::isEmpty
bool isEmpty() const const
QPainter::setPen
void setPen(const QColor &color)
QPolygon::containsPoint
bool containsPoint(const QPoint &point, Qt::FillRule fillRule) const const
QRect
QRect::right
int right() const const
Qt::left
QTextStream & left(QTextStream &stream)
QRect::width
int width() const const
QRect::x
int x() const const
QRect::y
int y() const const
QPoint::x
int x() const const
QPoint::y
int y() const const
QPolygon
QPainter
QPen
QPainter::drawPolygon
void drawPolygon(const QPointF *points, int pointCount, Qt::FillRule fillRule)
QRect::bottom
int bottom() const const
Qt::OddEvenFill
OddEvenFill
QVector::clear
void clear()
QRect::center
QPoint center() const const
KDDockWidgets::Config::setDraggedWindowOpacity
void setDraggedWindowOpacity(qreal opacity)
sets the dragged window opacity 1.0 is fully opaque while 0.0 is fully transparent
Definition: Config.cpp:163
QPolygon::boundingRect
QRect boundingRect() const const
QPainter::setBrush
void setBrush(const QBrush &brush)
Config.h
Application-wide config to tune certain behaviours of the framework.
QPaintEvent
KDDockWidgets
Definition: Config.cpp:36
Qt::center
QTextStream & center(QTextStream &stream)
QVector
Qt::black
black
QPoint
KDDockWidgets::Config::self
static Config & self()
returns the singleton Config instance
Definition: Config.cpp:82

© 2019-2022 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 Mon Mar 7 2022 02:01:21 for KDDockWidgets API Documentation by doxygen 1.8.20