Skip to content

Commit 6e9643a

Browse files
authored
MarkupExtension and Adorner changes (#133)
* Create markup extension * Use render bitmap * Fix issue with tooltip on buff icons
1 parent 855daf5 commit 6e9643a

File tree

8 files changed

+142
-87
lines changed

8 files changed

+142
-87
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using System.Globalization;
3+
using System.Windows.Data;
4+
5+
namespace KoAR.SaveEditor.Constructs
6+
{
7+
public sealed class IsTypeConverter : IValueConverter
8+
{
9+
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture) => BooleanBoxes.GetBox(parameter is Type type && type.IsInstanceOfType(value));
10+
11+
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException();
12+
}
13+
}

KoAR.SaveEditor/Constructs/LoadingIndicator.cs

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Windows;
44
using System.Windows.Controls;
55
using System.Windows.Data;
6+
using System.Windows.Markup;
67

78
namespace KoAR.SaveEditor.Constructs;
89

@@ -24,40 +25,63 @@ public bool IsLoading
2425
set => this.SetValue(LoadingIndicator.IsLoadingProperty, BooleanBoxes.GetBox(value));
2526
}
2627

28+
private static double ParseName(string name, CultureInfo culture) => double.Parse(name[6..], NumberStyles.Float, culture);
29+
2730
private sealed class CircleLocationConverter : IMultiValueConverter
2831
{
2932
object IMultiValueConverter.Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
3033
{
31-
if (values is not { Length: 2 } || parameter is not string text)
34+
if (parameter is not DependencyProperty property || values is not { Length: 2 } || values[0] is not double width || values[1] is not string name)
3235
{
3336
return DependencyProperty.UnsetValue;
3437
}
35-
Func<double, double> function = text == "Top" ? Math.Cos : Math.Sin;
36-
return (1d + function(Math.PI + Convert.ToInt32(values[1], culture) * (Math.PI / 5d))) * Convert.ToDouble(values[0], culture) * 2.5;
38+
Func<double, double> function = property == Canvas.TopProperty ? Math.Cos : Math.Sin;
39+
return width * (1d + function(Math.PI + LoadingIndicator.ParseName(name, culture) * Math.PI / 5d)) * 2.5;
3740
}
3841

3942
object[] IMultiValueConverter.ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException();
4043
}
4144

4245
private sealed class CircleOpacityConverter : IValueConverter
4346
{
44-
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
45-
{
46-
return double.TryParse(value.ToString(), NumberStyles.Float, culture, out double index) ? 1d - index / 10d : DependencyProperty.UnsetValue;
47-
}
47+
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture) => value is not string name
48+
? DependencyProperty.UnsetValue
49+
: 1d - LoadingIndicator.ParseName(name, culture) / 10d;
4850

4951
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException();
5052
}
5153

5254
private sealed class DivisionConverter : IValueConverter
5355
{
54-
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
55-
{
56-
return value is double number && parameter is IConvertible divisor
57-
? number / divisor.ToDouble(culture)
58-
: DependencyProperty.UnsetValue;
59-
}
56+
object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture) => value is double number && parameter is double divisor
57+
? number / divisor
58+
: DependencyProperty.UnsetValue;
6059

6160
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => throw new NotImplementedException();
6261
}
6362
}
63+
64+
public sealed class LoadingEllipseLocationExtension : MarkupExtension
65+
{
66+
private static readonly Binding _nameBinding = new()
67+
{
68+
Path = new(FrameworkElement.NameProperty),
69+
RelativeSource = RelativeSource.Self,
70+
};
71+
private static readonly Binding _tagBinding = new()
72+
{
73+
Path = new(Control.TagProperty),
74+
RelativeSource = new() { AncestorType = typeof(Canvas) }
75+
};
76+
77+
public override object ProvideValue(IServiceProvider serviceProvider) => new MultiBinding()
78+
{
79+
Converter = LoadingIndicator.LocationConverter,
80+
ConverterParameter = ((IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget))!).TargetProperty,
81+
Bindings =
82+
{
83+
LoadingEllipseLocationExtension._tagBinding,
84+
LoadingEllipseLocationExtension._nameBinding,
85+
}
86+
};
87+
}

KoAR.SaveEditor/Themes/Generic.BuffCollectionManager.xaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
<ResourceDictionary.MergedDictionaries>
77
<ResourceDictionary Source="/PresentationFramework.Aero;component/Themes/Aero.NormalColor.xaml" />
88
<ResourceDictionary Source="/KoAR.SaveEditor;component/Templates/BuffTemplate.xaml" />
9-
<ResourceDictionary Source="/KoAR.SaveEditor;component/Templates/BuffToolTipTemplate.xaml" />
109
</ResourceDictionary.MergedDictionaries>
1110
<BitmapImage x:Key="Copy" UriSource="/KoAR.SaveEditor;component/Resources/Copy.png" po:Freeze="True" />
1211
<BitmapImage x:Key="Delete" UriSource="/KoAR.SaveEditor;component/Resources/Delete.png" po:Freeze="True" />

