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

Addition of MaxOpenBlades property on BladeView control #1049

Merged
merged 22 commits into from
Jun 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Expand Up @@ -11,7 +11,8 @@
<controls:BladeView Margin="0"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
BladeMode="@[BladeMode:Enum:BladeMode.Normal]">
BladeMode="@[BladeMode:Enum:BladeMode.Normal]"
AutoCollapseCountThreshold="@[AutoCollapseCountThreshold:String:4]">
<controls:BladeItem Title="Test"
IsOpen="True"
TitleBarVisibility="Collapsed">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<Grid Background="{StaticResource Brush-Grey-05}">
<controls:BladeView x:Name="BladeView"
Padding="0"
AutoCollapseCountThreshold="{Binding AutoCollapseCountThreshold.Value}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
BladeMode="{Binding BladeMode.Value}">
Expand All @@ -36,6 +37,9 @@
<ToggleButton Margin="0,24,0,0"
Content="Custom close button"
IsChecked="{Binding IsOpen, Mode=TwoWay, ElementName=FourthBlade}" />
<Button Margin="0,24,0,0"
Content="Add blade"
Click="OnAddBladeButtonClicked" />
</StackPanel>
</controls:BladeItem>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************

using Microsoft.Toolkit.Uwp.UI.Controls;
using Windows.UI.Xaml;

namespace Microsoft.Toolkit.Uwp.SampleApp.SamplePages
{
/// <summary>
Expand All @@ -21,5 +24,17 @@ public BladePage()
{
InitializeComponent();
}

private void OnAddBladeButtonClicked(object sender, RoutedEventArgs e)
{
BladeItem bladeItem = new BladeItem()
{
Title = "Default blade",
Width = 400,
IsOpen = true
};

BladeView?.Items?.Add(bladeItem);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ public partial class BladeItem
/// </summary>
public static readonly DependencyProperty CloseButtonForegroundProperty = DependencyProperty.Register(nameof(CloseButtonForeground), typeof(Brush), typeof(BladeItem), new PropertyMetadata(new SolidColorBrush(Colors.Black)));

/// <summary>
/// Identifies the <see cref="BladeItemMode"/> dependency property
/// </summary>
public static readonly DependencyProperty BladeItemModeProperty = DependencyProperty.RegisterAttached(nameof(BladeItemMode), typeof(BladeItemMode), typeof(BladeItem), new PropertyMetadata(BladeItemMode.Normal, OnBladeItemModeChanged));

/// <summary>
/// Gets or sets the foreground color of the close button
/// </summary>
Expand Down Expand Up @@ -119,11 +124,36 @@ public bool IsOpen
set { SetValue(IsOpenProperty, value); }
}

/// <summary>
/// Gets or sets a value indicating in what mode the blade should be presented, normal or small
/// </summary>
public BladeItemMode BladeItemMode
{
get { return (BladeItemMode)GetValue(BladeItemModeProperty); }
set { SetValue(BladeItemModeProperty, value); }
}

private static void IsOpenChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
BladeItem bladeItem = (BladeItem)dependencyObject;
bladeItem.Visibility = bladeItem.IsOpen ? Visibility.Visible : Visibility.Collapsed;
bladeItem.VisibilityChanged?.Invoke(bladeItem, bladeItem.Visibility);
}

private static void OnBladeItemModeChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
BladeItem bladeItem = (BladeItem)dependencyObject;

if (bladeItem.BladeItemMode == BladeItemMode.Normal)
{
VisualStateManager.GoToState(bladeItem, "Expanded", true);
bladeItem.Width = bladeItem._normalModeWidth;
}
else
{
VisualStateManager.GoToState(bladeItem, "Collapsed", true);
bladeItem.Width = double.NaN;
}
}
}
}
28 changes: 28 additions & 0 deletions Microsoft.Toolkit.Uwp.UI.Controls/BladeView/BladeItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

