FCT
载入中...
搜索中...
未找到
SizeNode.h
浏览该文件的文档.
1#ifndef SIZENODE_H
2#define SIZENODE_H
4namespace FCT
5{
6 struct SizeNode {
7 virtual ~SizeNode() = default;
8 mutable SizeNode* parent;
9 mutable uint32_t width;
10 mutable uint32_t height;
11 mutable bool sizeFixed; // 大小是否已固定(不能再改变)
12 mutable FractionScale2D scaleToParent; // 相对于父节点的缩放比例
13
14 SizeNode() noexcept
15 : parent(this), width(0), height(0), sizeFixed(false), scaleToParent() {}
16
17 SizeNode(uint32_t w, uint32_t h) noexcept
18 : parent(this), width(w), height(h), sizeFixed(true), scaleToParent() {}
19
20 SizeNode* findRoot() const noexcept {
21 if (parent != this) {
23 parent = parent->findRoot();
24 scaleToParent = oldScale * parent->scaleToParent;
25 }
26 return parent;
27 }
28
30 if (parent == this) {
31 return FractionScale2D();
32 }
33
34 findRoot();
35 return scaleToParent;
36 }
37
45 bool unite(SizeNode* other, const FractionScale2D& scale = FractionScale2D()) const noexcept {
46 SizeNode* rootA = findRoot();
47 SizeNode* rootB = other->findRoot();
48
49 if (rootA == rootB) {
50 FractionScale2D expectedScale = getScaleToRoot() / other->getScaleToRoot();
51 return expectedScale == scale;
52 }
53
54 SizeNode* newRoot;
55 SizeNode* childRoot;
56 FractionScale2D childScale;
57
58 if (rootA->sizeFixed && !rootB->sizeFixed) {
59 newRoot = rootA;
60 childRoot = rootB;
61 FractionScale2D thisScale = getScaleToRoot();
62 FractionScale2D otherScale = other->getScaleToRoot();
63 childScale = thisScale / (otherScale * scale);
64 } else if (!rootA->sizeFixed && rootB->sizeFixed) {
65 newRoot = rootB;
66 childRoot = rootA;
67 FractionScale2D thisScale = getScaleToRoot();
68 FractionScale2D otherScale = other->getScaleToRoot();
69 childScale = (otherScale * scale) / thisScale;
70 } else if (rootA->sizeFixed && rootB->sizeFixed) {
71 FractionScale2D thisScale = getScaleToRoot();
72 FractionScale2D otherScale = other->getScaleToRoot();
73
74 uint32_t expectedWidth = static_cast<uint32_t>(
75 rootB->width * otherScale.width.toFloat() * scale.width.toFloat() / thisScale.width.toFloat()
76 );
77 uint32_t expectedHeight = static_cast<uint32_t>(
78 rootB->height * otherScale.height.toFloat() * scale.height.toFloat() / thisScale.height.toFloat()
79 );
80
81 if (rootA->width != expectedWidth || rootA->height != expectedHeight) {
82 return false;
83 }
84
85 newRoot = rootA;
86 childRoot = rootB;
87 childScale = (otherScale * scale) / thisScale;
88 } else {
89 newRoot = rootA;
90 childRoot = rootB;
91 FractionScale2D thisScale = getScaleToRoot();
92 FractionScale2D otherScale = other->getScaleToRoot();
93 childScale = (otherScale * scale) / thisScale;
94 }
95
96 childRoot->parent = newRoot;
97 childRoot->scaleToParent = childScale;
98
99 return true;
100 }
101
102 bool setFixed() const noexcept {
103 SizeNode* root = findRoot();
104
105 if (root->sizeFixed) {
106 return false;
107 }
108
109 root->sizeFixed = true;
110 root->width = 0;
111 root->height = 0;
112
113 return true;
114 }
115
116 bool setFixedSize(uint32_t w, uint32_t h) const noexcept {
117 SizeNode* root = findRoot();
118
119 if (root->sizeFixed) {
121 uint32_t expectedWidth = static_cast<uint32_t>(root->width * scale.width.toFloat());
122 uint32_t expectedHeight = static_cast<uint32_t>(root->height * scale.height.toFloat());
123
124 return (expectedWidth == w && expectedHeight == h);
125 }
126
128 root->width = static_cast<uint32_t>(w / scale.width.toFloat());
129 root->height = static_cast<uint32_t>(h / scale.height.toFloat());
130 root->sizeFixed = true;
131
132 return true;
133 }
134
135 bool getComputedSize(uint32_t& w, uint32_t& h) const noexcept {
136 SizeNode* root = findRoot();
137
138 if (!root->sizeFixed) {
139 return false;
140 }
141
143 w = static_cast<uint32_t>(root->width * scale.width.toFloat());
144 h = static_cast<uint32_t>(root->height * scale.height.toFloat());
145
146 return true;
147 }
148
149 bool isSizeDetermined() const noexcept {
150 return findRoot()->sizeFixed;
151 }
152
153 const SizeNode* getRoot() const noexcept {
154 return findRoot();
155 }
156
157 bool isConnected(const SizeNode* other) const noexcept {
158 return findRoot() == other->findRoot();
159 }
160 bool isSameSize(const SizeNode* other) const noexcept
161 {
162 return findRoot() == other->findRoot() && getScaleToRoot() == other->getScaleToRoot();
163 }
164
165 FractionScale2D getRelativeScale(const SizeNode* other) const noexcept {
166 if (!isConnected(other)) {
167 return FractionScale2D(Fraction(0, 1), Fraction(0, 1));
168 }
169
170 return getScaleToRoot() / other->getScaleToRoot();
171 }
172 };
173} // namespace FCT
174#endif //SIZENODE_H
float toFloat() const noexcept
bool setFixed() const noexcept
const SizeNode * getRoot() const noexcept
SizeNode() noexcept
FractionScale2D getScaleToRoot() const noexcept
bool isConnected(const SizeNode *other) const noexcept
FractionScale2D getRelativeScale(const SizeNode *other) const noexcept
bool isSizeDetermined() const noexcept
bool isSameSize(const SizeNode *other) const noexcept
virtual ~SizeNode()=default
FractionScale2D scaleToParent
SizeNode(uint32_t w, uint32_t h) noexcept
SizeNode * findRoot() const noexcept
bool unite(SizeNode *other, const FractionScale2D &scale=FractionScale2D()) const noexcept
bool setFixedSize(uint32_t w, uint32_t h) const noexcept
bool getComputedSize(uint32_t &w, uint32_t &h) const noexcept
SizeNode * parent