diff --git a/App.xaml b/App.xaml index 582a119..695ba23 100644 --- a/App.xaml +++ b/App.xaml @@ -23,6 +23,7 @@ + diff --git a/Controls/AlignableWrapPanel.cs b/Controls/AlignableWrapPanel.cs new file mode 100644 index 0000000..8851249 --- /dev/null +++ b/Controls/AlignableWrapPanel.cs @@ -0,0 +1,116 @@ +namespace LostArkTools.Controls; + +using System; +using System.Windows; +using System.Windows.Controls; + +public class AlignableWrapPanel : Panel +{ + public HorizontalAlignment HorizontalContentAlignment + { + get => (HorizontalAlignment)GetValue(HorizontalContentAlignmentProperty); + set => SetValue(HorizontalContentAlignmentProperty, value); + } + + public static readonly DependencyProperty HorizontalContentAlignmentProperty = + DependencyProperty.Register("HorizontalContentAlignment", typeof(HorizontalAlignment), typeof(AlignableWrapPanel), new FrameworkPropertyMetadata(HorizontalAlignment.Left, FrameworkPropertyMetadataOptions.AffectsArrange)); + + protected override Size MeasureOverride(Size constraint) + { + var curLineSize = new Size(); + var panelSize = new Size(); + + var children = InternalChildren; + + for (var i = 0; i < children.Count; i++) + { + var child = children[i] as UIElement; + + // Flow passes its own constraint to children + child.Measure(constraint); + var sz = child.DesiredSize; + + if (curLineSize.Width + sz.Width > constraint.Width) //need to switch to another line + { + panelSize.Width = Math.Max(curLineSize.Width, panelSize.Width); + panelSize.Height += curLineSize.Height; + curLineSize = sz; + + if (sz.Width > constraint.Width) // if the element is wider then the constraint - give it a separate line + { + panelSize.Width = Math.Max(sz.Width, panelSize.Width); + panelSize.Height += sz.Height; + curLineSize = new Size(); + } + } + else //continue to accumulate a line + { + curLineSize.Width += sz.Width; + curLineSize.Height = Math.Max(sz.Height, curLineSize.Height); + } + } + + // the last line size, if any need to be added + panelSize.Width = Math.Max(curLineSize.Width, panelSize.Width); + panelSize.Height += curLineSize.Height; + + return panelSize; + } + + protected override Size ArrangeOverride(Size arrangeBounds) + { + var firstInLine = 0; + var curLineSize = new Size(); + double accumulatedHeight = 0; + var children = InternalChildren; + + for (var i = 0; i < children.Count; i++) + { + var sz = children[i].DesiredSize; + + if (curLineSize.Width + sz.Width > arrangeBounds.Width) //need to switch to another line + { + ArrangeLine(accumulatedHeight, curLineSize, arrangeBounds.Width, firstInLine, i); + + accumulatedHeight += curLineSize.Height; + curLineSize = sz; + + if (sz.Width > arrangeBounds.Width) //the element is wider then the constraint - give it a separate line + { + ArrangeLine(accumulatedHeight, sz, arrangeBounds.Width, i, ++i); + accumulatedHeight += sz.Height; + curLineSize = new Size(); + } + firstInLine = i; + } + else //continue to accumulate a line + { + curLineSize.Width += sz.Width; + curLineSize.Height = Math.Max(sz.Height, curLineSize.Height); + } + } + + if (firstInLine < children.Count) + ArrangeLine(accumulatedHeight, curLineSize, arrangeBounds.Width, firstInLine, children.Count); + + return arrangeBounds; + } + + private void ArrangeLine(double y, Size lineSize, double boundsWidth, int start, int end) + { + var x = HorizontalContentAlignment switch + { + HorizontalAlignment.Center => (boundsWidth - lineSize.Width) / 2, + HorizontalAlignment.Right => (boundsWidth - lineSize.Width), + _ => 0 + }; + + var children = InternalChildren; + for (var i = start; i < end; i++) + { + var child = children[i]; + child.Arrange(new Rect(x, y, child.DesiredSize.Width, lineSize.Height)); + x += child.DesiredSize.Width; + } + } +} \ No newline at end of file diff --git a/Converters/IsLastItemInContainerConverter.cs b/Converters/IsLastItemInContainerConverter.cs new file mode 100644 index 0000000..078fe69 --- /dev/null +++ b/Converters/IsLastItemInContainerConverter.cs @@ -0,0 +1,25 @@ +using System; +using System.Globalization; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; + +namespace LostArkTools.Converters; + +public class IsLastItemInContainerConverter : IValueConverter +{ + public object Convert(object value, Type targetType, + object parameter, CultureInfo culture) + { + var item = (DependencyObject)value; + var ic = ItemsControl.ItemsControlFromItemContainer(item); + var index = ic.ItemContainerGenerator.IndexFromContainer(item); + return index == ic.Items.Count - 1; + } + + public object ConvertBack(object value, Type targetType, + object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/Features/Checklist/CharacterChecklist/CharacterView.xaml b/Features/Checklist/CharacterChecklist/CharacterView.xaml index e3e22fd..0589404 100644 --- a/Features/Checklist/CharacterChecklist/CharacterView.xaml +++ b/Features/Checklist/CharacterChecklist/CharacterView.xaml @@ -63,6 +63,7 @@ KeyUp="{s:Action CharacterNameKeyPressed}" Margin="5" /> diff --git a/Features/ServerStatus/RegionView.xaml b/Features/ServerStatus/RegionView.xaml index 3badd24..9e5771a 100644 --- a/Features/ServerStatus/RegionView.xaml +++ b/Features/ServerStatus/RegionView.xaml @@ -4,54 +4,50 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:LostArkTools.Features.ServerStatus" + xmlns:controls="clr-namespace:LostArkTools.Controls" mc:Ignorable="d" d:DataContext="{d:DesignInstance local:RegionViewModel}" d:DesignHeight="300" d:DesignWidth="300"> - - - - + + + +