Expand All @@ -19,16 +20,21 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// The Blade is used as a child in the BladeView
/// </summary>
[TemplatePart(Name = "CloseButton", Type = typeof(Button))]
[TemplatePart(Name = "EnlargeButton", Type = typeof(Button))]
public partial class BladeItem : ContentControl
{
private Button _closeButton;
private Button _enlargeButton;
private double _normalModeWidth;

/// <summary>
/// Initializes a new instance of the <see cref="BladeItem"/> class.
/// </summary>
public BladeItem()
{
DefaultStyleKey = typeof(BladeItem);

SizeChanged += OnSizeChanged;
}

/// <summary>
Expand All @@ -39,6 +45,7 @@ protected override void OnApplyTemplate()
base.OnApplyTemplate();

_closeButton = GetTemplateChild("CloseButton") as Button;
_enlargeButton = GetTemplateChild("EnlargeButton") as Button;

if (_closeButton == null)
{
Expand All @@ -47,11 +54,32 @@ protected override void OnApplyTemplate()

_closeButton.Click -= CloseButton_Click;
_closeButton.Click += CloseButton_Click;

if (_enlargeButton == null)
{
return;
}

_enlargeButton.Click -= EnlargeButton_Click;
_enlargeButton.Click += EnlargeButton_Click;
}

private void OnSizeChanged(object sender, SizeChangedEventArgs sizeChangedEventArgs)
{
if (BladeItemMode == BladeItemMode.Normal)
{
_normalModeWidth = Width;
}
}

private void CloseButton_Click(object sender, RoutedEventArgs e)
{
IsOpen = false;
}

private void EnlargeButton_Click(object sender, RoutedEventArgs e)
{
BladeItemMode = BladeItemMode == BladeItemMode.Normal ? BladeItemMode.Small : BladeItemMode.Normal;
}
}
}
30 changes: 30 additions & 0 deletions Microsoft.Toolkit.Uwp.UI.Controls/BladeView/BladeItemMode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************

namespace Microsoft.Toolkit.Uwp.UI.Controls
{
/// <summary>
/// Blade item mode
/// </summary>
public enum BladeItemMode
{
/// <summary>
/// Normal mode
/// </summary>
Normal,

/// <summary>
/// Small mode
/// </summary>
Small
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ public partial class BladeView
/// </summary>
public static readonly DependencyProperty BladeModeProperty = DependencyProperty.RegisterAttached(nameof(BladeMode), typeof(BladeMode), typeof(BladeView), new PropertyMetadata(BladeMode.Normal, OnBladeModeChanged));

/// <summary>
/// Identifies the <see cref="AutoCollapseCountThreshold"/> attached property.
/// </summary>
public static readonly DependencyProperty AutoCollapseCountThresholdProperty = DependencyProperty.RegisterAttached(nameof(AutoCollapseCountThreshold), typeof(int), typeof(BladeView), new PropertyMetadata(int.MaxValue, OnOpenBladesChanged));

/// <summary>
/// Gets or sets a collection of visible blades
/// </summary>
Expand All @@ -51,6 +56,24 @@ public BladeMode BladeMode
set { SetValue(BladeModeProperty, value); }
}

/// <summary>
/// Gets or sets a value indicating what the overflow amount should be to start auto collapsing blade items
/// </summary>
/// <example>
/// For example we put AutoCollapseCountThreshold = 2
/// This means that each time a blade is added to the bladeview collection,
/// we will validate the amount of added blades that have a title bar visible.
/// If this number get's bigger than AutoCollapseCountThreshold, we will collapse all blades but the last one
/// </example>
/// <remarks>
/// We don't touch blade items that have no title bar
/// </remarks>
public int AutoCollapseCountThreshold
{
get { return (int)GetValue(AutoCollapseCountThresholdProperty); }
set { SetValue(AutoCollapseCountThresholdProperty, value); }
}

private static void OnBladeModeChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
var bladeView = (BladeView)dependencyObject;
Expand All @@ -60,9 +83,13 @@ private static void OnBladeModeChanged(DependencyObject dependencyObject, Depend
{
// Cache previous values of blade items properties (width & height)
bladeView._cachedBladeItemSizes.Clear();
foreach (BladeItem bladeItem in bladeView.Items)

if (bladeView.Items != null)
{
bladeView._cachedBladeItemSizes.Add(bladeItem, new Size(bladeItem.Width, bladeItem.Height));
foreach (BladeItem bladeItem in bladeView.Items)
{
bladeView._cachedBladeItemSizes.Add(bladeItem, new Size(bladeItem.Width, bladeItem.Height));
}
}

VisualStateManager.GoToState(bladeView, "FullScreen", false);
Expand All @@ -85,5 +112,11 @@ private static void OnBladeModeChanged(DependencyObject dependencyObject, Depend
// Execute change of blade item size
bladeView.AdjustBladeItemSize();
}

private static void OnOpenBladesChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
{
var bladeView = (BladeView)dependencyObject;
bladeView.CycleBlades();
}
}
}
27 changes: 26 additions & 1 deletion Microsoft.Toolkit.Uwp.UI.Controls/BladeView/BladeView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ protected override void PrepareContainerForItemOverride(DependencyObject element
}

base.PrepareContainerForItemOverride(element, item);
CycleBlades();
}

