Skip to content

Commit d5f4a2f

Browse files
authored
Feature: Added action to switch focus between panes (#15485)
1 parent 4cd471a commit d5f4a2f

File tree

9 files changed

+152
-49
lines changed

9 files changed

+152
-49
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) 2024 Files Community
2+
// Licensed under the MIT License. See the LICENSE.
3+
4+
namespace Files.App.Actions
5+
{
6+
internal sealed class FocusLeftPaneAction : ObservableObject, IAction
7+
{
8+
private readonly IContentPageContext context;
9+
10+
public string Label
11+
=> "FocusLeftPane".GetLocalizedResource();
12+
13+
public string Description
14+
=> "FocusLeftPaneDescription".GetLocalizedResource();
15+
16+
public HotKey HotKey
17+
=> new(Keys.Left, KeyModifiers.CtrlShift);
18+
19+
public bool IsExecutable
20+
=> context.IsMultiPaneActive;
21+
22+
public FocusLeftPaneAction()
23+
{
24+
context = Ioc.Default.GetRequiredService<IContentPageContext>();
25+
26+
context.PropertyChanged += Context_PropertyChanged;
27+
}
28+
29+
public Task ExecuteAsync(object? parameter = null)
30+
{
31+
context.ShellPage!.PaneHolder.FocusLeftPane();
32+
33+
return Task.CompletedTask;
34+
}
35+
36+
private void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
37+
{
38+
switch (e.PropertyName)
39+
{
40+
case nameof(IContentPageContext.ShellPage):
41+
case nameof(IContentPageContext.IsMultiPaneActive):
42+
OnPropertyChanged(nameof(IsExecutable));
43+
break;
44+
}
45+
}
46+
}
47+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) 2024 Files Community
2+
// Licensed under the MIT License. See the LICENSE.
3+
4+
namespace Files.App.Actions
5+
{
6+
internal sealed class FocusRightPaneAction : ObservableObject, IAction
7+
{
8+
private readonly IContentPageContext context;
9+
10+
public string Label
11+
=> "FocusRightPane".GetLocalizedResource();
12+
13+
public string Description
14+
=> "FocusRightPaneDescription".GetLocalizedResource();
15+
16+
public HotKey HotKey
17+
=> new(Keys.Right, KeyModifiers.CtrlShift);
18+
19+
public bool IsExecutable
20+
=> context.IsMultiPaneActive;
21+
22+
public FocusRightPaneAction()
23+
{
24+
context = Ioc.Default.GetRequiredService<IContentPageContext>();
25+
26+
context.PropertyChanged += Context_PropertyChanged;
27+
}
28+
29+
public Task ExecuteAsync(object? parameter = null)
30+
{
31+
context.ShellPage!.PaneHolder.FocusRightPane();
32+
33+
return Task.CompletedTask;
34+
}
35+
36+
private void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
37+
{
38+
switch (e.PropertyName)
39+
{
40+
case nameof(IContentPageContext.ShellPage):
41+
case nameof(IContentPageContext.IsMultiPaneActive):
42+
OnPropertyChanged(nameof(IsExecutable));
43+
break;
44+
}
45+
}
46+
}
47+
}

src/Files.App/Data/Commands/Manager/CommandCodes.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,8 @@ public enum CommandCodes
190190
CloseSelectedTab,
191191
OpenNewPane,
192192
ClosePane,
193+
FocusLeftPane,
194+
FocusRightPane,
193195

194196
// Play
195197
PlayAll,

