QmlMaterial 0.1.0
Loading...
Searching...
No Matches
split_view.hpp
1#pragma once
2
3#include "qml_material/control/container.hpp"
4#include <QHash>
5#include <QQmlComponent>
6#include <limits>
7#include <memory>
8#include <QtQuick/private/qquicktransition_p.h>
9
10namespace qml_material
11{
12class SplitViewAttached;
13class SplitHandleInput;
14struct SplitResizeState;
15struct SplitPaneState;
16namespace split_layout
17{
18struct Pane;
19}
20
21class QML_MATERIAL_API SplitView : public Container {
22 Q_OBJECT
23 QML_NAMED_ELEMENT(SplitViewBase)
24 QML_ATTACHED(SplitViewAttached)
25 Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY
26 orientationChanged FINAL)
27 Q_PROPERTY(QQmlComponent* handle READ handle WRITE setHandle NOTIFY handleChanged FINAL)
28 Q_PROPERTY(bool resizing READ isResizing NOTIFY resizingChanged FINAL)
29 Q_PROPERTY(QQuickTransition* expandTransition READ expandTransition WRITE setExpandTransition
30 NOTIFY transitionsChanged FINAL)
31 Q_PROPERTY(QQuickTransition* collapseTransition READ collapseTransition WRITE
32 setCollapseTransition NOTIFY transitionsChanged FINAL)
33public:
34 explicit SplitView(QQuickItem* parent = nullptr);
35 ~SplitView() override;
36 static SplitViewAttached* qmlAttachedProperties(QObject*);
37 Qt::Orientation orientation() const { return m_orientation; }
38 void setOrientation(Qt::Orientation);
39 Q_SIGNAL void orientationChanged();
40 QQmlComponent* handle() const { return m_handle; }
41 void setHandle(QQmlComponent*);
42 Q_INVOKABLE QQuickItem* handleItemAt(int index) const;
43 Q_SIGNAL void handleChanged();
44 bool isResizing() const;
45 Q_SIGNAL void resizingChanged();
46 Q_INVOKABLE QVariant saveState() const;
47 Q_INVOKABLE bool restoreState(const QVariant&);
48 QQuickTransition* expandTransition() const { return m_expand; }
49 QQuickTransition* collapseTransition() const { return m_collapse; }
50 void setExpandTransition(QQuickTransition*);
51 void setCollapseTransition(QQuickTransition*);
52 Q_SIGNAL void transitionsChanged();
53
54protected:
55 bool isContent(QQuickItem*) const override;
56 void itemAdded(QQuickItem*) override;
57 void itemRemoved(QQuickItem*) override;
58 void itemsChanged() override;
59 void updatePolish() override;
60 void componentComplete() override;
61
62private:
63 friend class SplitHandleInput;
64 friend class SplitViewAttached;
65 void changeExpanded(QQuickItem*);
66 void completeExpansion(QQuickItem*, quint64);
67 void settleExpansions(bool notify);
68 void cancelExpansion(QQuickItem*);
69 QHash<QQuickItem*, std::shared_ptr<SplitPaneState>> m_panes;
70 QPointer<QQuickTransition> m_expand, m_collapse;
71 bool m_updating_hosts = false;
72 bool beginResize(QQuickItem*, const QPointF&);
73 void moveResize(const QPointF&);
74 void endResize();
75 void invalidateLayout();
76 QList<split_layout::Pane> layoutPanes(Qt::Orientation) const;
77 std::unique_ptr<SplitResizeState> m_resize;
78 bool m_writing_preferred = false;
79 void requestLayout();
80 bool syncHandles();
81 void clearHandles();
82 QPointer<QQmlComponent> m_handle;
83 QList<QPointer<QQuickItem>> m_handles;
84 QList<QMetaObject::Connection> m_handle_connections;
85 bool m_handles_dirty = false;
86 bool m_destroying = false;
87 Qt::Orientation m_orientation = Qt::Horizontal;
88 QHash<QQuickItem*, QList<QMetaObject::Connection>> m_connections;
89 quint64 m_layout_revision = 0;
90 bool m_laying_out = false;
91 quint64 m_restore_revision = 0;
92};
93
94class QML_MATERIAL_API SplitHandleAttached : public QObject {
95 Q_OBJECT
96 QML_NAMED_ELEMENT(SplitHandle)
97 QML_UNCREATABLE("SplitHandle is an attached property")
98 QML_ATTACHED(SplitHandleAttached)
99 Q_PROPERTY(bool hovered READ isHovered NOTIFY hoveredChanged FINAL)
100 Q_PROPERTY(bool pressed READ isPressed NOTIFY pressedChanged FINAL)
101 Q_PROPERTY(bool resizable READ isResizable NOTIFY resizableChanged FINAL)
102public:
103 explicit SplitHandleAttached(QObject* parent): QObject(parent) {}
104 static SplitHandleAttached* qmlAttachedProperties(QObject* object);
105 bool isHovered() const { return m_hovered; }
106 bool isPressed() const { return m_pressed; }
107 bool isResizable() const { return m_resizable; }
108 Q_SIGNAL void resizableChanged();
109 Q_SIGNAL void hoveredChanged();
110 Q_SIGNAL void pressedChanged();
111
112private:
113 friend class SplitHandleInput;
114 friend class SplitView;
115 void setHovered(bool);
116 void setPressed(bool);
117 void setResizable(bool);
118 bool m_resizable = false;
119 bool m_hovered = false;
120 bool m_pressed = false;
121};
122
123class QML_MATERIAL_API SplitViewAttached : public QObject {
124 Q_OBJECT
125 Q_PROPERTY(SplitView* view READ view NOTIFY viewChanged FINAL)
126 Q_PROPERTY(qreal minimumWidth READ minimumWidth WRITE setMinimumWidth RESET resetMinimumWidth
127 NOTIFY minimumWidthChanged FINAL)
128 Q_PROPERTY(qreal minimumHeight READ minimumHeight WRITE setMinimumHeight RESET
129 resetMinimumHeight NOTIFY minimumHeightChanged FINAL)
130 Q_PROPERTY(qreal preferredWidth READ preferredWidth WRITE setPreferredWidth RESET
131 resetPreferredWidth NOTIFY preferredWidthChanged FINAL)
132 Q_PROPERTY(qreal preferredHeight READ preferredHeight WRITE setPreferredHeight RESET
133 resetPreferredHeight NOTIFY preferredHeightChanged FINAL)
134 Q_PROPERTY(qreal maximumWidth READ maximumWidth WRITE setMaximumWidth RESET resetMaximumWidth
135 NOTIFY maximumWidthChanged FINAL)
136 Q_PROPERTY(qreal maximumHeight READ maximumHeight WRITE setMaximumHeight RESET
137 resetMaximumHeight NOTIFY maximumHeightChanged FINAL)
138 Q_PROPERTY(bool fillWidth READ fillWidth WRITE setFillWidth NOTIFY fillWidthChanged FINAL)
139 Q_PROPERTY(bool fillHeight READ fillHeight WRITE setFillHeight NOTIFY fillHeightChanged FINAL)
140 Q_PROPERTY(bool expanded READ isExpanded WRITE setExpanded NOTIFY expandedChanged FINAL)
141 Q_PROPERTY(bool transitioning READ isTransitioning NOTIFY transitioningChanged FINAL)
142public:
143 explicit SplitViewAttached(QObject*);
144 SplitView* view() const;
145 qreal minimumWidth() const { return m_minimum_width; }
146 qreal minimumHeight() const { return m_minimum_height; }
147 qreal preferredWidth() const { return m_preferred_width.value_or(-1); }
148 qreal preferredHeight() const { return m_preferred_height.value_or(-1); }
149 qreal maximumWidth() const { return m_maximum_width; }
150 qreal maximumHeight() const { return m_maximum_height; }
151 bool fillWidth() const { return m_fill_width; }
152 bool fillHeight() const { return m_fill_height; }
153 bool isExpanded() const { return m_expanded; }
154 bool isTransitioning() const { return m_transitioning; }
155 void setExpanded(bool);
156 Q_SIGNAL void expandedChanged();
157 Q_SIGNAL void transitioningChanged();
158 Q_SIGNAL void expandedCompleted();
159 Q_SIGNAL void collapsedCompleted();
160 void setMinimumWidth(qreal);
161 void setMinimumHeight(qreal);
162 void setPreferredWidth(qreal);
163 void setPreferredHeight(qreal);
164 void setMaximumWidth(qreal);
165 void setMaximumHeight(qreal);
166 void setFillWidth(bool);
167 void setFillHeight(bool);
168 void resetMinimumWidth();
169 void resetMinimumHeight();
170 void resetPreferredWidth();
171 void resetPreferredHeight();
172 void resetMaximumWidth();
173 void resetMaximumHeight();
174 Q_SIGNAL void viewChanged();
175 Q_SIGNAL void minimumWidthChanged();
176 Q_SIGNAL void minimumHeightChanged();
177 Q_SIGNAL void preferredWidthChanged();
178 Q_SIGNAL void preferredHeightChanged();
179 Q_SIGNAL void maximumWidthChanged();
180 Q_SIGNAL void maximumHeightChanged();
181 Q_SIGNAL void fillWidthChanged();
182 Q_SIGNAL void fillHeightChanged();
183 Q_SIGNAL void constraintsChanged();
184
185private:
186 friend class SplitView;
187 QPointer<ContainerAttached> m_container;
188 qreal m_minimum_width = 0;
189 qreal m_minimum_height = 0;
190 qreal m_maximum_width = std::numeric_limits<qreal>::infinity();
191 qreal m_maximum_height = std::numeric_limits<qreal>::infinity();
192 std::optional<qreal> m_preferred_width;
193 std::optional<qreal> m_preferred_height;
194 bool m_fill_width = false;
195 bool m_fill_height = false;
196 bool m_expanded = true;
197 bool m_transitioning = false;
198};
199} // namespace qml_material
200QML_DECLARE_TYPEINFO(qml_material::SplitView, QML_HAS_ATTACHED_PROPERTIES)
201QML_DECLARE_TYPEINFO(qml_material::SplitHandleAttached, QML_HAS_ATTACHED_PROPERTIES)