Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Experiment] Shimmer #379

Closed
wants to merge 32 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
57f6732
Removing IsEnabled booloption from sample to avoid crash until bugfix
niels9001 Feb 24, 2023
0ca58f3
Removing STyledContentPresenter
niels9001 Feb 24, 2023
cd4b9ba
Removing internal reference
niels9001 Feb 24, 2023
1dce7d9
Fix for incorrect ToggleSwitch FocusVisual
niels9001 Feb 24, 2023
cb0a4f5
Replace UniformGridLayout with StackLayout
niels9001 Feb 24, 2023
e791646
Update SettingsExpander.xaml
niels9001 Feb 24, 2023
26f8875
Visual glitch fix
niels9001 Feb 24, 2023
4490c70
Bump version number
niels9001 Feb 24, 2023
8639511
Update SettingsExpanderSample.xaml.cs
niels9001 Feb 26, 2023
53b8cd5
Init --amend --author="Justin Liu <[email protected]>"
niels9001 Mar 1, 2023
f03cca7
Renaming
niels9001 Mar 1, 2023
80d44c3
XAML and MD cleanup
niels9001 Mar 1, 2023
7894a62
Sample tweaks
niels9001 Mar 2, 2023
abcb35d
Changes
niels9001 Mar 3, 2023
7318bcd
Removing whitespace
niels9001 Mar 3, 2023
8d69969
Add Justin in .md
niels9001 Mar 3, 2023
0e8fcde
Fixing CI
niels9001 Mar 3, 2023
190ca64
Only target UWP and WASDK
niels9001 Mar 3, 2023
0786c2b
Removing CompositeDisposable
niels9001 Mar 7, 2023
1d29f9c
Update Shimmer.md
niels9001 Mar 7, 2023
e53141f
Init --amend --author="Justin Liu <[email protected]>"
niels9001 Mar 1, 2023
4fd1ea7
Renaming
niels9001 Mar 1, 2023
3a2548b
XAML and MD cleanup
niels9001 Mar 1, 2023
31764eb
Sample tweaks
niels9001 Mar 2, 2023
1a7ce3e
Changes
niels9001 Mar 3, 2023
087ef8b
Removing whitespace
niels9001 Mar 3, 2023
0b39065
Add Justin in .md
niels9001 Mar 3, 2023
b4d8b18
Fixing CI
niels9001 Mar 3, 2023
b00c268
Only target UWP and WASDK
niels9001 Mar 3, 2023
2001c4b
Removing CompositeDisposable
niels9001 Mar 7, 2023
a6523ae
Update Shimmer.md
niels9001 Mar 7, 2023
0a0bc82
Merge branch 'user/niels9001/shimmer' of https://github.com/Community…
niels9001 Mar 8, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
<!-- Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE file in the project root for more information. -->
<Page x:Class="SettingsControlsExperiment.Samples.SettingsExpanderSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Expand All @@ -11,7 +11,6 @@
<labs:SettingsExpander x:Name="settingsCard"
Description="The SettingsExpander has the same properties as a Card, and you can set SettingsCard as part of the Items collection."
Header="SettingsExpander"
IsEnabled="{x:Bind IsCardEnabled, Mode=OneWay}"
IsExpanded="{x:Bind IsCardExpanded, Mode=OneWay}">
<!-- TODO: This should be TwoWay bound but throws compile error in Uno. -->
<labs:SettingsExpander.HeaderIcon>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

namespace SettingsControlsExperiment.Samples;

[ToolkitSampleBoolOption("IsCardEnabled", true, Title = "Is Enabled")]
[ToolkitSampleBoolOption("IsCardExpanded", false, Title = "Is Expanded")]
// [ToolkitSampleBoolOption("IsCardEnabled", true, Title = "Is Enabled")] Disabled for now, see: https://github.com/CommunityToolkit/Labs-Windows/issues/362

// Single values without a colon are used for both label and value.
// To provide a different label for the value, separate with a colon surrounded by a single space on both sides ("label : value").
//[ToolkitSampleMultiChoiceOption("TextSize", title: "Text size", "Small : 12", "Normal : 16", "Big : 32")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<PropertyGroup>
<ToolkitComponentName>SettingsControls</ToolkitComponentName>
<Description>This package contains the SettingsCard and SettingsExpander controls.</Description>
<Version>0.0.15</Version>
<Version>0.0.16</Version>
<LangVersion>10.0</LangVersion>