src/Files.App/Data/Commands/Manager/CommandManager.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ public IRichCommand this[HotKey hotKey]
185185
public IRichCommand CloseSelectedTab => commands[CommandCodes.CloseSelectedTab];
186186
public IRichCommand OpenNewPane => commands[CommandCodes.OpenNewPane];
187187
public IRichCommand ClosePane => commands[CommandCodes.ClosePane];
188+
public IRichCommand FocusLeftPane => commands[CommandCodes.FocusLeftPane];
189+
public IRichCommand FocusRightPane => commands[CommandCodes.FocusRightPane];
188190
public IRichCommand OpenFileLocation => commands[CommandCodes.OpenFileLocation];
189191
public IRichCommand PlayAll => commands[CommandCodes.PlayAll];
190192
public IRichCommand GitFetch => commands[CommandCodes.GitFetch];
@@ -360,6 +362,8 @@ public IEnumerator<IRichCommand> GetEnumerator() =>
360362
[CommandCodes.CloseSelectedTab] = new CloseSelectedTabAction(),
361363
[CommandCodes.OpenNewPane] = new OpenNewPaneAction(),
362364
[CommandCodes.ClosePane] = new ClosePaneAction(),
365+
[CommandCodes.FocusLeftPane] = new FocusLeftPaneAction(),
366+
[CommandCodes.FocusRightPane] = new FocusRightPaneAction(),
363367
[CommandCodes.OpenFileLocation] = new OpenFileLocationAction(),
364368
[CommandCodes.PlayAll] = new PlayAllAction(),
365369
[CommandCodes.GitFetch] = new GitFetchAction(),

src/Files.App/Data/Commands/Manager/ICommandManager.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ public interface ICommandManager : IEnumerable<IRichCommand>
175175
IRichCommand CloseSelectedTab { get; }
176176
IRichCommand OpenNewPane { get; }
177177
IRichCommand ClosePane { get; }
178+
IRichCommand FocusLeftPane { get; }
179+
IRichCommand FocusRightPane { get; }
178180

179181
IRichCommand PlayAll { get; }
180182

src/Files.App/Data/Contracts/IPanesPage.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ public interface IPanesPage : IDisposable, INotifyPropertyChanged
1818

1919
public void CloseActivePane();
2020

21+
public void FocusLeftPane();
22+
23+
public void FocusRightPane();
24+
2125
public bool IsLeftPaneActive { get; }
2226

2327
public bool IsRightPaneActive { get; }

src/Files.App/Strings/en-US/Resources.resw

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2678,6 +2678,18 @@
26782678
<data name="ClosePaneDescription" xml:space="preserve">
26792679
<value>Close right pane</value>
26802680
</data>
2681+
<data name="FocusLeftPane" xml:space="preserve">
2682+
<value>Focus left pane</value>
2683+
</data>
2684+
<data name="FocusLeftPaneDescription" xml:space="preserve">
2685+
<value>Switch focus to the left pane</value>
2686+
</data>
2687+
<data name="FocusRightPane" xml:space="preserve">
2688+
<value>Focus right pane</value>
2689+
</data>
2690+
<data name="FocusRightPaneDescription" xml:space="preserve">
2691+
<value>Switch focus to the right pane</value>
2692+
</data>
26812693
<data name="ToggleSidebar" xml:space="preserve">
26822694
<value>Toggle the sidebar</value>
26832695
</data>

src/Files.App/Views/PaneHolderPage.xaml

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,6 @@
2525
</ResourceDictionary>
2626
</Page.Resources>
2727

28-
<Page.KeyboardAccelerators>
29-
<KeyboardAccelerator
30-
Key="Left"
31-
Invoked="KeyboardAccelerator_Invoked"
32-
Modifiers="Control,Shift" />
33-
<KeyboardAccelerator
34-
Key="Right"
35-
Invoked="KeyboardAccelerator_Invoked"
36-
Modifiers="Control,Shift" />
37-
</Page.KeyboardAccelerators>
38-
3928
<Grid x:Name="RootGrid">
4029
<Grid.ColumnDefinitions>
4130
<ColumnDefinition

src/Files.App/Views/PaneHolderPage.xaml.cs

Lines changed: 34 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ public IShellPage? ActivePane
157157
NotifyPropertyChanged(nameof(IsRightPaneActive));
158158
NotifyPropertyChanged(nameof(ActivePaneOrColumn));
159159
NotifyPropertyChanged(nameof(FilesystemHelpers));
160+
161+
SetShadow();
160162
}
161163
}
162164
}
@@ -243,9 +245,21 @@ public void CloseActivePane()
243245
{
244246
// NOTE: Can only close right pane at the moment
245247
IsRightPaneVisible = false;
248+
249+
PaneLeft.Focus(FocusState.Programmatic);
250+
SetShadow();
251+
}
252+
253+
public void FocusLeftPane()
254+
{
246255
PaneLeft.Focus(FocusState.Programmatic);
247256
}
248257

