KDDockWidgets API Documentation 2.1
Loading...
Searching...
No Matches
core/Separator.cpp
Go to the documentation of this file.
1/*
2 This file is part of KDDockWidgets.
3
4 SPDX-FileCopyrightText: 2020 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 "Separator.h"
13#include "layouting/Item_p.h"
14#include "layouting/LayoutingSeparator_p.h"
15#include "View.h"
16#include "Logging_p.h"
17#include "Layout.h"
18#include "Config.h"
19#include "Platform.h"
20#include "Controller.h"
21#include "core/ViewFactory.h"
22
23
24#ifdef Q_OS_WIN
25#include <Windows.h>
26#endif
27
28using namespace KDDockWidgets;
29using namespace KDDockWidgets::Core;
30
32static int s_numSeparators = 0;
33
34namespace {
35
36bool rubberBandIsTopLevel()
37{
40}
41
42}
43
44struct Separator::Private : public LayoutingSeparator
45{
46 // Only set when anchor is moved through mouse. Side1 if going towards left or top, Side2
47 // otherwise.
48
49 explicit Private(Core::Separator *qq, LayoutingHost *host, Qt::Orientation orientation, Core::ItemBoxContainer *parentContainer)
50 : LayoutingSeparator(host, orientation, parentContainer)
51 , q(qq)
52 {
54 }
55
56 ~Private() override;
57
58 Rect geometry() const override
59 {
60 return m_geometry;
61 }
62
63 void setGeometry(Rect r) override
64 {
65 q->setGeometry(r);
66 }
67
68 void free() override
69 {
70#ifdef KDDW_FRONTEND_QT
72 q->deleteLater();
73 return;
74 }
75#endif
76 delete q;
77 }
78
79 void raise() override
80 {
81 q->view()->raise();
82 }
83
84 Core::Separator *const q;
85 Rect m_geometry;
86 int lazyPosition = 0;
87 View *lazyResizeRubberBand = nullptr;
88 const bool usesLazyResize = Config::self().flags() & Config::Flag_LazyResize;
89};
90
91namespace {
92Core::View *viewForLayoutingHost(LayoutingHost *host)
93{
94 // For KDDW, a LayoutingHost is always a Core::Layout
95 if (auto layout = Layout::fromLayoutingHost(host))
96 return layout->view();
97
98 return nullptr;
99}
100}
101
102Separator::Separator(LayoutingHost *host, Qt::Orientation orientation, Core::ItemBoxContainer *parentContainer)
103 : Controller(ViewType::Separator, Config::self().viewFactory()->createSeparator(this, viewForLayoutingHost(host)))
104 , d(new Private(this, host, orientation, parentContainer))
105{
106 view()->show();
107 view()->init();
108 d->lazyResizeRubberBand = d->usesLazyResize ? Config::self().viewFactory()->createRubberBand(
109 rubberBandIsTopLevel() ? nullptr : view())
110 : nullptr;
111 setVisible(true);
112}
113
115{
116 delete d;
117}
118
120{
121 return d->isVertical();
122}
123
125{
126 return d->position();
127}
128
130{
131 if (r == d->m_geometry)
132 return;
133
134 d->m_geometry = r;
135
136 if (View *v = view()) {
137 v->setGeometry(r);
138 }
139
140 setVisible(true);
141}
142
143void Separator::setLazyPosition(int pos)
144{
145 if (pos == d->lazyPosition)
146 return;
147
148 View *v = view();
149
150 d->lazyPosition = pos;
151
152 Rect geo = v->geometry();
153 if (isVertical()) {
154 geo.moveTop(pos);
155 } else {
156 geo.moveLeft(pos);
157 }
158
159 if (rubberBandIsTopLevel() && Platform::instance()->isQtWidgets())
160 geo.translate(view()->mapToGlobal(Point(0, 0)));
161 d->lazyResizeRubberBand->setGeometry(geo);
162}
163
164bool Separator::usesLazyResize() const
165{
166 return d->usesLazyResize;
167}
168
170{
171 d->onMousePress();
172
173 KDDW_DEBUG("Drag started");
174
175 if (d->lazyResizeRubberBand) {
176 setLazyPosition(position());
177 d->lazyResizeRubberBand->show();
178 if (rubberBandIsTopLevel() && Platform::instance()->isQtWidgets())
179 d->lazyResizeRubberBand->raise();
180 }
181}
182
184{
185 if (d->lazyResizeRubberBand) {
186 d->lazyResizeRubberBand->hide();
187 d->m_parentContainer->requestSeparatorMove(d, d->lazyPosition - position());
188 }
189
190 d->onMouseRelease();
191}
192
194{
195 // a double click means we'll resize the left and right neighbour so that they occupy
196 // the same size (or top/bottom, depending on orientation).
197 d->m_parentContainer->requestEqualSize(d);
198}
199
201{
202 if (!d->isBeingDragged())
203 return;
204
205 if (Platform::instance()->isQt()) {
206 // Workaround a bug in Qt where we're getting mouse moves without without the button being
207 // pressed
208 if (!Platform::instance()->isLeftMouseButtonPressed()) {
209 KDDW_DEBUG(
210 "Separator::onMouseMove: Ignoring spurious mouse event. Someone ate our ReleaseEvent");
212 return;
213 }
214
215#ifdef KDDW_FRONTEND_QT_WINDOWS
216 // Try harder, Qt can be wrong, if mixed with MFC
217 const bool mouseButtonIsReallyDown =
218 (GetKeyState(VK_LBUTTON) & 0x8000) || (GetKeyState(VK_RBUTTON) & 0x8000);
219 if (!mouseButtonIsReallyDown) {
220 KDDW_DEBUG(
221 "Separator::onMouseMove: Ignoring spurious mouse event. Someone ate our ReleaseEvent");
223 return;
224 }
225#endif
226 }
227
228 if (d->lazyResizeRubberBand) {
229 const int positionToGoTo = d->onMouseMove(pos, /*moveSeparator=*/false);
230 if (positionToGoTo != -1)
231 setLazyPosition(positionToGoTo);
232 } else {
233 d->onMouseMove(pos, /*moveSeparator=*/true);
234 }
235}
236
237LayoutingSeparator *Separator::asLayoutingSeparator() const
238{
239 return d;
240}
241
244{
245 return LayoutingSeparator::s_separatorBeingDragged != nullptr;
246}
247
250{
251 return s_numSeparators;
252}
253
254Separator::Private::~Private()
255{
257}
Application-wide config to tune certain behaviours of the framework.
A widget that supports an arbitrary number of splitters (called Separators) in any combination of ver...
Singleton to allow to choose certain behaviours of the framework.
Definition Config.h:64
InternalFlags internalFlags() const
Definition Config.cpp:312
Core::ViewFactory * viewFactory() const
getter for the framework view factory
Definition Config.cpp:182
@ InternalFlag_DeleteSeparatorsLater
This flag allows to disable the workaround if you think you don't have the complex setup reported in ...
Definition Config.h:177
@ InternalFlag_TopLevelIndicatorRubberBand
with more exotic setups. This flag can be used to override.
Definition Config.h:171
static Config & self()
returns the singleton Config instance
Definition Config.cpp:88
Flags flags() const
returns the chosen flags
Definition Config.cpp:102
View * view() const
Returns the view associated with this controller, if any.
Point mapToGlobal(Point) const
static Layout * fromLayoutingHost(LayoutingHost *)
Definition Layout.cpp:396
static Platform * instance()
Returns the platform singleton.
LayoutingSeparator * asLayoutingSeparator() const
static bool isResizing()
Returns whether we're dragging a separator. Can be useful for the app to stop other work while we're ...
virtual View * createRubberBand(View *parent) const =0
Called by the framework to create a RubberBand view to show as drop zone.
virtual void show()=0
virtual Rect geometry() const =0
static int s_numSeparators
internal counter just for unit-tests
ViewType
Each View type also has a specific Controller associated with, except for ViewType::None.
Definition Controller.h:26
Class to abstract QAction, so code still works with QtQuick and Flutter.
Orientation

© 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 by doxygen 1.9.8