<!-- Rns suffix is required for namespaces shared across projects. See https://github.com/CommunityToolkit/Labs-Windows/issues/152 -->
Expand Down
141 changes: 141 additions & 0 deletions components/SettingsControls/src/Helpers/IsNullOrEmptyStateTrigger.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Collections;
using System.Collections.Specialized;

#if WINAPPSDK
using CommunityToolkit.WinUI.Helpers;
#else
using Microsoft.Toolkit.Uwp.Helpers;
#endif


namespace CommunityToolkit.Labs.WinUI;

/// <summary>
/// Enables a state if an Object is <c>null</c> or a String/IEnumerable is empty
/// </summary>
public class IsNullOrEmptyStateTrigger : StateTriggerBase
{
/// <summary>
/// Gets or sets the value used to check for <c>null</c> or empty.
/// </summary>
public object Value
{
get { return GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}

/// <summary>
/// Identifies the <see cref="Value"/> DependencyProperty
/// </summary>
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register(nameof(Value), typeof(object), typeof(IsNullOrEmptyStateTrigger), new PropertyMetadata(null, OnValuePropertyChanged));

public IsNullOrEmptyStateTrigger()
{
UpdateTrigger();
}

private void UpdateTrigger()
{
var val = Value;

SetActive(IsNullOrEmpty(val));

if (val == null)
{
return;
}

// Try to listen for various notification events
// Starting with INorifyCollectionChanged
#pragma warning disable CS8622 // Nullability of reference types
var valNotifyCollection = val as INotifyCollectionChanged;
if (valNotifyCollection != null)
{
var weakEvent = new WeakEventListener<IsNullOrEmptyStateTrigger, object, NotifyCollectionChangedEventArgs>(this)
{
OnEventAction = static (instance, source, args) => instance.SetActive(IsNullOrEmpty(source)),
OnDetachAction = (weakEventListener) => valNotifyCollection.CollectionChanged -= weakEventListener.OnEvent
};

valNotifyCollection.CollectionChanged += weakEvent.OnEvent;
#pragma warning restore CS8622
return;
}

// Not INotifyCollectionChanged, try IObservableVector
var valObservableVector = val as IObservableVector<object>;
if (valObservableVector != null)
{
var weakEvent = new WeakEventListener<IsNullOrEmptyStateTrigger, object, IVectorChangedEventArgs>(this)
{
OnEventAction = static (instance, source, args) => instance.SetActive(IsNullOrEmpty(source)),
OnDetachAction = (weakEventListener) => valObservableVector.VectorChanged -= weakEventListener.OnEvent
};

valObservableVector.VectorChanged += weakEvent.OnEvent;
return;
}

// Not INotifyCollectionChanged, try IObservableMap
var valObservableMap = val as IObservableMap<object, object>;
if (valObservableMap != null)
{
var weakEvent = new WeakEventListener<IsNullOrEmptyStateTrigger, object, IMapChangedEventArgs<object>>(this)
{
OnEventAction = static (instance, source, args) => instance.SetActive(IsNullOrEmpty(source)),
OnDetachAction = (weakEventListener) => valObservableMap.MapChanged -= weakEventListener.OnEvent
};

valObservableMap.MapChanged += weakEvent.OnEvent;
}
}

private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var obj = (IsNullOrEmptyStateTrigger)d;
obj.UpdateTrigger();
}

private static bool IsNullOrEmpty(object val)
{
if (val == null)
{
return true;
}

// Object is not null, check for an empty string
var valString = val as string;
if (valString != null)
{
return valString.Length == 0;
}

// Object is not a string, check for an empty ICollection (faster)
var valCollection = val as ICollection;
if (valCollection != null)
{
return valCollection.Count == 0;
}

// Object is not an ICollection, check for an empty IEnumerable
var valEnumerable = val as IEnumerable;
if (valEnumerable != null)
{
foreach (var item in valEnumerable)
{
// Found an item, not empty
return false;
}

return true;
}

// Not null and not a known type to test for emptiness
return false;
}
}
53 changes: 38 additions & 15 deletions components/SettingsControls/src/SettingsCard/SettingsCard.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -294,22 +294,12 @@
</VisualState.Setters>
</VisualState>
</VisualStateGroup>

