Files
Explorer-Workbench/src/Explorer.App/ExplorerAddressBar.xaml.cs

179 lines
4.4 KiB
C#

using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using Explorer.Presentation.ViewModels;
namespace Explorer.App;
public partial class ExplorerAddressBar : UserControl
{
private bool _suppressLostFocus;
public ExplorerAddressBar()
{
InitializeComponent();
DataContextChanged += OnDataContextChanged;
IsVisibleChanged += (_, _) =>
{
if (IsVisible && DataContext is ExplorerPaneViewModel { IsEditingPath: true })
{
FocusEditor();
}
};
}
public void FocusEditor()
{
Dispatcher.BeginInvoke(() =>
{
PathCombo.ApplyTemplate();
if (PathCombo.Template.FindName("PART_EditableTextBox", PathCombo) is TextBox box)
{
box.Focus();
box.SelectAll();
}
else
{
PathCombo.Focus();
}
}, DispatcherPriority.Loaded);
}
private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if (e.OldValue is ExplorerPaneViewModel previous)
{
previous.PropertyChanged -= OnPanePropertyChanged;
}
if (e.NewValue is ExplorerPaneViewModel pane)
{
pane.PropertyChanged += OnPanePropertyChanged;
if (pane.IsEditingPath)
{
FocusEditor();
}
}
}
private void OnPanePropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(ExplorerPaneViewModel.IsEditingPath)
&& sender is ExplorerPaneViewModel { IsEditingPath: true })
{
FocusEditor();
}
}
private void OnBreadcrumbMouseDown(object sender, MouseButtonEventArgs e)
{
if (e.OriginalSource is DependencyObject origin && IsInsideButton(origin))
{
return;
}
if (DataContext is not ExplorerPaneViewModel pane)
{
return;
}
pane.BeginEditPath();
e.Handled = true;
}
private void OnPathKeyDown(object sender, KeyEventArgs e)
{
if (DataContext is not ExplorerPaneViewModel pane)
{
return;
}
if (e.Key == Key.Enter)
{
CommitPath();
e.Handled = true;
return;
}
if (e.Key == Key.Escape)
{
_suppressLostFocus = true;
pane.CancelEditPath();
e.Handled = true;
}
}
private void OnPathHistorySelected(object sender, SelectionChangedEventArgs e)
{
if (sender is not ComboBox combo || e.AddedItems.Count == 0 || e.AddedItems[0] is not string path)
{
return;
}
if (DataContext is not ExplorerPaneViewModel pane)
{
return;
}
if (NavigationTreeViewModel.PathsEqual(path, pane.CurrentPath))
{
return;
}
if (combo.IsDropDownOpen || combo.IsKeyboardFocusWithin)
{
pane.PathEditText = path;
CommitPath();
}
}
private void OnPathLostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
Dispatcher.BeginInvoke(() =>
{
if (_suppressLostFocus)
{
_suppressLostFocus = false;
return;
}
if (PathCombo.IsDropDownOpen || PathCombo.IsKeyboardFocusWithin)
{
return;
}
if (DataContext is ExplorerPaneViewModel pane)
{
pane.CancelEditPath();
}
}, DispatcherPriority.Input);
}
private void CommitPath()
{
if (Window.GetWindow(this)?.DataContext is MainViewModel vm)
{
vm.GoCommand.Execute(null);
}
}
private static bool IsInsideButton(DependencyObject origin)
{
for (var current = origin; current is not null;)
{
if (current is Button)
{
return true;
}
current = current is Visual
? VisualTreeHelper.GetParent(current)
: LogicalTreeHelper.GetParent(current);
}
return false;
}
}