Skip to content

Commit f37635a

Browse files
committed
Created ToolkitSampleButtonActionAttribute, general cleanup
1 parent d34f725 commit f37635a

12 files changed

Lines changed: 341 additions & 88 deletions

CommunityToolkit.App.Shared/Renderers/GeneratedSampleOptionTemplateSelector.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ internal class GeneratedSampleOptionTemplateSelector : DataTemplateSelector
1313
{
1414
public DataTemplate? BoolOptionTemplate { get; set; }
1515

16+
public DataTemplate? ButtonActionTemplate { get; set; }
17+
1618
public DataTemplate? MultiChoiceOptionTemplate { get; set; }
1719

1820
public DataTemplate? SliderOptionTemplate { get; set; }
@@ -26,6 +28,7 @@ protected override DataTemplate SelectTemplateCore(object item, DependencyObject
2628
return item switch
2729
{
2830
ToolkitSampleBoolOptionMetadataViewModel => BoolOptionTemplate ?? base.SelectTemplateCore(item, container),
31+
ToolkitSampleButtonActionMetadataViewModel => ButtonActionTemplate ?? base.SelectTemplateCore(item, container),
2932
ToolkitSampleMultiChoiceOptionMetadataViewModel => MultiChoiceOptionTemplate ?? base.SelectTemplateCore(item, container),
3033
ToolkitSampleNumericOptionMetadataViewModel { ShowAsNumberBox: true } => NumberBoxOptionTemplate ?? base.SelectTemplateCore(item, container),
3134
ToolkitSampleNumericOptionMetadataViewModel { ShowAsNumberBox: false } => SliderOptionTemplate ?? base.SelectTemplateCore(item, container),

CommunityToolkit.App.Shared/Renderers/GeneratedSampleOptionsRenderer.xaml

Lines changed: 59 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -12,58 +12,64 @@
1212
d:DesignWidth="400"
1313
mc:Ignorable="d">
1414

15-
<UserControl.Resources>
16-
<local:GeneratedSampleOptionTemplateSelector x:Key="GeneratedSampleOptionTemplateSelector">
17-
<local:GeneratedSampleOptionTemplateSelector.BoolOptionTemplate>
18-
<DataTemplate x:DataType="metadata:ToolkitSampleBoolOptionMetadataViewModel">
19-
<ToggleSwitch Header="{x:Bind Title, Mode=OneWay}"
20-
IsOn="{x:Bind BoolValue, Mode=TwoWay}" />
21-
</DataTemplate>
22-
</local:GeneratedSampleOptionTemplateSelector.BoolOptionTemplate>
23-
<local:GeneratedSampleOptionTemplateSelector.MultiChoiceOptionTemplate>
24-
<DataTemplate x:DataType="metadata:ToolkitSampleMultiChoiceOptionMetadataViewModel">
25-
<ComboBox Header="{x:Bind Title, Mode=OneWay}"
26-
ItemsSource="{x:Bind Options}"
27-
SelectedIndex="0"
28-
SelectedItem="{x:Bind Value, Mode=TwoWay}" />
29-
</DataTemplate>
30-
</local:GeneratedSampleOptionTemplateSelector.MultiChoiceOptionTemplate>
31-
<local:GeneratedSampleOptionTemplateSelector.SliderOptionTemplate>
32-
<DataTemplate x:DataType="metadata:ToolkitSampleNumericOptionMetadataViewModel">
33-
<Slider Header="{x:Bind Title, Mode=OneWay}"
34-
Maximum="{x:Bind Max, Mode=OneWay}"
35-
Minimum="{x:Bind Min, Mode=OneWay}"
36-
StepFrequency="{x:Bind Step, Mode=OneWay}"
37-
Value="{x:Bind Initial, Mode=TwoWay}" />
38-
</DataTemplate>
39-
</local:GeneratedSampleOptionTemplateSelector.SliderOptionTemplate>
40-
<local:GeneratedSampleOptionTemplateSelector.NumberBoxOptionTemplate>
41-
<DataTemplate x:DataType="metadata:ToolkitSampleNumericOptionMetadataViewModel">
42-
<muxc:NumberBox Header="{x:Bind Title, Mode=OneWay}"
43-
Maximum="{x:Bind Max, Mode=OneWay}"
44-
Minimum="{x:Bind Min, Mode=OneWay}"
45-
SmallChange="{x:Bind Step, Mode=OneWay}"
46-
SpinButtonPlacementMode="Compact"
47-
Value="{x:Bind Initial, Mode=TwoWay}" />
48-
</DataTemplate>
49-
</local:GeneratedSampleOptionTemplateSelector.NumberBoxOptionTemplate>
50-
<local:GeneratedSampleOptionTemplateSelector.TextOptionTemplate>
51-
<DataTemplate x:DataType="metadata:ToolkitSampleTextOptionMetadataViewModel">
52-
<TextBox HorizontalAlignment="Stretch"
53-
Header="{x:Bind Title, Mode=OneWay}"
54-
Text="{x:Bind PlaceholderText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
55-
</DataTemplate>
56-
</local:GeneratedSampleOptionTemplateSelector.TextOptionTemplate>
57-
</local:GeneratedSampleOptionTemplateSelector>
58-
</UserControl.Resources>
15+
<UserControl.Resources>
16+
<local:GeneratedSampleOptionTemplateSelector x:Key="GeneratedSampleOptionTemplateSelector">
17+
<local:GeneratedSampleOptionTemplateSelector.BoolOptionTemplate>
18+
<DataTemplate x:DataType="metadata:ToolkitSampleBoolOptionMetadataViewModel">
19+
<ToggleSwitch Header="{x:Bind Title, Mode=OneWay}"
20+
IsOn="{x:Bind BoolValue, Mode=TwoWay}" />
21+
</DataTemplate>
22+
</local:GeneratedSampleOptionTemplateSelector.BoolOptionTemplate>
23+
<local:GeneratedSampleOptionTemplateSelector.ButtonActionTemplate>
24+
<DataTemplate x:DataType="metadata:ToolkitSampleButtonActionMetadataViewModel">
25+
<Button Command="{x:Bind CommandValue, Mode=TwoWay}"
26+
Content="{x:Bind Label, Mode=OneWay}" />
27+
</DataTemplate>
28+
</local:GeneratedSampleOptionTemplateSelector.ButtonActionTemplate>
29+
<local:GeneratedSampleOptionTemplateSelector.MultiChoiceOptionTemplate>
30+
<DataTemplate x:DataType="metadata:ToolkitSampleMultiChoiceOptionMetadataViewModel">
31+
<ComboBox Header="{x:Bind Title, Mode=OneWay}"
32+
ItemsSource="{x:Bind Options}"
33+
SelectedIndex="0"
34+
SelectedItem="{x:Bind Value, Mode=TwoWay}" />
35+
</DataTemplate>
36+
</local:GeneratedSampleOptionTemplateSelector.MultiChoiceOptionTemplate>
37+
<local:GeneratedSampleOptionTemplateSelector.SliderOptionTemplate>
38+
<DataTemplate x:DataType="metadata:ToolkitSampleNumericOptionMetadataViewModel">
39+
<Slider Header="{x:Bind Title, Mode=OneWay}"
40+
Maximum="{x:Bind Max, Mode=OneWay}"
41+
Minimum="{x:Bind Min, Mode=OneWay}"
42+
StepFrequency="{x:Bind Step, Mode=OneWay}"
43+
Value="{x:Bind Initial, Mode=TwoWay}" />
44+
</DataTemplate>
45+
</local:GeneratedSampleOptionTemplateSelector.SliderOptionTemplate>
46+
<local:GeneratedSampleOptionTemplateSelector.NumberBoxOptionTemplate>
47+
<DataTemplate x:DataType="metadata:ToolkitSampleNumericOptionMetadataViewModel">
48+
<muxc:NumberBox Header="{x:Bind Title, Mode=OneWay}"
49+
Maximum="{x:Bind Max, Mode=OneWay}"
50+
Minimum="{x:Bind Min, Mode=OneWay}"
51+
SmallChange="{x:Bind Step, Mode=OneWay}"
52+
SpinButtonPlacementMode="Compact"
53+
Value="{x:Bind Initial, Mode=TwoWay}" />
54+
</DataTemplate>
55+
</local:GeneratedSampleOptionTemplateSelector.NumberBoxOptionTemplate>
56+
<local:GeneratedSampleOptionTemplateSelector.TextOptionTemplate>
57+
<DataTemplate x:DataType="metadata:ToolkitSampleTextOptionMetadataViewModel">
58+
<TextBox HorizontalAlignment="Stretch"
59+
Header="{x:Bind Title, Mode=OneWay}"
60+
Text="{x:Bind PlaceholderText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
61+
</DataTemplate>
62+
</local:GeneratedSampleOptionTemplateSelector.TextOptionTemplate>
63+
</local:GeneratedSampleOptionTemplateSelector>
64+
</UserControl.Resources>
5965

60-
<ItemsControl ItemTemplateSelector="{StaticResource GeneratedSampleOptionTemplateSelector}"
61-
ItemsSource="{x:Bind SampleOptions, Mode=OneWay}">
62-
<ItemsControl.ItemsPanel>
63-
<ItemsPanelTemplate>
64-
<StackPanel Orientation="Vertical"
65-
Spacing="12" />
66-
</ItemsPanelTemplate>
67-
</ItemsControl.ItemsPanel>
68-
</ItemsControl>
66+
<ItemsControl ItemTemplateSelector="{StaticResource GeneratedSampleOptionTemplateSelector}"
67+
ItemsSource="{x:Bind SampleOptions, Mode=OneWay}">
68+
<ItemsControl.ItemsPanel>
69+
<ItemsPanelTemplate>
70+
<StackPanel Orientation="Vertical"
71+
Spacing="12" />
72+
</ItemsPanelTemplate>
73+
</ItemsControl.ItemsPanel>
74+
</ItemsControl>
6975
</UserControl>

CommunityToolkit.Tooling.SampleGen/Attributes/ToolkitSampleBoolOptionAttribute.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ public sealed class ToolkitSampleBoolOptionAttribute : ToolkitSampleOptionBaseAt
2323
public ToolkitSampleBoolOptionAttribute(string bindingName, bool defaultState)
2424
: base(bindingName, defaultState)
2525
{
26-
2726
}
2827

2928
/// <summary>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
namespace CommunityToolkit.Tooling.SampleGen.Attributes;
6+
7+
/// <summary>
8+
/// Generates a command that invokes the decorated method, and a button in the sample option panel that invokes the command when clicked.
9+
/// </summary>
10+
/// <remarks>
11+
/// Using this attribute will automatically generate an <see cref="INotifyPropertyChanged"/>-enabled property
12+
/// that you can bind to in XAML, and displays an options pane alonside your sample which allows the user to manipulate the property.
13+
/// </remarks>
14+
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
15+
public sealed class ToolkitSampleButtonActionAttribute : ToolkitSampleOptionBaseAttribute
16+
{
17+
/// <summary>
18+
/// Creates a new instance of <see cref="ToolkitSampleButtonActionAttribute"/>.
19+
/// </summary>
20+
/// <param name="label">The text displayed inside the button.</param>
21+
public ToolkitSampleButtonActionAttribute(string label)
22+
: base(string.Empty, null)
23+
{
24+
Label = label;
25+
}
26+
27+
public string Label { get; }
28+
29+
/// <summary>
30+
/// The source generator-friendly type name used for casting.
31+
/// </summary>
32+
internal override string TypeName { get; } = "System.Windows.Input.ICommand";
33+
}

CommunityToolkit.Tooling.SampleGen/Attributes/ToolkitSampleMultiChoiceOptionAttribute.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
namespace CommunityToolkit.Tooling.SampleGen.Attributes;
66

77
/// <summary>
8-
/// Represents a boolean sample option.
8+
/// Generates a property and multi-choice option in the sample option pane that can be used to update it.
99
/// </summary>
1010
/// <remarks>
1111
/// Using this attribute will automatically generate an <see cref="INotifyPropertyChanged"/>-enabled property

CommunityToolkit.Tooling.SampleGen/Attributes/ToolkitSampleOptionBaseAttribute.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public ToolkitSampleOptionBaseAttribute(string bindingName, object? defaultState
2424
/// <summary>
2525
/// A name that you can bind to in your XAML.
2626
/// </summary>
27-
public string Name { get; }
27+
public string Name { get; internal set; }
2828

2929
/// <summary>
3030
/// The default state.

CommunityToolkit.Tooling.SampleGen/CommunityToolkit.Tooling.SampleGen.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<TargetFramework>netstandard2.0</TargetFramework>
55
<Nullable>enable</Nullable>
66
<WarningsAsErrors>nullable</WarningsAsErrors>
7-
<LangVersion>10.0</LangVersion>
7+
<LangVersion>11.0</LangVersion>
88
</PropertyGroup>
99

1010
<ItemGroup>

CommunityToolkit.Tooling.SampleGen/GeneratorExtensions.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,21 @@ public static class GeneratorExtensions
1212
/// Crawls a namespace and all child namespaces for all contained types.
1313
/// </summary>
1414
/// <returns>A flattened enumerable of <see cref="INamedTypeSymbol"/>s.</returns>
15-
public static IEnumerable<INamedTypeSymbol> CrawlForAllNamedTypes(this INamespaceSymbol namespaceSymbol)
15+
public static IEnumerable<ISymbol> CrawlForAllSymbols(this INamespaceSymbol namespaceSymbol, SymbolKind symbolKind)
1616
{
1717
foreach (var member in namespaceSymbol.GetMembers())
1818
{
1919
if (member is INamespaceSymbol nestedNamespace)
2020
{
21-
foreach (var item in CrawlForAllNamedTypes(nestedNamespace))
21+
foreach (var item in CrawlForAllSymbols(nestedNamespace, symbolKind))
2222
yield return item;
2323
}
2424

25-
if (member is INamedTypeSymbol typeSymbol)
26-
yield return typeSymbol;
25+
foreach (Enum value in Enum.GetValues(typeof(SymbolKind)))
26+
{
27+
if (symbolKind.HasFlag(value) && member.Kind.HasFlag(value))
28+
yield return member;
29+
}
2730
}
2831
}
2932

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using CommunityToolkit.Tooling.SampleGen.Attributes;
6+
using System.Windows.Input;
7+
8+
namespace CommunityToolkit.Tooling.SampleGen.Metadata;
9+
10+
/// <summary>
11+
/// An INPC-enabled metadata container for data defined in an <see cref="ToolkitSampleButtonActionAttribute"/>.
12+
/// </summary>
13+
/// <remarks>
14+
/// Instances of these are generated by the <see cref="ToolkitSampleMetadataGenerator"/> and
15+
/// provided to the app alongside the sample registration.
16+
/// </remarks>
17+
public class ToolkitSampleButtonActionMetadataViewModel : IGeneratedToolkitSampleOptionViewModel
18+
{
19+
private string? _title;
20+
private object? _value;
21+
private string _label;
22+
23+
/// <summary>
24+
/// Creates a new instance of <see cref="ToolkitSampleButtonActionMetadataViewModel"/>.
25+
/// </summary>
26+
public ToolkitSampleButtonActionMetadataViewModel(string name, string label, string? title = null)
27+
{
28+
Name = name;
29+
30+
_label = label;
31+
_title = title;
32+
}
33+
34+
/// <inheritdoc cref="INotifyPropertyChanged.PropertyChanged"/>
35+
public event PropertyChangedEventHandler? PropertyChanged;
36+
37+
/// <summary>
38+
/// A unique identifier for this option.
39+
/// </summary>
40+
/// <remarks>
41+
/// Used by the sample system to match up <see cref="ToolkitSampleButtonActionMetadataViewModel"/> to the original <see cref="ToolkitSampleButtonActionAttribute"/> and the control that declared it.
42+
/// </remarks>
43+
public string Name { get; }
44+
45+
/// <summary>
46+
/// The current boolean value.
47+
/// </summary>
48+
/// <remarks>
49+
/// Provided to accomodate binding to a property that is a non-nullable <see cref="bool"/>.
50+
/// </remarks>
51+
public ICommand CommandValue
52+
{
53+
get => (ICommand)_value!;
54+
set
55+
{
56+
_value = value;
57+
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value)));
58+
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CommandValue)));
59+
}
60+
}
61+
62+
/// <summary>
63+
/// The current boolean value.
64+
/// </summary>
65+
public object? Value
66+
{
67+
get => _value;
68+
set
69+
{
70+
_value = value;
71+
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Value)));
72+
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CommandValue)));
73+
}
74+
}
75+
76+
/// <summary>
77+
/// The label to display inside the button.
78+
/// </summary>
79+
public string Label
80+
{
81+
get => _label;
82+
set
83+
{
84+
_label = value;
85+
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Label)));
86+
}
87+
}
88+
89+
/// <summary>
90+
/// A title to display on top of the button.
91+
/// </summary>
92+
public string? Title
93+
{
94+
get => _title;
95+
set
96+
{
97+
_title = value;
98+
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Title)));
99+
}
100+
}
101+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Windows.Input;
6+
7+
namespace CommunityToolkit.Tooling.SampleGen.Metadata;
8+
9+
/// <summary>
10+
/// A command that invokes the provided <see cref="Action"/> when executed.
11+
/// </summary>
12+
public class ToolkitSampleButtonCommand : ICommand
13+
{
14+
private readonly Action _callback;
15+
16+
public ToolkitSampleButtonCommand(Action callback)
17+
{
18+
_callback = callback;
19+
}
20+
21+
/// <inheritdoc />
22+
public event EventHandler? CanExecuteChanged;
23+
24+
/// <inheritdoc />
25+
public bool CanExecute(object parameter)
26+
{
27+
throw new NotImplementedException();
28+
}
29+
/// <inheritdoc />
30+
public void Execute(object parameter)
31+
{
32+
_callback();
33+
}
34+
}

0 commit comments

Comments
 (0)