123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732 |
- using System;
- using System.Collections.Generic;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Media;
- using HandyControl.Data;
- using HandyControl.Expression.Drawing;
- using HandyControl.Tools;
- using HandyControl.Tools.Extension;
- namespace HandyControl.Controls;
- public class FlexPanel : Panel
- {
- private UVSize _uvConstraint;
- private int _lineCount;
- private readonly List<FlexItemInfo> _orderList = new();
- #region Item
- public static readonly DependencyProperty OrderProperty = DependencyProperty.RegisterAttached(
- "Order", typeof(int), typeof(FlexPanel),
- new FrameworkPropertyMetadata(ValueBoxes.Int0Box, OnItemPropertyChanged));
- public static void SetOrder(DependencyObject element, int value)
- => element.SetValue(OrderProperty, value);
- public static int GetOrder(DependencyObject element)
- => (int) element.GetValue(OrderProperty);
- public static readonly DependencyProperty FlexGrowProperty = DependencyProperty.RegisterAttached(
- "FlexGrow", typeof(double), typeof(FlexPanel),
- new FrameworkPropertyMetadata(ValueBoxes.Double0Box, OnItemPropertyChanged),
- ValidateHelper.IsInRangeOfPosDoubleIncludeZero);
- public static void SetFlexGrow(DependencyObject element, double value)
- => element.SetValue(FlexGrowProperty, value);
- public static double GetFlexGrow(DependencyObject element)
- => (double) element.GetValue(FlexGrowProperty);
- public static readonly DependencyProperty FlexShrinkProperty = DependencyProperty.RegisterAttached(
- "FlexShrink", typeof(double), typeof(FlexPanel),
- new FrameworkPropertyMetadata(ValueBoxes.Double1Box, OnItemPropertyChanged),
- ValidateHelper.IsInRangeOfPosDoubleIncludeZero);
- public static void SetFlexShrink(DependencyObject element, double value)
- => element.SetValue(FlexShrinkProperty, value);
- public static double GetFlexShrink(DependencyObject element)
- => (double) element.GetValue(FlexShrinkProperty);
- public static readonly DependencyProperty FlexBasisProperty = DependencyProperty.RegisterAttached(
- "FlexBasis", typeof(double), typeof(FlexPanel),
- new FrameworkPropertyMetadata(double.NaN, OnItemPropertyChanged));
- public static void SetFlexBasis(DependencyObject element, double value)
- => element.SetValue(FlexBasisProperty, value);
- public static double GetFlexBasis(DependencyObject element)
- => (double) element.GetValue(FlexBasisProperty);
- public static readonly DependencyProperty AlignSelfProperty = DependencyProperty.RegisterAttached(
- "AlignSelf", typeof(FlexItemAlignment), typeof(FlexPanel),
- new FrameworkPropertyMetadata(default(FlexItemAlignment), OnItemPropertyChanged));
- public static void SetAlignSelf(DependencyObject element, FlexItemAlignment value)
- => element.SetValue(AlignSelfProperty, value);
- #endregion
- #region Panel
- public static FlexItemAlignment GetAlignSelf(DependencyObject element)
- => (FlexItemAlignment) element.GetValue(AlignSelfProperty);
- public static readonly DependencyProperty FlexDirectionProperty = DependencyProperty.Register(
- nameof(FlexDirection), typeof(FlexDirection), typeof(FlexPanel),
- new FrameworkPropertyMetadata(default(FlexDirection), FrameworkPropertyMetadataOptions.AffectsMeasure));
- public FlexDirection FlexDirection
- {
- get => (FlexDirection) GetValue(FlexDirectionProperty);
- set => SetValue(FlexDirectionProperty, value);
- }
- public static readonly DependencyProperty FlexWrapProperty = DependencyProperty.Register(
- nameof(FlexWrap), typeof(FlexWrap), typeof(FlexPanel),
- new FrameworkPropertyMetadata(default(FlexWrap), FrameworkPropertyMetadataOptions.AffectsMeasure));
- public FlexWrap FlexWrap
- {
- get => (FlexWrap) GetValue(FlexWrapProperty);
- set => SetValue(FlexWrapProperty, value);
- }
- public static readonly DependencyProperty JustifyContentProperty = DependencyProperty.Register(
- nameof(JustifyContent), typeof(FlexContentJustify), typeof(FlexPanel),
- new FrameworkPropertyMetadata(default(FlexContentJustify),
- FrameworkPropertyMetadataOptions.AffectsMeasure));
- public FlexContentJustify JustifyContent
- {
- get => (FlexContentJustify) GetValue(JustifyContentProperty);
- set => SetValue(JustifyContentProperty, value);
- }
- public static readonly DependencyProperty AlignItemsProperty = DependencyProperty.Register(
- nameof(AlignItems), typeof(FlexItemsAlignment), typeof(FlexPanel),
- new FrameworkPropertyMetadata(default(FlexItemsAlignment),
- FrameworkPropertyMetadataOptions.AffectsMeasure));
- public FlexItemsAlignment AlignItems
- {
- get => (FlexItemsAlignment) GetValue(AlignItemsProperty);
- set => SetValue(AlignItemsProperty, value);
- }
- public static readonly DependencyProperty AlignContentProperty = DependencyProperty.Register(
- nameof(AlignContent), typeof(FlexContentAlignment), typeof(FlexPanel),
- new FrameworkPropertyMetadata(default(FlexContentAlignment),
- FrameworkPropertyMetadataOptions.AffectsMeasure));
- public FlexContentAlignment AlignContent
- {
- get => (FlexContentAlignment) GetValue(AlignContentProperty);
- set => SetValue(AlignContentProperty, value);
- }
- #endregion
- private static void OnItemPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- if (d is UIElement element)
- {
- if (VisualTreeHelper.GetParent(element) is FlexPanel p)
- {
- p.InvalidateMeasure();
- }
- }
- }
- protected override Size MeasureOverride(Size constraint)
- {
- var flexDirection = FlexDirection;
- var flexWrap = FlexWrap;
- var curLineSize = new UVSize(flexDirection);
- var panelSize = new UVSize(flexDirection);
- _uvConstraint = new UVSize(flexDirection, constraint);
- var childConstraint = new Size(constraint.Width, constraint.Height);
- _lineCount = 1;
- var children = InternalChildren;
- _orderList.Clear();
- for (var i = 0; i < children.Count; i++)
- {
- var child = children[i];
- if (child == null) continue;
- _orderList.Add(new FlexItemInfo(i, GetOrder(child)));
- }
- _orderList.Sort();
- for (var i = 0; i < children.Count; i++)
- {
- var child = children[_orderList[i].Index];
- if (child == null) continue;
- var flexBasis = GetFlexBasis(child);
- if (!flexBasis.IsNaN())
- {
- child.SetCurrentValue(WidthProperty, flexBasis);
- }
- child.Measure(childConstraint);
- var sz = new UVSize(flexDirection, child.DesiredSize);
- if (flexWrap == FlexWrap.NoWrap) //continue to accumulate a line
- {
- curLineSize.U += sz.U;
- curLineSize.V = Math.Max(sz.V, curLineSize.V);
- }
- else
- {
- if (MathHelper.GreaterThan(curLineSize.U + sz.U, _uvConstraint.U)) //need to switch to another line
- {
- panelSize.U = Math.Max(curLineSize.U, panelSize.U);
- panelSize.V += curLineSize.V;
- curLineSize = sz;
- _lineCount++;
- if (MathHelper.GreaterThan(sz.U, _uvConstraint.U)) //the element is wider then the constrint - give it a separate line
- {
- panelSize.U = Math.Max(sz.U, panelSize.U);
- panelSize.V += sz.V;
- curLineSize = new UVSize(flexDirection);
- _lineCount++;
- }
- }
- else //continue to accumulate a line
- {
- curLineSize.U += sz.U;
- curLineSize.V = Math.Max(sz.V, curLineSize.V);
- }
- }
- }
- //the last line size, if any should be added
- panelSize.U = Math.Max(curLineSize.U, panelSize.U);
- panelSize.V += curLineSize.V;
- //go from UV space to W/H space
- return new Size(panelSize.Width, panelSize.Height);
- }
- protected override Size ArrangeOverride(Size arrangeSize)
- {
- var flexDirection = FlexDirection;
- var flexWrap = FlexWrap;
- var alignContent = AlignContent;
- var uvFinalSize = new UVSize(flexDirection, arrangeSize);
- if (MathHelper.IsZero(uvFinalSize.U) || MathHelper.IsZero(uvFinalSize.V)) return arrangeSize;
- // init status
- var children = InternalChildren;
- var lineIndex = 0;
- var curLineSizeArr = new UVSize[_lineCount];
- curLineSizeArr[0] = new UVSize(flexDirection);
- var lastInLineArr = new int[_lineCount];
- for (var i = 0; i < _lineCount; i++)
- {
- lastInLineArr[i] = int.MaxValue;
- }
- // calculate line max U space
- for (var i = 0; i < children.Count; i++)
- {
- var child = children[_orderList[i].Index];
- if (child == null) continue;
- var sz = new UVSize(flexDirection, child.DesiredSize);
- if (flexWrap == FlexWrap.NoWrap)
- {
- curLineSizeArr[lineIndex].U += sz.U;
- curLineSizeArr[lineIndex].V = Math.Max(sz.V, curLineSizeArr[lineIndex].V);
- }
- else
- {
- if (MathHelper.GreaterThan(curLineSizeArr[lineIndex].U + sz.U, uvFinalSize.U)) //need to switch to another line
- {
- lastInLineArr[lineIndex] = i;
- lineIndex++;
- curLineSizeArr[lineIndex] = sz;
- if (MathHelper.GreaterThan(sz.U, uvFinalSize.U)) //the element is wider then the constraint - give it a separate line
- {
- //switch to next line which only contain one element
- lastInLineArr[lineIndex] = i;
- lineIndex++;
- curLineSizeArr[lineIndex] = new UVSize(flexDirection);
- }
- }
- else //continue to accumulate a line
- {
- curLineSizeArr[lineIndex].U += sz.U;
- curLineSizeArr[lineIndex].V = Math.Max(sz.V, curLineSizeArr[lineIndex].V);
- }
- }
- }
- // init status
- var scaleU = Math.Min(_uvConstraint.U / uvFinalSize.U, 1);
- var firstInLine = 0;
- var wrapReverseAdd = 0;
- var wrapReverseFlag = flexWrap == FlexWrap.WrapReverse ? -1 : 1;
- var accumulatedFlag = flexWrap == FlexWrap.WrapReverse ? 1 : 0;
- var itemsU = .0;
- var accumulatedV = .0;
- var freeV = uvFinalSize.V;
- foreach (var flexSize in curLineSizeArr)
- {
- freeV -= flexSize.V;
- }
- var freeItemV = freeV;
- // calculate status
- var lineFreeVArr = new double[_lineCount];
- switch (alignContent)
- {
- case FlexContentAlignment.Stretch:
- if (_lineCount > 1)
- {
- freeItemV = freeV / _lineCount;
- for (var i = 0; i < _lineCount; i++)
- {
- lineFreeVArr[i] = freeItemV;
- }
- accumulatedV = flexWrap == FlexWrap.WrapReverse ? uvFinalSize.V - curLineSizeArr[0].V - lineFreeVArr[0] : 0;
- }
- break;
- case FlexContentAlignment.FlexStart:
- wrapReverseAdd = flexWrap == FlexWrap.WrapReverse ? 0 : 1;
- if (_lineCount > 1)
- {
- accumulatedV = flexWrap == FlexWrap.WrapReverse ? uvFinalSize.V - curLineSizeArr[0].V : 0;
- }
- else
- {
- wrapReverseAdd = 0;
- }
- break;
- case FlexContentAlignment.FlexEnd:
- wrapReverseAdd = flexWrap == FlexWrap.WrapReverse ? 1 : 0;
- if (_lineCount > 1)
- {
- accumulatedV = flexWrap == FlexWrap.WrapReverse ? uvFinalSize.V - curLineSizeArr[0].V - freeV : freeV;
- }
- else
- {
- wrapReverseAdd = 0;
- }
- break;
- case FlexContentAlignment.Center:
- if (_lineCount > 1)
- {
- accumulatedV = flexWrap == FlexWrap.WrapReverse ? uvFinalSize.V - curLineSizeArr[0].V - freeV * 0.5 : freeV * 0.5;
- }
- break;
- case FlexContentAlignment.SpaceBetween:
- if (_lineCount > 1)
- {
- freeItemV = freeV / (_lineCount - 1);
- for (var i = 0; i < _lineCount - 1; i++)
- {
- lineFreeVArr[i] = freeItemV;
- }
- accumulatedV = flexWrap == FlexWrap.WrapReverse ? uvFinalSize.V - curLineSizeArr[0].V : 0;
- }
- break;
- case FlexContentAlignment.SpaceAround:
- if (_lineCount > 1)
- {
- freeItemV = freeV / _lineCount * 0.5;
- for (var i = 0; i < _lineCount - 1; i++)
- {
- lineFreeVArr[i] = freeItemV * 2;
- }
- accumulatedV = flexWrap == FlexWrap.WrapReverse ? uvFinalSize.V - curLineSizeArr[0].V - freeItemV : freeItemV;
- }
- break;
- }
- // clear status
- lineIndex = 0;
- // arrange line
- for (var i = 0; i < children.Count; i++)
- {
- var child = children[_orderList[i].Index];
- if (child == null) continue;
- var sz = new UVSize(flexDirection, child.DesiredSize);
- if (flexWrap != FlexWrap.NoWrap)
- {
- if (i >= lastInLineArr[lineIndex]) //need to switch to another line
- {
- ArrangeLine(new FlexLineInfo
- {
- ItemsU = itemsU,
- OffsetV = accumulatedV + freeItemV * wrapReverseAdd,
- LineV = curLineSizeArr[lineIndex].V,
- LineFreeV = freeItemV,
- LineU = uvFinalSize.U,
- ItemStartIndex = firstInLine,
- ItemEndIndex = i,
- ScaleU = scaleU
- });
- accumulatedV += (lineFreeVArr[lineIndex] + curLineSizeArr[lineIndex + accumulatedFlag].V) * wrapReverseFlag;
- lineIndex++;
- itemsU = 0;
- if (i >= lastInLineArr[lineIndex]) //the element is wider then the constraint - give it a separate line
- {
- //switch to next line which only contain one element
- ArrangeLine(new FlexLineInfo
- {
- ItemsU = itemsU,
- OffsetV = accumulatedV + freeItemV * wrapReverseAdd,
- LineV = curLineSizeArr[lineIndex].V,
- LineFreeV = freeItemV,
- LineU = uvFinalSize.U,
- ItemStartIndex = i,
- ItemEndIndex = ++i,
- ScaleU = scaleU
- });
- accumulatedV += (lineFreeVArr[lineIndex] + curLineSizeArr[lineIndex + accumulatedFlag].V) * wrapReverseFlag;
- lineIndex++;
- itemsU = 0;
- }
- firstInLine = i;
- }
- }
- itemsU += sz.U;
- }
- // arrange the last line, if any
- if (firstInLine < children.Count)
- {
- ArrangeLine(new FlexLineInfo
- {
- ItemsU = itemsU,
- OffsetV = accumulatedV + freeItemV * wrapReverseAdd,
- LineV = curLineSizeArr[lineIndex].V,
- LineFreeV = freeItemV,
- LineU = uvFinalSize.U,
- ItemStartIndex = firstInLine,
- ItemEndIndex = children.Count,
- ScaleU = scaleU
- });
- }
- return arrangeSize;
- }
- private void ArrangeLine(FlexLineInfo lineInfo)
- {
- var flexDirection = FlexDirection;
- var flexWrap = FlexWrap;
- var justifyContent = JustifyContent;
- var alignItems = AlignItems;
- var isHorizontal = flexDirection == FlexDirection.Row || flexDirection == FlexDirection.RowReverse;
- var isReverse = flexDirection == FlexDirection.RowReverse || flexDirection == FlexDirection.ColumnReverse;
- var itemCount = lineInfo.ItemEndIndex - lineInfo.ItemStartIndex;
- var children = InternalChildren;
- var lineFreeU = lineInfo.LineU - lineInfo.ItemsU;
- var constraintFreeU = _uvConstraint.U - lineInfo.ItemsU;
- // calculate initial u
- var u = .0;
- if (isReverse)
- {
- u = justifyContent switch
- {
- FlexContentJustify.FlexStart => lineInfo.LineU,
- FlexContentJustify.SpaceBetween => lineInfo.LineU,
- FlexContentJustify.SpaceAround => lineInfo.LineU,
- FlexContentJustify.FlexEnd => lineInfo.ItemsU,
- FlexContentJustify.Center => (lineInfo.LineU + lineInfo.ItemsU) * 0.5,
- _ => u
- };
- }
- else
- {
- u = justifyContent switch
- {
- FlexContentJustify.FlexEnd => lineFreeU,
- FlexContentJustify.Center => lineFreeU * 0.5,
- _ => u
- };
- }
- u *= lineInfo.ScaleU;
- // apply FlexGrow
- var flexGrowUArr = new double[itemCount];
- if (constraintFreeU > 0)
- {
- var ignoreFlexGrow = true;
- var flexGrowSum = .0;
- for (var i = 0; i < itemCount; i++)
- {
- var flexGrow = GetFlexGrow(children[_orderList[i].Index]);
- ignoreFlexGrow &= MathHelper.IsVerySmall(flexGrow);
- flexGrowUArr[i] = flexGrow;
- flexGrowSum += flexGrow;
- }
- if (!ignoreFlexGrow)
- {
- var flexGrowItem = .0;
- if (flexGrowSum > 0)
- {
- flexGrowItem = constraintFreeU / flexGrowSum;
- lineInfo.ScaleU = 1;
- lineFreeU = 0; //line free U was used up
- }
- for (var i = 0; i < itemCount; i++)
- {
- flexGrowUArr[i] *= flexGrowItem;
- }
- }
- else
- {
- flexGrowUArr = new double[itemCount];
- }
- }
- // apply FlexShrink
- var flexShrinkUArr = new double[itemCount];
- if (constraintFreeU < 0)
- {
- var ignoreFlexShrink = true;
- var flexShrinkSum = .0;
- for (var i = 0; i < itemCount; i++)
- {
- var flexShrink = GetFlexShrink(children[_orderList[i].Index]);
- ignoreFlexShrink &= MathHelper.IsVerySmall(flexShrink - 1);
- flexShrinkUArr[i] = flexShrink;
- flexShrinkSum += flexShrink;
- }
- if (!ignoreFlexShrink)
- {
- var flexShrinkItem = .0;
- if (flexShrinkSum > 0)
- {
- flexShrinkItem = constraintFreeU / flexShrinkSum;
- lineInfo.ScaleU = 1;
- lineFreeU = 0; //line free U was used up
- }
- for (var i = 0; i < itemCount; i++)
- {
- flexShrinkUArr[i] *= flexShrinkItem;
- }
- }
- else
- {
- flexShrinkUArr = new double[itemCount];
- }
- }
- // calculate offset u
- var offsetUArr = new double[itemCount];
- if (lineFreeU > 0)
- {
- if (justifyContent == FlexContentJustify.SpaceBetween)
- {
- var freeItemU = lineFreeU / (itemCount - 1);
- for (var i = 1; i < itemCount; i++)
- {
- offsetUArr[i] = freeItemU;
- }
- }
- else if (justifyContent == FlexContentJustify.SpaceAround)
- {
- var freeItemU = lineFreeU / itemCount * 0.5;
- offsetUArr[0] = freeItemU;
- for (var i = 1; i < itemCount; i++)
- {
- offsetUArr[i] = freeItemU * 2;
- }
- }
- }
- // arrange item
- for (int i = lineInfo.ItemStartIndex, j = 0; i < lineInfo.ItemEndIndex; i++, j++)
- {
- var child = children[_orderList[i].Index];
- if (child == null) continue;
- var childSize = new UVSize(flexDirection, isHorizontal
- ? new Size(child.DesiredSize.Width * lineInfo.ScaleU, child.DesiredSize.Height)
- : new Size(child.DesiredSize.Width, child.DesiredSize.Height * lineInfo.ScaleU));
- childSize.U += flexGrowUArr[j] + flexShrinkUArr[j];
- if (isReverse)
- {
- u -= childSize.U;
- u -= offsetUArr[j];
- }
- else
- {
- u += offsetUArr[j];
- }
- var v = lineInfo.OffsetV;
- var alignSelf = GetAlignSelf(child);
- var alignment = alignSelf == FlexItemAlignment.Auto ? alignItems : (FlexItemsAlignment) alignSelf;
- switch (alignment)
- {
- case FlexItemsAlignment.Stretch:
- if (_lineCount == 1 && flexWrap == FlexWrap.NoWrap)
- {
- childSize.V = lineInfo.LineV + lineInfo.LineFreeV;
- }
- else
- {
- childSize.V = lineInfo.LineV;
- }
- break;
- case FlexItemsAlignment.FlexEnd:
- v += lineInfo.LineV - childSize.V;
- break;
- case FlexItemsAlignment.Center:
- v += (lineInfo.LineV - childSize.V) * 0.5;
- break;
- }
- child.Arrange(isHorizontal ? new Rect(u, v, childSize.U, childSize.V) : new Rect(v, u, childSize.V, childSize.U));
- if (!isReverse)
- {
- u += childSize.U;
- }
- }
- }
- private readonly struct FlexItemInfo : IComparable<FlexItemInfo>
- {
- public FlexItemInfo(int index, int order)
- {
- Index = index;
- Order = order;
- }
- private int Order { get; }
- public int Index { get; }
- public int CompareTo(FlexItemInfo other)
- {
- var orderCompare = Order.CompareTo(other.Order);
- if (orderCompare != 0) return orderCompare;
- return Index.CompareTo(other.Index);
- }
- }
- private struct FlexLineInfo
- {
- public double ItemsU { get; set; }
- public double OffsetV { get; set; }
- public double LineU { get; set; }
- public double LineV { get; set; }
- public double LineFreeV { get; set; }
- public int ItemStartIndex { get; set; }
- public int ItemEndIndex { get; set; }
- public double ScaleU { get; set; }
- }
- private struct UVSize
- {
- public UVSize(FlexDirection direction, Size size)
- {
- U = V = 0d;
- FlexDirection = direction;
- Width = size.Width;
- Height = size.Height;
- }
- public UVSize(FlexDirection direction)
- {
- U = V = 0d;
- FlexDirection = direction;
- }
- public double U { get; set; }
- public double V { get; set; }
- private FlexDirection FlexDirection { get; }
- public double Width
- {
- get => FlexDirection == FlexDirection.Row || FlexDirection == FlexDirection.RowReverse ? U : V;
- private set
- {
- if (FlexDirection == FlexDirection.Row || FlexDirection == FlexDirection.RowReverse)
- {
- U = value;
- }
- else
- {
- V = value;
- }
- }
- }
- public double Height
- {
- get => FlexDirection == FlexDirection.Row || FlexDirection == FlexDirection.RowReverse ? V : U;
- private set
- {
- if (FlexDirection == FlexDirection.Row || FlexDirection == FlexDirection.RowReverse)
- {
- V = value;
- }
- else
- {
- U = value;
- }
- }
- }
- }
- }
|