/// <summary>
Expand Down Expand Up @@ -108,6 +109,19 @@ private void CycleBlades()
ActiveBlades.Add(blade);
}
}

// For now we skip this feature when blade mode is set to fullscreen
if (AutoCollapseCountThreshold > 0 && BladeMode != BladeMode.Fullscreen && ActiveBlades.Any())
{
var openBlades = ActiveBlades.Where(item => item.TitleBarVisibility == Visibility.Visible).ToList();
Copy link
Contributor

@skendrot skendrot Jun 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should check the expand mode instead of the visibility of the title bar. This could be set by the user

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding was that the TitleBarVisibility property was used to pin blades to the screen.
I want to filter the pinned once out, they are not touched by the auto resize mechanism.
@skendrot Is there another property that tells me this? I don't seem to find it...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right! Thanks for pointing that out

if (openBlades.Count > AutoCollapseCountThreshold)
{
for (int i = 0; i < openBlades.Count - 1; i++)
{
openBlades[i].BladeItemMode = BladeItemMode.Small;
}
}
}
}

private async void BladeOnVisibilityChanged(object sender, Visibility visibility)
Expand All @@ -116,6 +130,11 @@ private async void BladeOnVisibilityChanged(object sender, Visibility visibility

if (visibility == Visibility.Visible)
{
if (Items == null)
{
return;
}

Items.Remove(blade);
Items.Add(blade);
BladeOpened?.Invoke(this, blade);
Expand All @@ -133,6 +152,12 @@ await Dispatcher.RunAsync(CoreDispatcherPriority.Low, () =>

BladeClosed?.Invoke(this, blade);
ActiveBlades.Remove(blade);

var lastBlade = ActiveBlades.LastOrDefault();
if (lastBlade != null && lastBlade.TitleBarVisibility == Visibility.Visible)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't check the titlebar visibility. This can be set to collapsed by the user but still want the last blade to be expanded

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same remark as above, I don't want to auto size pinned blades.

{
lastBlade.BladeItemMode = BladeItemMode.Normal;
}
}

private ScrollViewer GetScrollViewer()
Expand Down Expand Up @@ -175,4 +200,4 @@ private void ItemsVectorChanged(IObservableVector<object> sender, IVectorChanged
}
}
}
}
}
30 changes: 27 additions & 3 deletions Microsoft.Toolkit.Uwp.UI.Controls/BladeView/BladeView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,19 @@
<ControlTemplate TargetType="controls:BladeItem">
<Grid BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ExpandedStates">
<VisualState x:Name="Expanded"/>
<VisualState x:Name="Collapsed">
<VisualState.Setters>
<Setter Target="TitleBar.Visibility" Value="Collapsed" />
<Setter Target="ContentPresenter.Visibility" Value="Collapsed" />
<Setter Target="EnlargeButton.Content" Value="&#xE1D9;"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>

<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
Expand All @@ -115,25 +128,36 @@
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>

<TextBlock Margin="4,0,0,0"
<TextBlock x:Name="TitleBar"
Margin="4,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="{TemplateBinding TitleBarForeground}"
Text="{TemplateBinding Title}" />
<Button Name="CloseButton"
<Button Name="EnlargeButton"
Grid.Column="1"
TabIndex="0"
HorizontalAlignment="Right"
Background="{TemplateBinding CloseButtonBackground}"
Content="&#xE73F;"
FontFamily="Segoe MDL2 Assets"
Foreground="{TemplateBinding CloseButtonForeground}" />
<Button Name="CloseButton"
Grid.Column="2"
TabIndex="0"
HorizontalAlignment="Right"
AutomationProperties.Name="Cancel"
Background="{TemplateBinding CloseButtonBackground}"
Content="&#xE711;"
FontFamily="Segoe MDL2 Assets"
Foreground="{TemplateBinding CloseButtonForeground}" />
</Grid>

<ContentPresenter Grid.Row="1"
<ContentPresenter x:Name="ContentPresenter"
Grid.Row="1"
VerticalAlignment="Stretch"
Background="{TemplateBinding Background}"
Visibility="{TemplateBinding IsOpen}" />
Expand Down
Loading