<VisualStateGroup x:Name="ContentAlignmentStates">
<!-- Default -->
<VisualState x:Name="Right" />
<VisualState x:Name="Left">
<VisualState.StateTriggers>
<labs:IsEqualStateTrigger Value="{Binding ContentAlignment, RelativeSource={RelativeSource TemplatedParent}}"
To="Left" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="PART_HeaderIconPresenterHolder.Visibility" Value="Collapsed" />
<Setter Target="PART_DescriptionPresenter.Visibility" Value="Collapsed" />
<Setter Target="PART_HeaderPresenter.Visibility" Value="Collapsed" />
<Setter Target="PART_ContentPresenter.(Grid.Row)" Value="1" />
<Setter Target="PART_ContentPresenter.(Grid.Column)" Value="1" />
<Setter Target="PART_ContentPresenter.HorizontalAlignment" Value="Left" />
</VisualState.Setters>
</VisualState>

<!-- Whenever the control width is less than SettingsCardWrapThreshold, the Content is below the Header/Description -->
<VisualState x:Name="RightWrapped">
<VisualState.StateTriggers>
<labs:ControlSizeTrigger MinWidth="{ThemeResource SettingsCardWrapNoIconThreshold}"
Expand All @@ -325,6 +315,8 @@
<Setter Target="HeaderPanel.Margin" Value="0" />
</VisualState.Setters>
</VisualState>

<!-- For even smaller widths: the HeaderIcon is collapsed. -->
<VisualState x:Name="RightWrappedNoIcon">
<VisualState.StateTriggers>
<labs:ControlSizeTrigger MaxWidth="{ThemeResource SettingsCardWrapNoIconThreshold}"
Expand All @@ -340,6 +332,24 @@
<Setter Target="HeaderPanel.Margin" Value="0" />
</VisualState.Setters>
</VisualState>

<!-- Header/Description/Icon collapsed, content is to the left. Great for e.g. Checkboxes -->
<VisualState x:Name="Left">
<VisualState.StateTriggers>
<labs:IsEqualStateTrigger Value="{Binding ContentAlignment, RelativeSource={RelativeSource TemplatedParent}}"
To="Left" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="PART_HeaderIconPresenterHolder.Visibility" Value="Collapsed" />
<Setter Target="PART_DescriptionPresenter.Visibility" Value="Collapsed" />
<Setter Target="PART_HeaderPresenter.Visibility" Value="Collapsed" />
<Setter Target="PART_ContentPresenter.(Grid.Row)" Value="1" />
<Setter Target="PART_ContentPresenter.(Grid.Column)" Value="1" />
<Setter Target="PART_ContentPresenter.HorizontalAlignment" Value="Left" />
</VisualState.Setters>
</VisualState>

<!-- Similiar to Left, but the HeaderIcon/Header/Description is visible -->
<VisualState x:Name="Vertical">
<VisualState.StateTriggers>
<labs:IsEqualStateTrigger Value="{Binding ContentAlignment, RelativeSource={RelativeSource TemplatedParent}}"
Expand All @@ -354,6 +364,19 @@
</VisualState.Setters>
</VisualState>
</VisualStateGroup>

<!-- Collapsing the Content presenter whenever it's empty -->
<VisualStateGroup x:Name="ContentVisibilityStates">
<VisualState x:Name="Visible" />
<VisualState x:Name="Collapsed">
<VisualState.StateTriggers>
<labs:IsNullOrEmptyStateTrigger Value="{Binding Content, RelativeSource={RelativeSource TemplatedParent}}" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="PART_ContentPresenter.Visibility" Value="Collapsed" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

