1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * grid.cpp: canvas definitions.
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2008 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
23 #include "namescope.h"
24 #include "collection.h"
28 SetObjectType (Type::GRID
);
39 Grid::Clamp (double val
, double min
, double max
)
49 Grid::OnPropertyChanged (PropertyChangedEventArgs
*args
, MoonError
*error
)
51 if (args
->GetProperty ()->GetOwnerType() != Type::GRID
) {
52 Panel::OnPropertyChanged (args
, error
);
56 if (args
->GetId () == Grid::ShowGridLinesProperty
){
62 NotifyListenersOfPropertyChange (args
, error
);
66 Grid::OnCollectionChanged (Collection
*col
, CollectionChangedEventArgs
*args
)
68 if (col
== GetColumnDefinitions () ||
69 col
== GetRowDefinitions ()) {
72 Panel::OnCollectionChanged (col
, args
);
77 Grid::OnCollectionItemChanged (Collection
*col
, DependencyObject
*obj
, PropertyChangedEventArgs
*args
)
79 if (col
== GetChildren ()) {
80 if (args
->GetId () == Grid::ColumnProperty
81 || args
->GetId () == Grid::RowProperty
82 || args
->GetId () == Grid::ColumnSpanProperty
83 || args
->GetId () == Grid::RowSpanProperty
) {
86 // SL invalidates the measure on the child when these properties change.
87 // Tested by MeasureAutoRows2 and ChangingGridPropertiesInvalidates
88 ((UIElement
*) obj
)->InvalidateMeasure ();
91 } else if (col
== GetColumnDefinitions () || col
== GetRowDefinitions ()) {
92 if (args
->GetId() != ColumnDefinition::ActualWidthProperty
93 && args
->GetId() != RowDefinition::ActualHeightProperty
) {
99 Panel::OnCollectionItemChanged (col
, obj
, args
);
103 Grid::MeasureOverride (Size availableSize
)
105 Size totalSize
= availableSize
;
107 ColumnDefinitionCollection
*columns
= GetColumnDefinitions ();
108 RowDefinitionCollection
*rows
= GetRowDefinitions ();
109 bool free_col
= false;
110 bool free_row
= false;
112 int col_count
= columns
->GetCount ();
113 int row_count
= rows
->GetCount ();
114 Size total_stars
= Size (0,0);
116 if (col_count
== 0) {
117 columns
= new ColumnDefinitionCollection ();
118 ColumnDefinition
*coldef
= new ColumnDefinition ();
119 columns
->Add (coldef
);
125 if (row_count
== 0) {
126 rows
= new RowDefinitionCollection ();
127 RowDefinition
*rowdef
= new RowDefinition ();
134 CreateMatrices (row_count
, col_count
);
136 for (int i
= 0; i
< row_count
; i
++) {
137 RowDefinition
*rowdef
= rows
->GetValueAt (i
)->AsRowDefinition ();
138 GridLength
* height
= rowdef
->GetHeight();
140 rowdef
->SetActualHeight (INFINITY
);
141 row_matrix
[i
][i
] = Segment (0.0, rowdef
->GetMinHeight (), rowdef
->GetMaxHeight (), height
->type
);
143 if (height
->type
== GridUnitTypePixel
) {
144 row_matrix
[i
][i
].size
= Grid::Clamp (height
->val
, row_matrix
[i
][i
].min
, row_matrix
[i
][i
].max
);
145 rowdef
->SetActualHeight (row_matrix
[i
][i
].size
);
147 if (height
->type
== GridUnitTypeStar
) {
148 row_matrix
[i
][i
].stars
= height
->val
;
149 total_stars
.height
+= height
->val
;
153 for (int i
= 0; i
< col_count
; i
++) {
154 ColumnDefinition
*coldef
= columns
->GetValueAt (i
)->AsColumnDefinition ();
155 GridLength
*width
= coldef
->GetWidth ();
157 coldef
->SetActualWidth (INFINITY
);
158 col_matrix
[i
][i
] = Segment (0.0, coldef
->GetMinWidth (), coldef
->GetMaxWidth (), width
->type
);
160 if (width
->type
== GridUnitTypePixel
) {
161 col_matrix
[i
][i
].size
= Grid::Clamp (width
->val
, col_matrix
[i
][i
].min
, col_matrix
[i
][i
].max
);
162 coldef
->SetActualWidth (col_matrix
[i
][i
].size
);
164 if (width
->type
== GridUnitTypeStar
) {
165 col_matrix
[i
][i
].stars
= width
->val
;
166 total_stars
.width
+= width
->val
;
172 GridNode
*separator
= new GridNode (NULL
, 0, 0, 0);
173 sizes
.Append (separator
);
175 // Pre-process the grid children so that we know what types of elements we have so
176 // we can apply our special measuring rules.
177 GridWalker
grid_walker (this, row_matrix
, row_matrix_dim
, col_matrix
, col_matrix_dim
);
178 for (int i
= 0; i
< 6; i
++) {
179 // These bools tell us which grid element type we should be measuring. i.e.
180 // 'star/auto' means we should measure elements with a star row and auto col
181 bool auto_auto
= i
== 0;
182 bool star_auto
= i
== 1;
183 bool auto_star
= i
== 2;
184 bool star_auto_again
= i
== 3;
185 bool non_star
= i
== 4;
186 bool remaining_star
= i
== 5;
188 VisualTreeWalker walker
= VisualTreeWalker (this);
189 while (UIElement
*child
= walker
.Step ()) {
191 gint32 colspan
, rowspan
;
192 Size child_size
= Size (0,0);
193 bool star_col
= false;
194 bool star_row
= false;
195 bool auto_col
= false;
196 bool auto_row
= false;
198 col
= MIN (Grid::GetColumn (child
), col_count
- 1);
199 row
= MIN (Grid::GetRow (child
), row_count
- 1);
200 colspan
= MIN (Grid::GetColumnSpan (child
), col_count
- col
);
201 rowspan
= MIN (Grid::GetRowSpan (child
), row_count
- row
);
203 for (int r
= row
; r
< row
+ rowspan
; r
++) {
204 star_row
|= row_matrix
[r
][r
].type
== GridUnitTypeStar
;
205 auto_row
|= row_matrix
[r
][r
].type
== GridUnitTypeAuto
;
207 for (int c
= col
; c
< col
+ colspan
; c
++) {
208 star_col
|= col_matrix
[c
][c
].type
== GridUnitTypeStar
;
209 auto_col
|= col_matrix
[c
][c
].type
== GridUnitTypeAuto
;
212 // This series of if statements checks whether or not we should measure
213 // the current element and also if we need to override the sizes
214 // passed to the Measure call.
216 // If the element has Auto rows and Auto columns and does not span Star
217 // rows/cols it should only be measured in the auto_auto phase.
218 // There are similar rules governing auto/star and star/auto elements.
219 // NOTE: star/auto elements are measured twice. The first time with
220 // an override for height, the second time without it.
221 if (auto_row
&& auto_col
&& !star_row
&& !star_col
) {
224 child_size
.width
= INFINITY
;
225 child_size
.height
= INFINITY
;
227 else if (star_row
&& auto_col
) {
228 if (!(star_auto
|| star_auto_again
))
231 if (star_auto
&& grid_walker
.HasAutoStar ())
232 child_size
.height
= INFINITY
;
233 child_size
.width
= INFINITY
;
234 } else if (auto_row
&& star_col
&& !star_row
) {
238 child_size
.height
= INFINITY
;
239 } else if ((auto_row
|| auto_col
) && !(star_row
|| star_col
)) {
243 child_size
.height
= INFINITY
;
245 child_size
.width
= INFINITY
;
246 } else if (!(star_row
|| star_col
)) {
254 for (int r
= row
; r
< row
+ rowspan
; r
++) {
255 if (row_matrix
[r
][r
].type
== GridUnitTypeStar
) {
256 double v
= availableSize
.height
* row_matrix
[r
][r
].stars
/ total_stars
.height
;
257 child_size
.height
+= Grid::Clamp (v
, row_matrix
[r
][r
].min
, row_matrix
[r
][r
].max
);
259 child_size
.height
+= row_matrix
[r
][r
].size
;
262 for (int c
= col
; c
< col
+ colspan
; c
++) {
263 if (col_matrix
[c
][c
].type
== GridUnitTypeStar
) {
264 double v
= availableSize
.width
* col_matrix
[c
][c
].stars
/ total_stars
.width
;
265 child_size
.width
+= Grid::Clamp (v
, col_matrix
[c
][c
].min
, col_matrix
[c
][c
].max
);
267 child_size
.width
+= col_matrix
[c
][c
].size
;
271 child
->Measure (child_size
);
272 Size desired
= child
->GetDesiredSize();
274 // Elements distribute their height based on two rules:
275 // 1) Elements with rowspan/colspan == 1 distribute their height first
276 // 2) Everything else distributes in a LIFO manner.
277 // As such, add all UIElements with rowspan/colspan == 1 after the separator in
278 // the list and everything else before it. Then to process, just keep popping
279 // elements off the end of the list.
280 node
= new GridNode (row_matrix
, row
+ rowspan
- 1, row
, desired
.height
);
281 sizes
.InsertBefore (node
, node
->row
== node
->col
? separator
->next
: separator
);
283 node
= new GridNode (col_matrix
, col
+ colspan
- 1, col
, desired
.width
);
284 sizes
.InsertBefore (node
, node
->row
== node
->col
? separator
->next
: separator
);
287 sizes
.Unlink (separator
);
289 while (GridNode
*node
= (GridNode
*) sizes
.Last ()) {
290 node
->matrix
[node
->row
][node
->col
].size
= MAX (node
->matrix
[node
->row
][node
->col
].size
, node
->size
);
291 AllocateGridSegments (row_count
, col_count
);
295 // Calculate how much unused space we have so the next round of
296 // measurements uses the right sizes for Star segments
297 availableSize
= totalSize
;
298 for (int r
= 0; r
< row_matrix_dim
; r
++)
299 if (row_matrix
[r
][r
].type
!= GridUnitTypeStar
)
300 availableSize
.height
= MAX (availableSize
.height
- row_matrix
[r
][r
].size
, 0);
302 for (int c
= 0; c
< col_matrix_dim
; c
++)
303 if (col_matrix
[c
][c
].type
!= GridUnitTypeStar
)
304 availableSize
.width
= MAX (availableSize
.width
- col_matrix
[c
][c
].size
, 0);
306 sizes
.Append (separator
);
309 sizes
.Remove (separator
);
311 // We have to calulate the desired grid size before expanding
312 // star segments to consume available space.
313 Size grid_size
= Size (0, 0);
314 for (int c
= 0; c
< col_count
; c
++)
315 grid_size
.width
+= col_matrix
[c
][c
].size
;
316 for (int r
= 0; r
< row_count
; r
++)
317 grid_size
.height
+= row_matrix
[r
][r
].size
;
319 grid_size
= grid_size
.Max (GetWidth (), GetHeight ());
321 // This is where we do the final expansion of star rows. Right now the value
322 // of 'size' for star segments in row_matrix and col_matrix contains the
323 // size that the segments would naturally take up.
325 bool has_child
= GetChildren ()->GetCount () > 0;
326 if (columns
->GetCount () > 0)
327 TryExpandStarCols (totalSize
, !has_child
, !has_child
);
328 if (rows
->GetCount () > 0)
329 TryExpandStarRows (totalSize
, !has_child
, !has_child
);
337 // now choose whichever is smaller, our chosen size or the availableSize.
338 return totalSize
.Min (grid_size
);
342 Grid::TryExpandStarRows (Size availableSize
, bool force_width_nan
, bool force_height_nan
)
344 RowDefinitionCollection
*rows
= GetRowDefinitions ();
345 bool expand_stars
= GetVerticalAlignment () == VerticalAlignmentStretch
|| !isnan (GetHeight ());
346 if (force_height_nan
)
347 expand_stars
&= !isnan (GetHeight ());
349 if (expand_stars
&& availableSize
.height
!= INFINITY
) {
350 // When expanding star rows, we need to zero out their height before
351 // calling AssignSize. AssignSize takes care of distributing the
352 // available size when there are Mins and Maxs applied.
353 for (int i
= 0; i
< row_matrix_dim
; i
++) {
354 if (row_matrix
[i
][i
].type
== GridUnitTypeStar
)
355 row_matrix
[i
][i
].size
= 0.0;
357 availableSize
.height
= MAX (availableSize
.height
- row_matrix
[i
][i
].size
, 0);
360 AssignSize (row_matrix
, 0, row_matrix_dim
- 1, &availableSize
.height
, GridUnitTypeStar
);
361 if (rows
->GetCount () > 0) {
362 for (int i
= 0; i
< row_matrix_dim
; i
++)
363 if (row_matrix
[i
][i
].type
== GridUnitTypeStar
)
364 rows
->GetValueAt (i
)->AsRowDefinition ()->SetActualHeight (row_matrix
[i
][i
].size
);
370 Grid::TryExpandStarCols (Size availableSize
, bool force_width_nan
, bool force_height_nan
)
372 ColumnDefinitionCollection
*columns
= GetColumnDefinitions ();
373 bool expand_stars
= GetHorizontalAlignment () == HorizontalAlignmentStretch
|| !isnan (GetWidth ());
375 expand_stars
&= !isnan (GetWidth ());
377 if (expand_stars
&& availableSize
.width
!= INFINITY
) {
378 for (int i
= 0; i
< col_matrix_dim
; i
++) {
379 if (col_matrix
[i
][i
].type
== GridUnitTypeStar
)
380 col_matrix
[i
][i
].size
= 0;
382 availableSize
.width
= MAX (availableSize
.width
- col_matrix
[i
][i
].size
, 0);
385 AssignSize (col_matrix
, 0, col_matrix_dim
- 1, &availableSize
.width
, GridUnitTypeStar
);
387 if (columns
->GetCount () > 0) {
388 for (int i
= 0; i
< col_matrix_dim
; i
++)
389 if (col_matrix
[i
][i
].type
== GridUnitTypeStar
)
390 columns
->GetValueAt (i
)->AsColumnDefinition ()->SetActualWidth (col_matrix
[i
][i
].size
);
396 Grid::AllocateGridSegments (int row_count
, int col_count
)
398 // First allocate the heights of the RowDefinitions, then allocate
399 // the widths of the ColumnDefinitions.
400 for (int i
= 0; i
< 2; i
++) {
401 Segment
**matrix
= i
== 0 ? row_matrix
: col_matrix
;
402 int count
= i
== 0 ? row_count
: col_count
;
404 for (int row
= count
- 1; row
>= 0; row
--) {
405 for (int col
= row
; col
>= 0; col
--) {
406 bool spans_star
= false;
407 for (int j
= row
; j
>= col
; j
--)
408 spans_star
|= matrix
[j
][j
].type
== GridUnitTypeStar
;
410 // This is the amount of pixels which must be available between the grid rows
411 // at index 'col' and 'row'. i.e. if 'row' == 0 and 'col' == 2, there must
412 // be at least 'matrix [row][col].size' pixels of height allocated between
413 // all the rows in the range col -> row.
414 double current
= matrix
[row
][col
].size
;
416 // Count how many pixels have already been allocated between the grid rows
417 // in the range col -> row. The amount of pixels allocated to each grid row/column
418 // is found on the diagonal of the matrix.
419 double total_allocated
= 0;
420 for (int i
= row
; i
>= col
; i
--)
421 total_allocated
+= matrix
[i
][i
].size
;
423 // If the size requirement has not been met, allocate the additional required
424 // size between 'pixel' rows, then 'star' rows, finally 'auto' rows, until all
425 // height has been assigned.
426 if (total_allocated
< current
) {
427 double additional
= current
- total_allocated
;
429 AssignSize (matrix
, col
, row
, &additional
, GridUnitTypeStar
);
431 AssignSize (matrix
, col
, row
, &additional
, GridUnitTypePixel
);
432 AssignSize (matrix
, col
, row
, &additional
, GridUnitTypeAuto
);
441 Grid::AssignSize (Segment
**matrix
, int start
, int end
, double *size
, GridUnitType type
)
446 // Count how many segments are of the correct type. If we're measuring Star rows/cols
447 // we need to count the number of stars instead.
448 for (int i
= start
; i
<= end
; i
++)
449 if (matrix
[i
][i
].type
== type
&& matrix
[i
][i
].size
< matrix
[i
][i
].max
)
450 count
+= type
== GridUnitTypeStar
? matrix
[i
][i
].stars
: 1;
454 double contribution
= *size
/ count
;
456 for (int i
= start
; i
<= end
; i
++) {
457 if (!(matrix
[i
][i
].type
== type
&& matrix
[i
][i
].size
< matrix
[i
][i
].max
))
459 double newsize
= matrix
[i
][i
].size
;
460 newsize
+= contribution
* (type
== GridUnitTypeStar
? matrix
[i
][i
].stars
: 1);
461 newsize
= MIN (newsize
, matrix
[i
][i
].max
);
462 assigned
|= newsize
> matrix
[i
][i
].size
;
463 *size
-= newsize
- matrix
[i
][i
].size
;
464 matrix
[i
][i
].size
= newsize
;
470 Grid::DestroyMatrices ()
472 if (row_matrix
!= NULL
) {
473 for (int i
= 0; i
< row_matrix_dim
; i
++)
474 delete [] row_matrix
[i
];
475 delete [] row_matrix
;
479 if (col_matrix
!= NULL
) {
480 for (int i
= 0; i
< col_matrix_dim
; i
++)
481 delete [] col_matrix
[i
];
482 delete [] col_matrix
;
488 Grid::CreateMatrices (int row_count
, int col_count
)
492 row_matrix_dim
= row_count
;
493 col_matrix_dim
= col_count
;
495 row_matrix
= new Segment
*[row_count
];
496 for (int i
= 0; i
< row_count
; i
++) {
497 row_matrix
[i
] = new Segment
[row_count
];
498 for (int j
= 0; j
< row_count
; j
++)
499 row_matrix
[i
][j
] = Segment ();
502 col_matrix
= new Segment
*[col_count
];
503 for (int i
= 0; i
< col_count
; i
++) {
504 col_matrix
[i
] = new Segment
[col_count
];
505 for (int j
= 0; j
< col_count
; j
++)
506 col_matrix
[i
][j
] = Segment ();
511 Grid::ComputeBounds ()
513 Panel::ComputeBounds ();
515 if (GetShowGridLines ()) {
516 extents
= Rect (0,0,GetActualWidth (),GetActualHeight ());
517 bounds
= IntersectBoundsWithClipPath (extents
, false).Transform (&absolute_xform
);
518 bounds_with_children
= bounds_with_children
.Union (bounds
);
522 Grid::PostRender (cairo_t
*cr
, Region
*region
, bool front_to_back
)
524 // render our chidren if not in front to back mode
525 if (!front_to_back
) {
526 VisualTreeWalker walker
= VisualTreeWalker (this, ZForward
);
527 while (UIElement
*child
= walker
.Step ())
528 child
->DoRender (cr
, region
);
531 if (GetShowGridLines ()) {
534 ColumnDefinitionCollection
*cols
= GetColumnDefinitions ();
535 RowDefinitionCollection
*rows
= GetRowDefinitions ();
537 cairo_set_line_width(cr
, 1.0);
538 // Initially render a blue color
539 cairo_set_dash (cr
, &dash
, 1, offset
);
540 cairo_set_source_rgb (cr
, 0.4, 0.4, 1.0);
542 // Draw gridlines between each pair of columns/rows
543 for (int count
= 0; count
< 2; count
++) {
545 for (int i
= 0, offset
= 0; i
< cols
->GetCount () - 1; i
++) {
546 ColumnDefinition
*def
= cols
->GetValueAt (i
)->AsColumnDefinition ();
547 offset
+= def
->GetActualWidth ();
548 cairo_move_to (cr
, offset
, 0);
549 cairo_line_to (cr
, offset
, GetActualHeight ());
552 for (int i
= 0, offset
= 0; i
< rows
->GetCount () -1; i
++) {
553 RowDefinition
*def
= rows
->GetValueAt (i
)->AsRowDefinition ();
554 offset
+= def
->GetActualHeight ();
555 cairo_move_to (cr
, 0, offset
);
556 cairo_line_to (cr
, GetActualWidth (), offset
);
561 // For the second pass render a yellow color in the gaps between the previous dashes
562 cairo_set_dash (cr
, &dash
, 1, dash
);
563 cairo_set_source_rgb (cr
, 1.0, 1.0, 0.3);
567 // Chain up in front_to_back mode since we've alread rendered content
568 UIElement::PostRender (cr
, region
, true);
572 Grid::ArrangeOverride (Size finalSize
)
574 ColumnDefinitionCollection
*columns
= GetColumnDefinitions ();
575 RowDefinitionCollection
*rows
= GetRowDefinitions ();
577 int col_count
= columns
->GetCount ();
578 int row_count
= rows
->GetCount ();
580 HorizontalAlignment horiz
= !isnan (GetWidth ()) ? HorizontalAlignmentStretch
: GetHorizontalAlignment ();
581 VerticalAlignment vert
= !isnan (GetHeight ()) ? VerticalAlignmentStretch
: GetVerticalAlignment ();
583 Size total_consumed
= Size (0, 0);
584 for (int c
= 0; c
< col_matrix_dim
; c
++)
585 total_consumed
.width
+= col_matrix
[c
][c
].size
;
586 for (int r
= 0; r
< row_matrix_dim
; r
++)
587 total_consumed
.height
+= row_matrix
[r
][r
].size
;
589 if (total_consumed
.width
!= finalSize
.width
)
590 TryExpandStarCols (finalSize
, false, false);
591 if (total_consumed
.height
!= finalSize
.height
)
592 TryExpandStarRows (finalSize
, false, false);
594 for (int c
= 0; c
< col_count
; c
++)
595 columns
->GetValueAt (c
)->AsColumnDefinition ()->SetActualWidth (col_matrix
[c
][c
].size
);
596 for (int r
= 0; r
< row_count
; r
++)
597 rows
->GetValueAt (r
)->AsRowDefinition ()->SetActualHeight (row_matrix
[r
][r
].size
);
600 Size arranged
= finalSize
;
602 VisualTreeWalker walker
= VisualTreeWalker (this);
603 while (UIElement
*child
= walker
.Step ()) {
604 gint32 col
= MIN (Grid::GetColumn (child
), col_matrix_dim
- 1);
605 gint32 row
= MIN (Grid::GetRow (child
), row_matrix_dim
- 1);
606 gint32 colspan
= MIN (Grid::GetColumnSpan (child
), col_matrix_dim
- col
);
607 gint32 rowspan
= MIN (Grid::GetRowSpan (child
), row_matrix_dim
- row
);
609 Rect child_final
= Rect (0, 0, 0, 0);
618 for (int c
= 0; c
< col
+ colspan
; c
++) {
620 child_final
.x
+= col_matrix
[c
][c
].size
;
622 child_final
.width
+= col_matrix
[c
][c
].size
;
624 min_size
.width
+= col_matrix
[c
][c
].min
;
625 max_size
.width
+= col_matrix
[c
][c
].size
;;
629 for (int r
= 0; r
< row
+ rowspan
; r
++) {
631 child_final
.y
+= row_matrix
[r
][r
].size
;
633 child_final
.height
+= row_matrix
[r
][r
].size
;
635 min_size
.height
+= row_matrix
[r
][r
].min
;
636 max_size
.height
+= row_matrix
[r
][r
].max
;
640 child
->Arrange (child_final
);
642 if (horiz
== HorizontalAlignmentStretch
)
643 arranged
.width
= MAX (child_final
.x
+ child_final
.width
, finalSize
.width
);
645 arranged
.width
= MAX (child_final
.x
+ child_final
.width
, arranged
.width
);
647 if (vert
== VerticalAlignmentStretch
)
648 arranged
.height
= MAX (child_final
.y
+ child_final
.height
, finalSize
.height
);
650 arranged
.height
= MAX (child_final
.y
+ child_final
.height
, arranged
.height
);
657 // ColumnDefinitionCollection
660 ColumnDefinitionCollection::ColumnDefinitionCollection ()
662 SetObjectType (Type::COLUMNDEFINITION_COLLECTION
);
665 ColumnDefinitionCollection::~ColumnDefinitionCollection ()
670 ColumnDefinitionCollection::AddedToCollection (Value
*value
, MoonError
*error
)
672 if (Contains (value
)) {
673 MoonError::FillIn (error
, MoonError::ARGUMENT
, "ColumnDefinition is already a member of this collection.");
676 return DependencyObjectCollection::AddedToCollection (value
, error
);
683 ColumnDefinition::ColumnDefinition ()
685 SetObjectType (Type::COLUMNDEFINITION
);
688 ColumnDefinition::~ColumnDefinition ()
693 // RowDefinitionCollection
696 RowDefinitionCollection::RowDefinitionCollection ()
698 SetObjectType (Type::ROWDEFINITION_COLLECTION
);
701 RowDefinitionCollection::~RowDefinitionCollection ()
706 RowDefinitionCollection::AddedToCollection (Value
*value
, MoonError
*error
)
708 if (Contains (value
)) {
709 MoonError::FillIn (error
, MoonError::ARGUMENT
, "RowDefinition is already a member of this collection.");
712 return DependencyObjectCollection::AddedToCollection (value
, error
);
719 RowDefinition::RowDefinition ()
721 SetObjectType (Type::ROWDEFINITION
);
724 RowDefinition::~RowDefinition ()
730 Init (0.0, 0.0, INFINITY
, GridUnitTypePixel
);
733 Segment::Segment (double size
, double min
, double max
, GridUnitType type
)
735 Init (size
, min
, max
, type
);
739 Segment::Init (double size
, double min
, double max
, GridUnitType type
)
746 this->size
= Grid::Clamp (size
, min
, max
);
749 GridWalker::GridWalker (Grid
*grid
, Segment
**row_matrix
, int row_count
, Segment
**col_matrix
, int col_count
)
751 has_auto_auto
= false;
752 has_star_auto
= false;
753 has_auto_star
= false;
755 VisualTreeWalker
walker (grid
);
756 while (UIElement
*child
= walker
.Step ()) {
757 bool star_col
= false;
758 bool star_row
= false;
759 bool auto_col
= false;
760 bool auto_row
= false;
762 gint32 col
= MIN (Grid::GetColumn (child
), col_count
- 1);
763 gint32 row
= MIN (Grid::GetRow (child
), row_count
- 1);
764 gint32 colspan
= MIN (Grid::GetColumnSpan (child
), col_count
- col
);
765 gint32 rowspan
= MIN (Grid::GetRowSpan (child
), row_count
- row
);
767 for (int r
= row
; r
< row
+ rowspan
; r
++) {
768 star_row
|= row_matrix
[r
][r
].type
== GridUnitTypeStar
;
769 auto_row
|= row_matrix
[r
][r
].type
== GridUnitTypeAuto
;
771 for (int c
= col
; c
< col
+ colspan
; c
++) {
772 star_col
|= col_matrix
[c
][c
].type
== GridUnitTypeStar
;
773 auto_col
|= col_matrix
[c
][c
].type
== GridUnitTypeAuto
;
776 has_auto_auto
|= auto_row
&& auto_col
&& !star_row
&& !star_col
;
777 has_star_auto
|= star_row
&& auto_col
;
778 has_auto_star
|= auto_row
&& star_col
;