258+
public void FocusRightPane()
259+
{
260+
PaneRight.Focus(FocusState.Programmatic);
261+
}
262+
249263
// Override methods
250264

251265
protected override void OnNavigatedTo(NavigationEventArgs eventArgs)
@@ -305,30 +319,6 @@ private void MainWindow_SizeChanged(object sender, WindowSizeChangedEventArgs e)
305319
WindowIsCompact = MainWindow.Instance.Bounds.Width <= Constants.UI.MultiplePaneWidthThreshold;
306320
}
307321

308-
private void KeyboardAccelerator_Invoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
309-
{
310-
args.Handled = true;
311-
var ctrl = args.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Control);
312-
var shift = args.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Shift);
313-
var menu = args.KeyboardAccelerator.Modifiers.HasFlag(VirtualKeyModifiers.Menu);
314-
315-
switch (c: ctrl, s: shift, m: menu, k: args.KeyboardAccelerator.Key)
316-
{
317-
case (true, true, false, VirtualKey.Left): // ctrl + shift + "<-" select left pane
318-
ActivePane = PaneLeft;
319-
break;
320-
321-
case (true, true, false, VirtualKey.Right): // ctrl + shift + "->" select right pane
322-
if (string.IsNullOrEmpty(NavParamsRight?.NavPath))
323-
{
324-
NavParamsRight = new NavigationParams { NavPath = "Home" };
325-
}
326-
IsRightPaneVisible = true;
327-
ActivePane = PaneRight;
328-
break;
329-
}
330-
}
331-
332322
private void Pane_ContentChanged(object sender, TabBarItemParameter e)
333323
{
334324
TabBarItemParameter = new()
@@ -346,8 +336,6 @@ private void Pane_Loaded(object sender, RoutedEventArgs e)
346336
{
347337
((UIElement)sender).GotFocus += Pane_GotFocus;
348338
((UIElement)sender).RightTapped += Pane_RightTapped;
349-
350-
PaneLeft.RootGrid.Translation = new System.Numerics.Vector3(0, 0, 8);
351339
}
352340

353341
private void Pane_GotFocus(object sender, RoutedEventArgs e)
@@ -369,22 +357,30 @@ private void Pane_GotFocus(object sender, RoutedEventArgs e)
369357
var activePane = isLeftPane ? PaneLeft : PaneRight;
370358
if (ActivePane != activePane)
371359
ActivePane = activePane;
360+
}
372361

373-
// Add theme shadow to the active pane
374-
if (isLeftPane)
362+
private void SetShadow()
363+
{
364+
if (IsMultiPaneActive)
375365
{
376-
if (PaneRight is not null)
377-
PaneRight.RootGrid.Translation = new System.Numerics.Vector3(0, 0, 0);
378-
if (PaneLeft is not null)
379-
PaneLeft.RootGrid.Translation = new System.Numerics.Vector3(0, 0, 8);
366+
// Add theme shadow to the active pane
367+
if (IsLeftPaneActive)
368+
{
369+
if (PaneRight is not null)
370+
PaneRight.RootGrid.Translation = new System.Numerics.Vector3(0, 0, 0);
371+
if (PaneLeft is not null)
372+
PaneLeft.RootGrid.Translation = new System.Numerics.Vector3(0, 0, 32);
373+
}
374+
else
375+
{
376+
if (PaneRight is not null)
377+
PaneRight.RootGrid.Translation = new System.Numerics.Vector3(0, 0, 32);
378+
if (PaneLeft is not null)
379+
PaneLeft.RootGrid.Translation = new System.Numerics.Vector3(0, 0, 0);
380+
}
380381
}
381382
else
382-
{
383-
if (PaneRight is not null)
384-
PaneRight.RootGrid.Translation = new System.Numerics.Vector3(0, 0, 8);
385-
if (PaneLeft is not null)
386-
PaneLeft.RootGrid.Translation = new System.Numerics.Vector3(0, 0, 0);
387-
}
383+
PaneLeft.RootGrid.Translation = new System.Numerics.Vector3(0, 0, 8);
388384
}
389385

390386
private void Pane_RightTapped(object sender, RoutedEventArgs e)

0 commit comments

Comments
 (0)