KoAR.SaveEditor/Themes/Generic.ItemCollectionManager.xaml

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,16 @@
1818
<constructs:LittleEndianConverter x:Key="LittleEndianConverter" />
1919
<constructs:AndConverter x:Key="AndConverter" />
2020
<constructs:GrayscaleConverter x:Key="GrayscaleConverter" />
21+
<constructs:IsTypeConverter x:Key="IsTypeConverter" />
2122
<BitmapImage x:Key="Delete" UriSource="/KoAR.SaveEditor;component/Resources/Delete.png" po:Freeze="True" />
2223
<BitmapImage x:Key="Ellipsis" UriSource="/KoAR.SaveEditor;component/Resources/Ellipsis.png" po:Freeze="True" />
24+
<Style TargetType="{x:Type ToolTip}" BasedOn="{StaticResource {x:Type ToolTip}}" x:Key="BuffToolTipStyle">
25+
<Style.Triggers>
26+
<DataTrigger Binding="{Binding Content, RelativeSource={RelativeSource Self}, Converter={StaticResource IsTypeConverter}, ConverterParameter={x:Type core:Buff}}" Value="True">
27+
<Setter Property="ContentTemplate" Value="{StaticResource BuffToolTipTemplate}" />
28+
</DataTrigger>
29+
</Style.Triggers>
30+
</Style>
2331
<Style TargetType="{x:Type Button}" x:Key="CommandButtonStyle">
2432
<Setter Property="Template">
2533
<Setter.Value>
@@ -480,9 +488,7 @@
480488
<GridViewColumn.CellTemplate>
481489
<DataTemplate DataType="{x:Type views:ItemModelBase}">
482490
<DataTemplate.Resources>
483-
<Style TargetType="{x:Type ToolTip}" BasedOn="{StaticResource {x:Type ToolTip}}">
484-
<Setter Property="ContentTemplate" Value="{StaticResource BuffToolTipTemplate}" />
485-
</Style>
491+
<Style TargetType="{x:Type ToolTip}" BasedOn="{StaticResource BuffToolTipStyle}" />
486492
<Style TargetType="{x:Type views:BuffIcon}">
487493
<Style.Triggers>
488494
<Trigger Property="Buff" Value="{x:Null}">
@@ -511,9 +517,7 @@
511517
<ItemsControl.ItemTemplate>
512518
<DataTemplate DataType="{x:Type core:Buff}">
513519
<DataTemplate.Resources>
514-
<Style TargetType="{x:Type ToolTip}" BasedOn="{StaticResource {x:Type ToolTip}}">
515-
<Setter Property="ContentTemplate" Value="{StaticResource BuffToolTipTemplate}" />
516-
</Style>
520+
<Style TargetType="{x:Type ToolTip}" BasedOn="{StaticResource BuffToolTipStyle}" />
517521
</DataTemplate.Resources>
518522
<views:BuffIcon Buff="{Binding}" Margin="1,0" ToolTip="{Binding}" />
519523
</DataTemplate>
@@ -534,9 +538,7 @@
534538
<ItemsControl.ItemTemplate>
535539
<DataTemplate DataType="{x:Type core:Buff}">
536540
<DataTemplate.Resources>
537-
<Style TargetType="{x:Type ToolTip}" BasedOn="{StaticResource {x:Type ToolTip}}">
538-
<Setter Property="ContentTemplate" Value="{StaticResource BuffToolTipTemplate}" />
539-
</Style>
541+
<Style TargetType="{x:Type ToolTip}" BasedOn="{StaticResource BuffToolTipStyle}" />
540542
</DataTemplate.Resources>
541543
<views:BuffIcon Buff="{Binding}" Margin="1,0" ToolTip="{Binding}" />
542544
</DataTemplate>

KoAR.SaveEditor/Themes/Generic.LoadingIndicator.xaml

