Phosphor
Qt6 / Wayland library suite for window-management tools
 
Loading...
Searching...
No Matches
SplitTree.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 fuddlesworth
2// SPDX-License-Identifier: LGPL-2.1-or-later
3
4#pragma once
5
6#include <phosphortiles_export.h>
7
8#include "AutotileConstants.h"
9
10#include <QJsonObject>
11#include <QRect>
12#include <QString>
13#include <QStringList>
14#include <QVector>
15
16#include <memory>
17
18namespace PhosphorTiles {
19
26struct PHOSPHORTILES_EXPORT SplitNode
27{
28 qreal splitRatio = AutotileDefaults::DefaultSplitRatio;
29 bool splitHorizontal = false;
30 std::unique_ptr<SplitNode> first;
31 std::unique_ptr<SplitNode> second;
32 SplitNode* parent = nullptr;
33 QString windowId;
34
35 bool isLeaf() const
36 {
37 return !first && !second;
38 }
39};
40
57class PHOSPHORTILES_EXPORT SplitTree
58{
59public:
62
64 SplitTree(SplitTree&& other) noexcept;
65
67 SplitTree& operator=(SplitTree&& other) noexcept;
68
70
71 // Non-copyable (unique_ptr members)
72 SplitTree(const SplitTree&) = delete;
73 SplitTree& operator=(const SplitTree&) = delete;
74
75 // ═══════════════════════════════════════════════════════════════════════
76 // Queries
77 // ═══════════════════════════════════════════════════════════════════════
78
83 const SplitNode* root() const noexcept;
84 SplitNode* root() noexcept;
85
89 bool isEmpty() const noexcept;
90
94 int leafCount() const noexcept;
95
100 int treeHeight() const noexcept;
101
107 const SplitNode* leafForWindow(const QString& windowId) const;
108 SplitNode* leafForWindow(const QString& windowId);
109
114 QStringList leafOrder() const;
115
116 // ═══════════════════════════════════════════════════════════════════════
117 // Mutations
118 // ═══════════════════════════════════════════════════════════════════════
119
129 void insertAtFocused(const QString& windowId, const QString& focusedWindowId, qreal initialRatio = 0.0);
130
139 void insertAtEnd(const QString& windowId, qreal initialRatio = 0.0);
140
151 void insertAtPosition(const QString& windowId, int position, qreal initialRatio = 0.0);
152
157 void remove(const QString& windowId);
158
168 void swap(const QString& windowId1, const QString& windowId2);
169
188 bool swapLeaves(const QString& a, const QString& b);
189
195 void resizeSplit(const QString& windowId, qreal newRatio);
196
197 // ═══════════════════════════════════════════════════════════════════════
198 // Geometry
199 // ═══════════════════════════════════════════════════════════════════════
200
215 QVector<QRect> applyGeometry(const QRect& area, int innerGap) const;
216
226 bool rebuildFromOrder(const QStringList& tiledWindows,
227 qreal defaultSplitRatio = AutotileDefaults::DefaultSplitRatio);
228
229 // ═══════════════════════════════════════════════════════════════════════
230 // Serialization
231 // ═══════════════════════════════════════════════════════════════════════
232
236 QJsonObject toJson() const;
237
243 static std::unique_ptr<SplitTree> fromJson(const QJsonObject& json);
244
245private:
246 enum class InsertReady {
247 Proceed,
248 Done,
249 Rejected
250 };
254 static constexpr int MaxRuntimeTreeDepth = AutotileDefaults::MaxRuntimeTreeDepth;
255
256 InsertReady prepareInsert(const QString& windowId);
257
259 void insertAtEndRaw(const QString& windowId, qreal initialRatio);
260
262 void insertAtEndImpl(const QString& windowId, qreal initialRatio);
263
264 std::unique_ptr<SplitNode> m_root;
265
266 SplitNode* findLeaf(SplitNode* node, const QString& windowId, int depth = 0) const;
267 const SplitNode* findLeaf(const SplitNode* node, const QString& windowId, int depth = 0) const;
268 SplitNode* leafAtIndex(SplitNode* node, int targetIndex, int& currentIndex, int depth = 0) const;
269 const SplitNode* leafAtIndex(const SplitNode* node, int targetIndex, int& currentIndex, int depth = 0) const;
270 SplitNode* rightmostLeaf(SplitNode* node) const;
271 const SplitNode* rightmostLeaf(const SplitNode* node) const;
272 void collectLeafOrder(const SplitNode* node, QStringList& order, int depth = 0) const;
273 int countLeaves(const SplitNode* node, int depth = 0) const;
274 void applyGeometryRecursive(const SplitNode* node, const QRect& rect, int innerGap, QVector<QRect>& zones,
275 int depth = 0) const;
276
277 static int subtreeHeight(const SplitNode* node, int depth = 0);
278 static void splitLeaf(SplitNode* leaf, const QString& newId, qreal ratio);
279
280 static constexpr int MaxDeserializationDepth = AutotileDefaults::MaxRuntimeTreeDepth;
281 static constexpr int MaxDeserializationNodes = 1024;
282
283 static QJsonObject nodeToJson(const SplitNode* node, int depth = 0);
284 static std::unique_ptr<SplitNode> nodeFromJson(const QJsonObject& json, SplitNode* parent, int depth,
285 int& nodeCount, int& clampedRatios, QSet<QString>& seenIds);
286};
287
288} // namespace PhosphorTiles
Algorithm-layer constants for the autotile/tile primitives.
A binary split tree for interactive window tiling.
Definition SplitTree.h:58
SplitTree(SplitTree &&other) noexcept
Move constructor.
const SplitNode * root() const noexcept
Get the root node of the tree.
SplitTree & operator=(const SplitTree &)=delete
SplitTree & operator=(SplitTree &&other) noexcept
Move assignment.
SplitTree()
Construct an empty tree (no root)
SplitTree(const SplitTree &)=delete
Definition AutotileEngine.h:71
A single node in the binary split tree.
Definition SplitTree.h:27
std::unique_ptr< SplitNode > second
Second child (right or bottom)
Definition SplitTree.h:31
bool isLeaf() const
Definition SplitTree.h:35
std::unique_ptr< SplitNode > first
First child (left or top)
Definition SplitTree.h:30
QString windowId
Non-empty only for leaf nodes.
Definition SplitTree.h:33