<Viewbox x:Name="PART_HeaderIconPresenterHolder"
Expand Down Expand Up @@ -463,6 +486,7 @@
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Control.IsTemplateFocusTarget="True"
CornerRadius="{TemplateBinding CornerRadius}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
Expand Down Expand Up @@ -964,7 +988,6 @@
Grid.ColumnSpan="3"
Margin="0,5"
Background="{ThemeResource ToggleSwitchContainerBackground}"
Control.IsTemplateFocusTarget="True"
CornerRadius="{TemplateBinding CornerRadius}" />
<ContentPresenter x:Name="OffContentPresenter"
Grid.RowSpan="3"
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using CommunityToolkit.Labs.WinUI.Internal;

namespace CommunityToolkit.Labs.WinUI;

//// Note: ItemsRepeater will request all the available horizontal space: https://github.com/microsoft/microsoft-ui-xaml/issues/3842
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
<Thickness x:Key="SettingsExpanderItemPadding">58,8,44,8</Thickness>
<Thickness x:Key="SettingsExpanderItemBorderThickness">0,1,0,0</Thickness>
<Thickness x:Key="ClickableSettingsExpanderItemPadding">58,8,16,8</Thickness>
<x:Double x:Key="SettingsExpanderContentMinHeight">16</x:Double>

<Style x:Key="DefaultSettingsExpanderItemStyle"
BasedOn="{StaticResource DefaultSettingsCardStyle}"
Expand Down Expand Up @@ -101,9 +102,7 @@
ItemTemplate="{Binding ItemTemplate, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
TabFocusNavigation="Local">
<muxc:ItemsRepeater.Layout>
<muxc:UniformGridLayout ItemsStretch="Fill"
MaximumRowsOrColumns="1"
Orientation="Horizontal" />
<muxc:StackLayout Orientation="Vertical" />
</muxc:ItemsRepeater.Layout>
</muxc:ItemsRepeater>
<ContentPresenter Grid.Row="2"
Expand Down Expand Up @@ -263,7 +262,7 @@
<Border x:Name="ExpanderContentClip"
Grid.Row="1">
<Border x:Name="ExpanderContent"
MinHeight="{TemplateBinding MinHeight}"
MinHeight="{ThemeResource SettingsExpanderContentMinHeight}"
Padding="{TemplateBinding Padding}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Expand Down
3 changes: 3 additions & 0 deletions components/Shimmer/OpenSolution.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@ECHO OFF

powershell ..\..\common\ProjectHeads\GenerateSingleSampleHeads.ps1 -componentPath %CD% %*
Binary file added components/Shimmer/samples/Assets/Owl.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions components/Shimmer/samples/Dependencies.props
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!--
WinUI 2 under UWP uses TargetFramework uap10.0.*
WinUI 3 under WinAppSdk uses TargetFramework net6.0-windows10.*
However, under Uno-powered platforms, both WinUI 2 and 3 can share the same TargetFramework.

MSBuild doesn't play nicely with this out of the box, so we've made it easy for you.

For .NET Standard packages, you can use the Nuget Package Manager in Visual Studio.
For UWP / WinAppSDK / Uno packages, place the package references here.
-->
<Project>
<!-- WinUI 2 / UWP -->
<ItemGroup Condition="'$(IsUwp)' == 'true'">
<!-- <PackageReference Include="Microsoft.Toolkit.Uwp.UI.Controls.Primitives" Version="7.1.2"/> -->
</ItemGroup>

<!-- WinUI 2 / Uno -->
<ItemGroup Condition="'$(IsUno)' == 'true' AND '$(WinUIMajorVersion)' == '2'">
<!-- <PackageReference Include="Uno.Microsoft.Toolkit.Uwp.UI.Controls.Primitives" Version="7.1.11"/> -->
</ItemGroup>

<!-- WinUI 3 / WinAppSdk -->
<ItemGroup Condition="'$(IsWinAppSdk)' == 'true'">
<!-- <PackageReference Include="CommunityToolkit.WinUI.UI.Controls.Primitives" Version="7.1.2"/> -->
</ItemGroup>

<!-- WinUI 3 / Uno -->
<ItemGroup Condition="'$(IsUno)' == 'true' AND '$(WinUIMajorVersion)' == '3'">
<!-- <PackageReference Include="Uno.CommunityToolkit.WinUI.UI.Controls.Primitives" Version="7.1.100-dev.15.g12261e2626"/> -->
</ItemGroup>
</Project>
Loading