Skip to content

Commit 9fa8929

Browse files
committed
### **Resolved / Related Issues**
Closes [Feature: Make columns resizable in Column Layout](#6534) --- ### **Steps used to test these changes** 1. Opened Files and confirmed that: - Columns are resizable using the splitter between them - Cursor changes to a resize icon when hovering over the column divider - Double-clicking the divider resets to default width - Content inside each column adjusts correctly to new width - No visual glitches appear when resizing multiple columns rapidly 2. Verified that: - Column resizing works with mouse. - Resizing does not interfere with item selection, list scroll or navigation - Minimum and maximum column widths are respected
1 parent b478218 commit 9fa8929

File tree

3 files changed

+131
-1
lines changed

3 files changed

+131
-1
lines changed

src/Files.App.Controls/BladeView/BladeItem.cs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using Microsoft.UI.Input;
45
using Microsoft.UI.Xaml.Automation.Peers;
6+
using Microsoft.UI.Xaml.Input;
57

68
namespace Files.App.Controls
79
{
@@ -11,7 +13,14 @@ namespace Files.App.Controls
1113
[TemplatePart(Name = "CloseButton", Type = typeof(Button))]
1214
public partial class BladeItem : ContentControl
1315
{
16+
private const double MINIMUM_WIDTH = 150;
17+
private const double DEFAULT_WIDTH = 300; // Default width for the blade item
18+
1419
private Button _closeButton;
20+
private Border _bladeResizer;
21+
private bool draggingSidebarResizer;
22+
private double preManipulationSidebarWidth = 0;
23+
1524
/// <summary>
1625
/// Initializes a new instance of the <see cref="BladeItem"/> class.
1726
/// </summary>
@@ -36,7 +45,31 @@ protected override void OnApplyTemplate()
3645

3746
_closeButton.Click -= CloseButton_Click;
3847
_closeButton.Click += CloseButton_Click;
48+
49+
_bladeResizer = GetTemplateChild("BladeResizer") as Border;
50+
51+
if (_bladeResizer != null)
52+
{
53+
_bladeResizer.ManipulationStarted -= BladeResizer_ManipulationStarted;
54+
_bladeResizer.ManipulationStarted += BladeResizer_ManipulationStarted;
55+
56+
_bladeResizer.ManipulationDelta -= BladeResizer_ManipulationDelta;
57+
_bladeResizer.ManipulationDelta += BladeResizer_ManipulationDelta;
58+
59+
_bladeResizer.ManipulationCompleted -= BladeResizer_ManipulationCompleted;
60+
_bladeResizer.ManipulationCompleted += BladeResizer_ManipulationCompleted;
61+
62+
_bladeResizer.PointerEntered -= BladeResizer_PointerEntered;
63+
_bladeResizer.PointerEntered += BladeResizer_PointerEntered;
64+
65+
_bladeResizer.PointerExited -= BladeResizer_PointerExited;
66+
_bladeResizer.PointerExited += BladeResizer_PointerExited;
67+
68+
_bladeResizer.DoubleTapped -= BladeResizer_DoubleTapped;
69+
_bladeResizer.DoubleTapped += BladeResizer_DoubleTapped;
70+
}
3971
}
72+
4073
/// <summary>
4174
/// Creates AutomationPeer (<see cref="UIElement.OnCreateAutomationPeer"/>)
4275
/// </summary>
@@ -50,5 +83,57 @@ private void CloseButton_Click(object sender, RoutedEventArgs e)
5083
{
5184
IsOpen = false;
5285
}
86+
private void BladeResizer_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
87+
{
88+
draggingSidebarResizer = true;
89+
preManipulationSidebarWidth = ActualWidth;
90+
VisualStateManager.GoToState(this, "ResizerPressed", true);
91+
e.Handled = true;
92+
}
93+
94+
private void BladeResizer_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
95+
{
96+
var newWidth = preManipulationSidebarWidth + e.Cumulative.Translation.X;
97+
98+
Debug.WriteLine($"BladeResizer - New item width: {newWidth}");
99+
100+
if (newWidth < MINIMUM_WIDTH)
101+
newWidth = MINIMUM_WIDTH;
102+
103+
Width = newWidth;
104+
e.Handled = true;
105+
}
106+
107+
private void BladeResizer_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
108+
{
109+
draggingSidebarResizer = false;
110+
VisualStateManager.GoToState(this, "ResizerNormal", true);
111+
e.Handled = true;
112+
}
113+
114+
private void BladeResizer_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
115+
{
116+
Width = DEFAULT_WIDTH;
117+
e.Handled = true;
118+
}
119+
120+
private void BladeResizer_PointerEntered(object sender, PointerRoutedEventArgs e)
121+
{
122+
var sidebarResizer = (FrameworkElement)sender;
123+
sidebarResizer.ChangeCursor(InputSystemCursor.Create(InputSystemCursorShape.SizeWestEast));
124+
VisualStateManager.GoToState(this, "ResizerPointerOver", true);
125+
e.Handled = true;
126+
}
127+
128+
private void BladeResizer_PointerExited(object sender, PointerRoutedEventArgs e)
129+
{
130+
if (draggingSidebarResizer)
131+
return;
132+
133+
var sidebarResizer = (FrameworkElement)sender;
134+
sidebarResizer.ChangeCursor(InputSystemCursor.Create(InputSystemCursorShape.Arrow));
135+
VisualStateManager.GoToState(this, "ResizerNormal", true);
136+
e.Handled = true;
137+
}
53138
}
54139
}

