Border.cpp
Go to the documentation of this file.
1 #include "Border.hpp"
2 
3 #include "Axis.hpp"
4 
5 namespace iv
6 {
7 
9  OneChildElem< SlotChild >( inst ),
10  SlotChild( this ),
11  cm( inst, this, "Border", ClientMarker::Status() ),
12  attr_borderLeft( &this->cm ),
13  attr_borderRight( &this->cm ),
14  attr_borderTop( &this->cm ),
15  attr_borderBottom( &this->cm ),
16  attr_borderFront( &this->cm ),
17  attr_borderBack( &this->cm ),
18  insizeDirty( false )
19 {
21 }
22 
24 {
25  static iv::TableId DebugTable = TableId::create( "Border" );
26 
27  auto row = view->Table( DebugTable ).Row( this );
28 
29  row.Column( "borderLeft", this->attr_borderLeft.Get() );
30  row.Column( "borderRight", this->attr_borderRight.Get() );
31  row.Column( "borderTop", this->attr_borderTop.Get() );
32  row.Column( "borderBottom", this->attr_borderBottom.Get() );
33  row.Column( "borderFront", this->attr_borderFront.Get() );
34  row.Column( "borderBack", this->attr_borderBack.Get() );
35 }
36 
37 float3 Border::BorderSums() const
38 {
39  float3 sum;
40  sum.x = this->attr_borderLeft.Get().value_or( 0.0f ) + this->attr_borderRight.Get().value_or( 0.0f );
41  sum.y = this->attr_borderTop.Get().value_or( 0.0f ) + this->attr_borderBottom.Get().value_or( 0.0f );
42  sum.z = this->attr_borderFront.Get().value_or( 0.0f ) + this->attr_borderBack.Get().value_or( 0.0f );
43  return sum;
44 }
45 
47 {
48  bool border_changed = this->attr_borderLeft.dirty() || this->attr_borderRight.dirty()
49  || this->attr_borderTop.dirty() || this->attr_borderBottom.dirty()
50  || this->attr_borderFront.dirty() || this->attr_borderBack.dirty();
51 
52  //
53  float3 child_prefsize;
54  bool child_prefsize_changed = false;
55 
56  if( this->child.Get() )
57  {
58  if( this->child.dirty() || this->expectedSize.dirty() || border_changed )
59  {
60  this->expectedSize.clear_dirty();
61  this->child.Get()->expectedSize.Set( this->expectedSize.Get() - this->BorderSums() );
62  }
63 
64  this->child.Get()->elem()->first_pass( er );
65 
66  if( this->child.dirty() || this->child.Get()->preferredSize.dirty() )
67  {
69  child_prefsize_changed = true;
70  }
71  }
72  else if( this->child.dirty() )
73  {
74  child_prefsize_changed = true;
75  }
76 
77  if( child_prefsize_changed )
78  this->insizeDirty = true;
79 
80  if( child_prefsize_changed || border_changed )
81  {
82  float3 child_prefsize( 0, 0, 0 );
83  if( this->child.Get() )
84  child_prefsize = this->child.Get()->preferredSize.Get();
85 
86  this->preferredSize.Set( child_prefsize + this->BorderSums() );
87  }
88 
89  if( this->child.Get() )
90  if( this->child.dirty() || border_changed || this->insizeDirty || this->scissor.dirty() )
91  er->QueueSecondPass( this );
92 }
93 
94 void Border::inner_layout( float3 & out_size, float3 & out_position ) const
95 {
96  // prepare size computation
97  float3 prefsize = this->child.Get()->preferredSize.Get();
98  float3 size = this->size.Get();
99 
100  //
101  bool fail = false;
102 
103  // X
104  float borders_x_sum = this->attr_borderLeft.Get().value_or(0) + this->attr_borderRight.Get().value_or( 0 );
105  if( fail || borders_x_sum > size.x )
106  {
107  fail = true;
108  }
109  else
110  {
111  float inspace = size.x - borders_x_sum;
112  if( this->attr_borderLeft.Get().has_value() && this->attr_borderRight.Get().has_value() )
113  {
114  out_size.x = inspace;
115  out_position.x = this->attr_borderLeft.Get().value();
116  }
117  else
118  {
119  out_size.x = std::min( inspace, prefsize.x );
120 
121  if( this->attr_borderLeft.Get().has_value() )
122  out_position.x = this->attr_borderLeft.Get().value();
123  else if( this->attr_borderRight.Get().has_value() )
124  out_position.x = size.x - this->attr_borderRight.Get().value() - out_size.x;
125  else
126  out_position.x = ( size.x - out_size.x ) / 2.0f;
127  }
128  }
129 
130  // Y
131  float borders_y_sum = this->attr_borderTop.Get().value_or(0) + this->attr_borderBottom.Get().value_or(0);
132  if( fail || borders_y_sum > size.y )
133  {
134  fail = true;
135  }
136  else
137  {
138  float inspace = size.y - borders_y_sum;
139  if( this->attr_borderTop.Get().has_value() && this->attr_borderBottom.Get().has_value() )
140  {
141  out_size.y = inspace;
142  out_position.y = this->attr_borderTop.Get().value();
143  }
144  else
145  {
146  out_size.y = std::min( inspace, prefsize.y );
147 
148  if( this->attr_borderTop.Get().has_value() )
149  out_position.y = this->attr_borderTop.Get().value();
150  else if( this->attr_borderBottom.Get().has_value() )
151  out_position.y = size.y - this->attr_borderBottom.Get().value() - out_size.y;
152  else
153  out_position.y = ( size.y - out_size.y ) / 2.0f;
154  }
155  }
156 
157  // Z
158  float borders_z_sum = this->attr_borderFront.Get().value_or(0) + this->attr_borderBack.Get().value_or(0);
159  if( fail || borders_z_sum > size.z )
160  {
161  fail = true;
162  }
163  else
164  {
165  float inspace = size.z - borders_z_sum;
166  if( this->attr_borderFront.Get().has_value() && this->attr_borderBack.Get().has_value() )
167  {
168  out_size.z = inspace;
169  out_position.z = this->attr_borderFront.Get().value();
170  }
171  else
172  {
173  out_size.z = std::min( inspace, prefsize.z );
174 
175  if( this->attr_borderFront.Get().has_value() )
176  out_position.z = this->attr_borderFront.Get().value();
177  else if( this->attr_borderBack.Get().has_value() )
178  out_position.z = size.z - this->attr_borderBack.Get().value() - out_size.z;
179  else
180  out_position.z = ( size.z - out_size.z ) / 2.0f;
181  }
182  }
183 
184  if( fail )
185  {
186  out_size = float3( 0, 0, 0 );
187  out_position = float3( 0, 0, 0 );
188  }
189 }
190 
192 {
193  // delay any refreshes if there is no child
194  if( !this->child.Get() )
195  return;
196 
197  bool refresh = false;
198 
199  // refresh internal geometry
200  bool border_changed = this->attr_borderLeft.clear_dirty() + this->attr_borderRight.clear_dirty()
203 
204  if( this->size.clear_dirty() + border_changed + this->insizeDirty )
205  {
206  this->insizeDirty = false;
207 
208  //
209  er->Notify_SecondPass_Refresh( this );
210  refresh = true;
211 
212  //
213  this->inner_layout( this->insize, this->inpos );
214  }
215 
216  //
217  if( refresh || this->child.dirty() || this->modelTransform.dirty() || this->scissor.dirty() )
218  {
219  this->child.clear_dirty();
220  this->modelTransform.clear_dirty();
221  this->scissor.clear_dirty();
222 
223  this->child.Get()->elem()->modelTransform.Set( this->modelTransform.Get() * glm::translate( float4x4( 1 ), inpos ) );
224  this->child.Get()->elem()->scissor.Set( this->scissor.Get() );
225  this->child.Get()->size.Set( insize );
226  this->child.Get()->elem()->second_pass( er );
227  }
228 }
229 
230 Border * Border::enabled( bool val )
231 {
232  this->Elem::enabled( val );
233  return this;
234 }
235 
236 Border * Border::borderLeft( std::optional< float > val )
237 {
238  this->attr_borderLeft.Set( val );
239  return this;
240 }
241 
242 Border * Border::borderRight( std::optional< float > val )
243 {
244  this->attr_borderRight.Set( val );
245  return this;
246 }
247 
248 Border * Border::borderTop( std::optional< float > val )
249 {
250  this->attr_borderTop.Set( val );
251  return this;
252 }
253 
254 Border * Border::borderBottom( std::optional< float > val )
255 {
256  this->attr_borderBottom.Set( val );
257  return this;
258 }
259 
260 Border * Border::borderFront( std::optional< float > val )
261 {
262  this->attr_borderFront.Set( val );
263  return this;
264 }
265 
266 Border * Border::borderBack( std::optional< float > val )
267 {
268  this->attr_borderBack.Set( val );
269  return this;
270 }
271 
272 Border * Border::leftTop( std::optional< float > left, std::optional< float > top )
273 {
274  this->attr_borderLeft.Set( left );
275  this->attr_borderTop.Set( top );
276  return this;
277 }
278 
279 Border * Border::leftBottom( std::optional< float > left, std::optional< float > bottom )
280 {
281  this->attr_borderLeft.Set( left );
282  this->attr_borderBottom.Set( bottom );
283  return this;
284 }
285 
286 Border * Border::rightTop( std::optional< float > right, std::optional< float > top )
287 {
288  this->attr_borderRight.Set( right );
289  this->attr_borderTop.Set( top );
290  return this;
291 }
292 
293 Border * Border::rightBottom( std::optional< float > right, std::optional< float > bottom )
294 {
295  this->attr_borderRight.Set( right );
296  this->attr_borderBottom.Set( bottom );
297  return this;
298 }
299 
300 Border * Border::leftRight( std::optional< float > left, std::optional< float > right )
301 {
302  this->attr_borderLeft.Set( left );
303  this->attr_borderRight.Set( right );
304  return this;
305 }
306 
307 Border * Border::topBottom( std::optional< float > top, std::optional< float > bottom )
308 {
309  this->attr_borderTop.Set( top );
310  this->attr_borderBottom.Set( bottom );
311  return this;
312 }
313 
314 Border * Border::frontBack( std::optional< float > front, std::optional< float > back )
315 {
316  this->attr_borderFront.Set( front );
317  this->attr_borderBack.Set( back );
318  return this;
319 }
320 
321 }