port from perforce

This commit is contained in:
2026-04-18 22:31:51 +02:00
commit 8d0ab5b7cc
8409 changed files with 3972376 additions and 0 deletions

View File

@@ -0,0 +1,134 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using DynamicData;
using NodeNetwork.Utilities;
using ReactiveUI;
namespace NodeNetwork.Toolkit.ContextMenu
{
public partial class SearchableContextMenuView : IViewFor<SearchableContextMenuViewModel>
{
#region ViewModel
public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(nameof(ViewModel),
typeof(SearchableContextMenuViewModel), typeof(SearchableContextMenuView), new PropertyMetadata(null));
public SearchableContextMenuViewModel ViewModel
{
get => (SearchableContextMenuViewModel)GetValue(ViewModelProperty);
set => SetValue(ViewModelProperty, value);
}
object IViewFor.ViewModel
{
get => ViewModel;
set => ViewModel = (SearchableContextMenuViewModel)value;
}
#endregion
#region ChildrenBelowSearch
public static readonly DependencyProperty ChildrenBelowSearchProperty =
DependencyProperty.Register(nameof(ChildrenBelowSearch), typeof(IEnumerable), typeof(SearchableContextMenuView), new PropertyMetadata(new object[0]));
public IEnumerable ChildrenBelowSearch
{
get => (IEnumerable)GetValue(ChildrenBelowSearchProperty);
set => SetValue(ChildrenBelowSearchProperty, value);
}
#endregion
#region ReferencePointElement
public static readonly DependencyProperty ReferencePointElementProperty =
DependencyProperty.Register(nameof(ReferencePointElement), typeof(IInputElement), typeof(SearchableContextMenuView), new PropertyMetadata(null));
public IInputElement ReferencePointElement
{
get => (IInputElement)GetValue(ReferencePointElementProperty);
set => SetValue(ReferencePointElementProperty, value);
}
#endregion
#region OpenPoint
public static readonly DependencyProperty OpenPointProperty =
DependencyProperty.Register(nameof(OpenPoint), typeof(Point), typeof(SearchableContextMenuView), new PropertyMetadata(new Point()));
public Point OpenPoint
{
get => (Point)GetValue(OpenPointProperty);
private set => SetValue(OpenPointProperty, value);
}
#endregion
public SearchableContextMenuView()
{
InitializeComponent();
this.Bind(ViewModel, vm => vm.SearchQuery, v => v.SearchTextBox.Text);
this.BindList(ViewModel, vm => vm.VisibleCommands, v => v.CollectionContainer.Collection);
Binding myBinding = new Binding(nameof(ChildrenBelowSearch)) { Source = this };
BindingOperations.SetBinding(ContainerBelowSearch, CollectionContainer.CollectionProperty, myBinding);
this.Opened += (sender, args) =>
{
SearchTextBox.Focus();
if (ReferencePointElement != null)
{
OpenPoint = Mouse.GetPosition(ReferencePointElement);
}
};
// This var is needed to ensure both key down and key up of arrow keys happened in the textbox,
// otherwise moving into the textbox will immediately move out again.
bool arrowWasPressedInTextBox = false;
this.SearchTextBox.PreviewKeyDown += (sender, args) =>
{
if (args.Key == Key.Enter || args.Key == Key.Return)
{
if (ViewModel.VisibleCommands.Count > 0)
{
var firstEntry = ViewModel.VisibleCommands.Items.First();
firstEntry.Command.Execute(firstEntry.CommandParameter);
this.IsOpen = false;
}
}
else if (args.Key == Key.Escape && SearchTextBox.Text.Length > 0)
{
SearchTextBox.Text = "";
args.Handled = true;
}
else if (args.Key == Key.Up || args.Key == Key.Down)
{
arrowWasPressedInTextBox = true;
}
};
this.SearchTextBox.PreviewKeyUp += (sender, args) =>
{
if (arrowWasPressedInTextBox && (args.Key == Key.Up || args.Key == Key.Down))
{
arrowWasPressedInTextBox = false;
var dir = args.Key == Key.Up ? FocusNavigationDirection.Previous : FocusNavigationDirection.Next;
var traversalRequest = new TraversalRequest(dir);
var focusedElem = Keyboard.FocusedElement as FrameworkElement;
focusedElem?.MoveFocus(traversalRequest);
}
};
this.SearchMenuItem.GotKeyboardFocus += (sender, args) => { SearchTextBox.Focus(); };
}
}
}