src/Files.App.Controls/BladeView/BladeView.xaml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,24 @@
114114
VerticalAlignment="Stretch"
115115
Background="{TemplateBinding Background}" />
116116

117+
<!-- Resizer -->
118+
<Border
119+
x:Name="BladeResizer"
120+
Width="4"
121+
HorizontalAlignment="Right"
122+
VerticalAlignment="Stretch"
123+
AllowFocusOnInteraction="True"
124+
Background="Transparent"
125+
BorderBrush="Transparent"
126+
CornerRadius="2"
127+
DoubleTapped="BladeResizer_DoubleTapped"
128+
ManipulationCompleted="BladeResizer_ManipulationCompleted"
129+
ManipulationDelta="BladeResizer_ManipulationDelta"
130+
ManipulationMode="TranslateX"
131+
ManipulationStarted="BladeResizer_ManipulationStarted"
132+
PointerEntered="BladeResizer_PointerEntered"
133+
PointerExited="BladeResizer_PointerExited" />
134+
117135
<Button
118136
Name="CloseButton"
119137
HorizontalAlignment="Right"
@@ -127,6 +145,33 @@
127145
Style="{StaticResource ButtonRevealStyle}"
128146
TabIndex="0"
129147
Visibility="{TemplateBinding CloseButtonVisibility}" />
148+
149+
<VisualStateManager.VisualStateGroups>
150+
<VisualStateGroup x:Name="ResizerStates">
151+
<VisualState x:Name="ResizerNormal" />
152+
<VisualState x:Name="ResizerPointerOver">
153+
<Storyboard>
154+
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BladeResizer" Storyboard.TargetProperty="Background">
155+
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource CardStrokeColorDefaultSolidBrush}" />
156+
</ObjectAnimationUsingKeyFrames>
157+
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BladeResizer" Storyboard.TargetProperty="BorderBrush">
158+
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource CardStrokeColorDefaultSolidBrush}" />
159+
</ObjectAnimationUsingKeyFrames>
160+
</Storyboard>
161+
</VisualState>
162+
163+
<VisualState x:Name="ResizerPressed">
164+
<Storyboard>
165+
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BladeResizer" Storyboard.TargetProperty="Background">
166+
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SolidBackgroundFillColorSecondaryBrush}" />
167+
</ObjectAnimationUsingKeyFrames>
168+
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BladeResizer" Storyboard.TargetProperty="BorderBrush">
169+
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SolidBackgroundFillColorSecondaryBrush}" />
170+
</ObjectAnimationUsingKeyFrames>
171+
</Storyboard>
172+
</VisualState>
173+
</VisualStateGroup>
174+
</VisualStateManager.VisualStateGroups>
130175
</Grid>
131176
</ControlTemplate>
132177
</Setter.Value>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
cb1ca000ef2f03f1afc7bde9ed4fb2987669c89a58b63919e67574696091f60f
1+
675e2af6383af3d850edd90be04a39cc57a15d9d271546aceeaf576d0a06da21

0 commit comments

Comments
 (0)