179 lines
4.4 KiB
C#
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;
|
|
}
|
|
}
|