Lines changed: 18 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
22
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3-
xmlns:constructs="clr-namespace:KoAR.SaveEditor.Constructs">
3+
xmlns:constructs="clr-namespace:KoAR.SaveEditor.Constructs"
4+
xmlns:s="clr-namespace:System;assembly=System.Runtime">
45
<Style TargetType="{x:Type constructs:LoadingIndicator}">
56
<Setter Property="FocusVisualStyle" Value="{x:Null}" />
67
<Setter Property="Width" Value="125" />
@@ -11,45 +12,32 @@
1112
<Setter Property="Template">
1213
<Setter.Value>
1314
<ControlTemplate TargetType="{x:Type constructs:LoadingIndicator}">
15+
<ControlTemplate.Resources>
16+
<s:Double x:Key="6">6</s:Double>
17+
</ControlTemplate.Resources>
1418
<Canvas x:Name="PART_Canvas" RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Center" VerticalAlignment="Center" Width="{TemplateBinding Width}" Height="{TemplateBinding Width}"
15-
Tag="{Binding Width, RelativeSource={RelativeSource TemplatedParent}, Converter={x:Static constructs:LoadingIndicator.NumericDivisionConverter}, ConverterParameter=6}">
19+
Tag="{Binding Width, RelativeSource={RelativeSource TemplatedParent}, Converter={x:Static constructs:LoadingIndicator.NumericDivisionConverter}, ConverterParameter={StaticResource 6}}">
1620
<Canvas.Resources>
1721
<Style TargetType="{x:Type Ellipse}">
18-
<Setter Property="Width" Value="{Binding Tag, ElementName=PART_Canvas}" />
19-
<Setter Property="Height" Value="{Binding Tag, ElementName=PART_Canvas}" />
2022
<Setter Property="Stretch" Value="Fill" />
23+
<Setter Property="Width" Value="{Binding Tag, ElementName=PART_Canvas}" />
24+
<Setter Property="Height" Value="{Binding Width, RelativeSource={RelativeSource Self}}" />
2125
<Setter Property="Fill" Value="{Binding Foreground, RelativeSource={RelativeSource TemplatedParent}}" />
22-
<Setter Property="Canvas.Left">
23-
<Setter.Value>
24-
<MultiBinding Converter="{x:Static constructs:LoadingIndicator.LocationConverter}" ConverterParameter="Left">
25-
<Binding Path="Tag" ElementName="PART_Canvas" />
26-
<Binding Path="Name[6]" RelativeSource="{RelativeSource Self}" />
27-
</MultiBinding>
28-
</Setter.Value>
29-
</Setter>
30-
<Setter Property="Canvas.Top">
31-
<Setter.Value>
32-
<MultiBinding Converter="{x:Static constructs:LoadingIndicator.LocationConverter}" ConverterParameter="Top">
33-
<Binding Path="Tag" ElementName="PART_Canvas" />
34-
<Binding Path="Name[6]" RelativeSource="{RelativeSource Self}" />
35-
</MultiBinding>
36-
</Setter.Value>
37-
</Setter>
38-
<Setter Property="Opacity" Value="{Binding Name[6], RelativeSource={RelativeSource Self}, Converter={x:Static constructs:LoadingIndicator.OpacityConverter}}" />
26+
<Setter Property="Opacity" Value="{Binding Name, RelativeSource={RelativeSource Self}, Converter={x:Static constructs:LoadingIndicator.OpacityConverter}}" />
3927
</Style>
4028
</Canvas.Resources>
4129
<Canvas.RenderTransform>
4230
<RotateTransform />
4331
</Canvas.RenderTransform>
44-
<Ellipse x:Name="PART_C0" />
45-
<Ellipse x:Name="PART_C1" />
46-
<Ellipse x:Name="PART_C2" />
47-
<Ellipse x:Name="PART_C3" />
48-
<Ellipse x:Name="PART_C4" />
49-
<Ellipse x:Name="PART_C5" />
50-
<Ellipse x:Name="PART_C6" />
51-
<Ellipse x:Name="PART_C7" />
52-
<Ellipse x:Name="PART_C8" />
32+
<Ellipse x:Name="PART_C0" Canvas.Left="{constructs:LoadingEllipseLocation}" Canvas.Top="{constructs:LoadingEllipseLocation}" />
33+
<Ellipse x:Name="PART_C1" Canvas.Left="{constructs:LoadingEllipseLocation}" Canvas.Top="{constructs:LoadingEllipseLocation}" />
34+
<Ellipse x:Name="PART_C2" Canvas.Left="{constructs:LoadingEllipseLocation}" Canvas.Top="{constructs:LoadingEllipseLocation}" />
35+
<Ellipse x:Name="PART_C3" Canvas.Left="{constructs:LoadingEllipseLocation}" Canvas.Top="{constructs:LoadingEllipseLocation}" />
36+
<Ellipse x:Name="PART_C4" Canvas.Left="{constructs:LoadingEllipseLocation}" Canvas.Top="{constructs:LoadingEllipseLocation}" />
37+
<Ellipse x:Name="PART_C5" Canvas.Left="{constructs:LoadingEllipseLocation}" Canvas.Top="{constructs:LoadingEllipseLocation}" />
38+
<Ellipse x:Name="PART_C6" Canvas.Left="{constructs:LoadingEllipseLocation}" Canvas.Top="{constructs:LoadingEllipseLocation}" />
39+
<Ellipse x:Name="PART_C7" Canvas.Left="{constructs:LoadingEllipseLocation}" Canvas.Top="{constructs:LoadingEllipseLocation}" />
40+
<Ellipse x:Name="PART_C8" Canvas.Left="{constructs:LoadingEllipseLocation}" Canvas.Top="{constructs:LoadingEllipseLocation}" />
5341
</Canvas>
5442
<ControlTemplate.Triggers>
5543
<Trigger Property="IsLoading" Value="True">

0 commit comments

Comments
 (0)