1 /* Copyright (c) 2019 Samsung Electronics Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
7 * http://www.apache.org/licenses/LICENSE-2.0
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
18 using Tizen.NUI.BaseComponents;
19 using System.Collections.Generic;
24 /// [Draft] This class implements a linear box layout, automatically handling right to left or left to right direction change.
26 internal class LinearLayout : LayoutGroup
29 /// [Draft] Enumeration for the direction in which the content is laid out
31 public enum Orientation
44 /// [Draft] Enumeration for the alignment of the linear layout items
49 /// At the left/right edge of the container (maps to LTR/RTL direction for horizontal orientation)
53 /// At the right/left edge of the container (maps to LTR/RTL direction for horizontal orientation)
57 /// At the horizontal center of the container
59 CenterHorizontal = 0x4,
61 /// At the top edge of the container
65 /// At the bottom edge of the container
69 /// At the vertical center of the container
74 struct HeightAndWidthState
76 public MeasuredSize.StateType widthState;
77 public MeasuredSize.StateType heightState;
79 public HeightAndWidthState( MeasuredSize.StateType width, MeasuredSize.StateType height)
87 /// [Draft] Get/Set the orientation in the layout
89 public LinearLayout.Orientation LinearOrientation
93 return _linearOrientation;
97 _linearOrientation = value;
103 /// [Draft] Get/Set the padding between cells in the layout
105 public Size2D CellPadding
113 _cellPadding = value;
120 /// [Draft] Get/Set the alignment in the layout
122 public LinearLayout.Alignment LinearAlignment{ get; set; } = Alignment.CenterVertical;
124 private float _totalLength = 0.0f;
125 private Size2D _cellPadding = new Size2D(0,0);
126 private Orientation _linearOrientation = Orientation.Horizontal;
129 /// [Draft] Constructor
131 public LinearLayout()
135 protected override void OnMeasure(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
137 if (_linearOrientation == Orientation.Horizontal)
139 MeasureHorizontal(widthMeasureSpec, heightMeasureSpec);
143 MeasureVertical(widthMeasureSpec, heightMeasureSpec);
147 protected override void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom)
149 if (_linearOrientation == Orientation.Horizontal)
151 LayoutHorizontal(left, top, right, bottom);
155 LayoutVertical(left, top, right, bottom);
159 private void MeasureHorizontal(MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec)
161 var widthMode = widthMeasureSpec.Mode;
162 var heightMode = heightMeasureSpec.Mode;
163 bool isExactly = ( widthMode == MeasureSpecification.ModeType.Exactly );
164 bool matchHeight = false;
165 bool allFillParent = true;
166 float maxHeight = 0.0f;
167 float alternativeMaxHeight = 0.0f;
168 float weightedMaxHeight = 0.0f;
169 float totalWeight = 0.0f;
171 // Reset total length
173 LayoutLength usedExcessSpace = new LayoutLength(0);
175 HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK,
176 MeasuredSize.StateType.MeasuredSizeOK);
178 // Measure children, and determine if further resolution is required
181 // We cycle through all children and measure children with weight 0 (non weighted children) according to their specs
182 // to accumulate total used space in totalLength based on measured sizes and margins.
183 // Weighted children are not measured at this phase.
184 // Available space for weighted children will be calculated in the phase 2 based on totalLength value.
186 foreach( LayoutItem childLayout in _children )
188 LayoutLength childDesiredWidth = new LayoutLength(childLayout.Owner.WidthSpecification);
189 LayoutLength childDesiredHeight = new LayoutLength(childLayout.Owner.HeightSpecification);
190 float childWeight = childLayout.Owner.Weight;
191 Extents childMargin = childLayout.Margin;
192 totalWeight += childWeight;
194 bool useExcessSpace = (childDesiredWidth.AsRoundedValue() == 0 ) && (childWeight > 0);
195 if( isExactly && useExcessSpace )
197 _totalLength += childMargin.Start + childMargin.End;
203 // The widthMode is either UNSPECIFIED or AT_MOST, and
204 // this child is only laid out using excess space. Measure
205 // using WRAP_CONTENT so that we can find out the view's
207 MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification(widthMeasureSpec, new LayoutLength(childLayout.Padding.Start + childLayout.Padding.End),
208 new LayoutLength(LayoutParamPolicies.WrapContent) );
209 MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification(heightMeasureSpec, new LayoutLength(childLayout.Padding.Top + childLayout.Padding.Bottom),
211 childLayout.Measure( childWidthMeasureSpec, childHeightMeasureSpec);
212 usedExcessSpace += childLayout.MeasuredWidth.Size;
216 MeasureChild(childLayout, widthMeasureSpec, heightMeasureSpec);
218 LayoutLength childWidth = childLayout.MeasuredWidth.Size;
220 LayoutLength length = childWidth + childMargin.Start + childMargin.End;
223 _totalLength += length.AsDecimal();
227 _totalLength = Math.Max(_totalLength, _totalLength + length.AsDecimal() + CellPadding.Width);
231 bool matchHeightLocally = false;
232 if(heightMode != MeasureSpecification.ModeType.Exactly && (int)childDesiredHeight.AsRoundedValue() == LayoutParamPolicies.MatchParent)
234 // Will have to re-measure at least this child when we know exact height.
236 matchHeightLocally = true;
239 LayoutLength marginHeight = new LayoutLength(childMargin.Top + childMargin.Bottom);
240 LayoutLength childHeight = childLayout.MeasuredHeight.Size + marginHeight;
242 if( childLayout.MeasuredWidthAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall )
244 childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall;
246 if( childLayout.MeasuredHeightAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
248 childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall;
251 maxHeight = Math.Max( maxHeight, childHeight.AsDecimal());
252 allFillParent = ( allFillParent && childDesiredHeight.AsRoundedValue() == LayoutParamPolicies.MatchParent );
254 if( childWeight > 0 )
257 * Heights of weighted Views are bogus if we end up
258 * remeasuring, so keep them separate.
260 weightedMaxHeight = Math.Max( weightedMaxHeight, matchHeightLocally ? marginHeight.AsDecimal() : childHeight.AsDecimal());
264 alternativeMaxHeight = Math.Max( alternativeMaxHeight, matchHeightLocally ? marginHeight.AsDecimal() : childHeight.AsDecimal() );
268 Extents padding = Padding;
269 _totalLength += padding.Start + padding.End;
270 LayoutLength widthSize = new LayoutLength(_totalLength);
271 widthSize = new LayoutLength( Math.Max( widthSize.AsDecimal(), SuggestedMinimumWidth.AsDecimal()));
272 MeasuredSize widthSizeAndState = ResolveSizeAndState( widthSize, widthMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK);
273 widthSize = widthSizeAndState.Size;
275 if (!allFillParent && heightMode != MeasureSpecification.ModeType.Exactly)
277 maxHeight = alternativeMaxHeight;
279 maxHeight += padding.Top + padding.Bottom;
280 maxHeight = Math.Max( maxHeight, SuggestedMinimumHeight.AsRoundedValue() );
282 widthSizeAndState.State = childState.widthState;
284 SetMeasuredDimensions(widthSizeAndState,
285 ResolveSizeAndState( new LayoutLength(maxHeight), heightMeasureSpec, childState.heightState ));
289 ForceUniformHeight( _children.Count, widthMeasureSpec );
291 } // MeasureHorizontally
293 void MeasureVertical( MeasureSpecification widthMeasureSpec, MeasureSpecification heightMeasureSpec )
295 var widthMode = widthMeasureSpec.Mode;
296 var heightMode = heightMeasureSpec.Mode;
297 bool isExactly = ( heightMode == MeasureSpecification.ModeType.Exactly);
298 bool matchWidth = false;
299 bool allFillParent = true;
300 float maxWidth = 0.0f;
301 float alternativeMaxWidth = 0.0f;
302 float weightedMaxWidth = 0.0f;
303 float totalWeight = 0.0f;
305 // Reset total length
307 LayoutLength usedExcessSpace = new LayoutLength(0);
309 HeightAndWidthState childState = new HeightAndWidthState(MeasuredSize.StateType.MeasuredSizeOK,
310 MeasuredSize.StateType.MeasuredSizeTooSmall);
313 // measure children, and determine if further resolution is required
316 // We cycle through all children and measure children with weight 0 (non weighted children) according to their specs
317 // to accumulate total used space in mTotalLength based on measured sizes and margins.
318 // Weighted children are not measured at this phase.
319 // Available space for weighted children will be calculated in the phase 2 based on mTotalLength value.
321 foreach( LayoutItem childLayout in _children )
323 LayoutLength childDesiredWidth = new LayoutLength(childLayout.Owner.WidthSpecification);
324 LayoutLength childDesiredHeight = new LayoutLength(childLayout.Owner.HeightSpecification);
325 float childWeight = childLayout.Owner.Weight;
326 Extents childMargin = childLayout.Margin;
327 totalWeight += childWeight;
329 bool useExcessSpace = (childDesiredHeight.AsRoundedValue() == 0) && (childWeight > 0);
331 if( isExactly && useExcessSpace )
333 LayoutLength totalLength = new LayoutLength(_totalLength);
334 _totalLength = Math.Max( totalLength.AsDecimal(), (totalLength + childMargin.Top + childMargin.Bottom).AsDecimal() );
338 LayoutLength childHeight = new LayoutLength(0);
341 // The heightMode is either Unspecified or AtMost, and
342 // this child is only laid out using excess space. Measure
343 // using WrapContent so that we can find out the view's
344 // optimal height. We'll restore the original height of 0
345 // after measurement.
346 MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification( widthMeasureSpec,
347 new LayoutLength(childLayout.Padding.Start + childLayout.Padding.End),
349 MeasureSpecification childHeightMeasureSpec = GetChildMeasureSpecification( heightMeasureSpec,
350 new LayoutLength(childLayout.Padding.Top + childLayout.Padding.Bottom),
351 new LayoutLength(LayoutParamPolicies.WrapContent) );
352 childLayout.Measure( childWidthMeasureSpec, childHeightMeasureSpec );
353 childHeight = childLayout.MeasuredHeight.Size;
354 usedExcessSpace += childHeight;
358 MeasureChild( childLayout, widthMeasureSpec, heightMeasureSpec );
359 childHeight = childLayout.MeasuredHeight.Size;
362 float length = (childHeight + childMargin.Top + childMargin.Bottom).AsDecimal();
363 float cellPadding = CellPadding.Height;
364 // No need to add cell padding to the end of last item.
365 if (index>=_children.Count-1)
369 _totalLength = Math.Max( _totalLength, _totalLength + length + cellPadding );
372 bool matchWidthLocally = false;
373 if( widthMode != MeasureSpecification.ModeType.Exactly && childDesiredWidth == new LayoutLength(LayoutParamPolicies.MatchParent) )
375 // Will have to re-measure at least this child when we know exact height.
377 matchWidthLocally = true;
380 float marginWidth = (childLayout.Margin.Start) + (childLayout.Margin.End);
381 LayoutLength childWidth = new LayoutLength(childLayout.MeasuredWidth.Size.AsDecimal() + marginWidth);
383 // was combineMeasuredStates()
384 if (childLayout.MeasuredWidthAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
386 childState.widthState = MeasuredSize.StateType.MeasuredSizeTooSmall;
388 if (childLayout.MeasuredHeightAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
390 childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall;
393 maxWidth = (Math.Max( maxWidth, childWidth.AsDecimal()));
394 allFillParent = (allFillParent && (childDesiredWidth == new LayoutLength(LayoutParamPolicies.MatchParent)));
396 float widthforWeight = childWidth.AsDecimal();
397 if (matchWidthLocally)
399 widthforWeight = marginWidth;
405 * Widths of weighted Views are bogus if we end up remeasuring, so keep them separate.
407 weightedMaxWidth = Math.Max( weightedMaxWidth, widthforWeight);
411 alternativeMaxWidth = Math.Max( alternativeMaxWidth, widthforWeight);
416 Extents padding = Padding;
417 _totalLength += padding.Top + padding.Bottom;
418 LayoutLength heightSize = new LayoutLength(_totalLength);
419 heightSize = new LayoutLength(Math.Max( heightSize.AsDecimal(), SuggestedMinimumHeight.AsDecimal() ));
420 MeasuredSize heightSizeAndState = ResolveSizeAndState( heightSize, heightMeasureSpec, MeasuredSize.StateType.MeasuredSizeOK);
421 heightSize = heightSizeAndState.Size;
423 // Either expand children with weight to take up available space or
424 // shrink them if they extend beyond our current bounds. If we skipped
425 // measurement on any children, we need to measure them now.
428 // We cycle through weighted children now (children with weight > 0).
429 // The children are measured with exact size equal to their share of the available space based on their weights.
430 // TotalLength is updated to include weighted children measured sizes.
432 float remainingExcess = heightSize.AsDecimal() - _totalLength + usedExcessSpace.AsDecimal();
434 if( remainingExcess != 0 && totalWeight > 0.0f )
436 float remainingWeightSum = totalWeight;
440 foreach( LayoutItem childLayout in _children )
442 int desiredWidth = childLayout.Owner.WidthSpecification;
443 int desiredHeight = childLayout.Owner.HeightSpecification;
444 float childWeight = childLayout.Owner.Weight;
445 Extents childMargin = childLayout.Margin;
447 float childHeight = 0;
448 if( childWeight > 0 )
450 float share = ( childWeight * remainingExcess ) / remainingWeightSum;
451 remainingExcess -= share;
452 remainingWeightSum -= childWeight;
454 // Always lay out weighted elements with intrinsic size regardless of the parent spec
455 // for consistency between specs.
456 if( desiredHeight == 0 )
458 // This child needs to be laid out from scratch using
459 // only its share of excess space.
464 // This child had some intrinsic width to which we
465 // need to add its share of excess space.
466 childHeight = childLayout.MeasuredHeight.Size.AsDecimal() + share;
469 MeasureSpecification childWidthMeasureSpec = GetChildMeasureSpecification( widthMeasureSpec,
470 new LayoutLength(Padding.Start + Padding.End),
471 new LayoutLength(desiredWidth) );
473 MeasureSpecification childHeightMeasureSpec = new MeasureSpecification( new LayoutLength(childHeight), MeasureSpecification.ModeType.Exactly);
474 childLayout.Measure( childWidthMeasureSpec, childHeightMeasureSpec );
476 // Child may now not fit in vertical dimension.
477 if( childLayout.MeasuredHeightAndState.State == MeasuredSize.StateType.MeasuredSizeTooSmall)
479 childState.heightState = MeasuredSize.StateType.MeasuredSizeTooSmall;
483 bool matchWidthLocally = false;
484 if( widthMode != MeasureSpecification.ModeType.Exactly && desiredWidth == (int)ChildLayoutData.MatchParent )
486 // Will have to re-measure at least this child when we know exact height.
488 matchWidthLocally = true;
491 float marginWidth = childMargin.Start + childMargin.End;
492 float childWidth = childLayout.MeasuredWidth.Size.AsDecimal() + marginWidth;
493 maxWidth = Math.Max( maxWidth, childWidth );
494 allFillParent = allFillParent && desiredWidth == (int)ChildLayoutData.MatchParent;
497 alternativeMaxWidth = Math.Max( alternativeMaxWidth, matchWidthLocally ? marginWidth : childWidth );
499 childHeight = childLayout.MeasuredHeight.Size.AsDecimal();
500 float length = childHeight + childMargin.Top + childMargin.Bottom;
501 float cellPadding = CellPadding.Height;
502 // No need to add cell padding to the end of last item.
503 if (index>=_children.Count-1)
507 _totalLength = Math.Max( _totalLength, _totalLength + length + cellPadding );
510 // Add in our padding
511 _totalLength += Padding.Top + Padding.Bottom;
515 alternativeMaxWidth = Math.Max( alternativeMaxWidth, weightedMaxWidth );
518 if (!allFillParent && widthMode != MeasureSpecification.ModeType.Exactly)
520 maxWidth = alternativeMaxWidth;
522 maxWidth += padding.Start + padding.End;
523 maxWidth = Math.Max( maxWidth, SuggestedMinimumWidth.AsRoundedValue());
525 heightSizeAndState.State = childState.heightState;
527 SetMeasuredDimensions( ResolveSizeAndState( new LayoutLength(maxWidth), widthMeasureSpec, childState.widthState ),
528 heightSizeAndState );
532 ForceUniformWidth( _children.Count, heightMeasureSpec );
534 } // MeasureVertically
536 void LayoutHorizontal(LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom)
538 bool isLayoutRtl = Owner.LayoutDirection == ViewLayoutDirectionType.RTL;
540 LayoutLength childTop = new LayoutLength(Padding.Top);
541 LayoutLength childLeft = new LayoutLength(Padding.Start);
543 // Where bottom of child should go
544 LayoutLength height = new LayoutLength(bottom - top);
546 // Space available for child
547 LayoutLength childSpace = new LayoutLength( height - Padding.Top - Padding.Bottom);
549 int count = _children.Count;
551 switch (LinearAlignment)
553 case Alignment.Begin:
555 // totalLength contains the padding already
556 // In case of RTL map BEGIN alignment to the right edge
559 childLeft = new LayoutLength(Padding.Start + right.AsDecimal() - left.AsDecimal() - _totalLength);
563 childLeft = new LayoutLength(Padding.Start);
567 // totalLength contains the padding already
568 // In case of RTL map END alignment to the left edge
571 childLeft = new LayoutLength(Padding.Start);
575 childLeft = new LayoutLength(Padding.Start + right.AsDecimal() - left.AsDecimal() - _totalLength);
578 case Alignment.CenterHorizontal:
579 // totalLength contains the padding already
580 childLeft = new LayoutLength(Padding.Start + (right.AsDecimal() - left.AsDecimal() - _totalLength) / 2.0f);
587 // In case of RTL, start drawing from the last child.
594 for( int i = 0; i < count; i++)
596 int childIndex = start + dir * i;
597 // Get a reference to the childLayout at the given index
598 LayoutItem childLayout = _children[childIndex];
599 if( childLayout != null )
601 LayoutLength childWidth = childLayout.MeasuredWidth.Size;
602 LayoutLength childHeight = childLayout.MeasuredHeight.Size;
603 Extents childMargin = childLayout.Margin;
605 switch ( LinearAlignment )
608 childTop = new LayoutLength(Padding.Top + childMargin.Top);
610 case Alignment.Bottom:
611 childTop = new LayoutLength(height - Padding.Bottom - childHeight - childMargin.Bottom);
613 case Alignment.CenterVertical: // FALLTHROUGH
615 childTop = new LayoutLength(Padding.Top + ( ( childSpace - childHeight ).AsDecimal() / 2.0f ) + childMargin.Top - childMargin.Bottom);
618 childLeft += childMargin.Start;
619 childLayout.Layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
620 childLeft += childWidth + childMargin.End + CellPadding.Width;
623 } // LayoutHorizontally
625 void LayoutVertical(LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom)
627 LayoutLength childTop = new LayoutLength(Padding.Top);
628 LayoutLength childLeft = new LayoutLength(Padding.Start);
630 // Where end of child should go
631 LayoutLength width = new LayoutLength(right - left);
633 // Space available for child
634 LayoutLength childSpace = new LayoutLength( width - Padding.Start - Padding.End);
636 int count = _children.Count;
638 switch (LinearAlignment)
641 // totalLength contains the padding already
642 childTop = new LayoutLength( Padding.Top );
644 case Alignment.Bottom:
645 // totalLength contains the padding already
646 childTop = new LayoutLength( Padding.Top + bottom.AsDecimal() - top.AsDecimal() - _totalLength);
648 case Alignment.CenterVertical:
650 // totalLength contains the padding already
651 childTop = new LayoutLength(Padding.Top + ( bottom.AsDecimal() - top.AsDecimal() - _totalLength ) / 2.0f);
655 for( int i = 0; i < count; i++)
657 LayoutItem childLayout = _children[i];
658 if( childLayout != null )
660 LayoutLength childWidth = childLayout.MeasuredWidth.Size;
661 LayoutLength childHeight = childLayout.MeasuredHeight.Size;
662 Extents childMargin = childLayout.Margin;
664 childTop += childMargin.Top;
665 switch ( LinearAlignment )
667 case Alignment.Begin:
670 childLeft = new LayoutLength(Padding.Start + childMargin.Start);
675 childLeft = new LayoutLength(width - Padding.End - childWidth - childMargin.End);
678 case Alignment.CenterHorizontal:
680 childLeft = new LayoutLength(Padding.Start + (( childSpace - childWidth ).AsDecimal() / 2.0f) + childMargin.Start - childMargin.End);
684 childLayout.Layout( childLeft, childTop, childLeft + childWidth, childTop + childHeight );
685 childTop += childHeight + childMargin.Bottom + CellPadding.Height;
690 void ForceUniformHeight( int count, MeasureSpecification widthMeasureSpec )
692 // Pretend that the linear layout has an exact size. This is the measured height of
693 // ourselves. The measured height should be the max height of the children, changed
694 // to accommodate the heightMeasureSpec from the parent
695 MeasureSpecification uniformMeasureSpec = new MeasureSpecification( MeasuredHeight.Size, MeasureSpecification.ModeType.Exactly);
696 for (int i = 0; i < count; ++i)
698 LayoutItem childLayout = _children[i];
699 if (childLayout != null)
701 LayoutLength desiredWidth = new LayoutLength(childLayout.Owner.WidthSpecification);
702 LayoutLength desiredHeight = new LayoutLength(Owner.WidthSpecification );
704 if (desiredHeight.AsRoundedValue() == LayoutParamPolicies.MatchParent)
706 // Temporarily force children to reuse their old measured width
707 LayoutLength oldWidth = desiredWidth;
708 childLayout.Owner.WidthSpecification = (int)childLayout.MeasuredWidth.Size.AsRoundedValue();
709 // Remeasure with new dimensions
710 MeasureChildWithMargins( childLayout, widthMeasureSpec, new LayoutLength(0),
711 uniformMeasureSpec, new LayoutLength(0) );
713 childLayout.Owner.WidthSpecification = (int)oldWidth.AsRoundedValue();
719 void ForceUniformWidth( int count, MeasureSpecification heightMeasureSpec )
721 // Pretend that the linear layout has an exact size.
722 MeasureSpecification uniformMeasureSpec = new MeasureSpecification( MeasuredWidth.Size, MeasureSpecification.ModeType.Exactly);
723 for (int i = 0; i < count; ++i)
725 LayoutItem childLayout = _children[i];
726 if (childLayout != null)
728 LayoutLength desiredWidth = new LayoutLength(childLayout.Owner.WidthSpecification);
729 LayoutLength desiredHeight = new LayoutLength(Owner.WidthSpecification );
731 if( desiredWidth.AsRoundedValue() == LayoutParamPolicies.MatchParent)
733 // Temporarily force children to reuse their old measured height
734 LayoutLength oldHeight = desiredHeight;
735 childLayout.Owner.HeightSpecification = (int)childLayout.MeasuredHeight.Size.AsRoundedValue();
737 // Remeasure with new dimensions
738 MeasureChildWithMargins( childLayout, uniformMeasureSpec, new LayoutLength(0),
739 heightMeasureSpec, new LayoutLength(0));
741 childLayout.Owner.HeightSpecification = (int)oldHeight.AsRoundedValue();