first commit
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
internal class ListBoxBehavior
|
||||
{
|
||||
private static readonly Dictionary<ListBox, Capture> Associations = new Dictionary<ListBox, Capture>();
|
||||
|
||||
public static readonly DependencyProperty ScrollOnNewItemProperty =
|
||||
DependencyProperty.RegisterAttached( "ScrollOnNewItem", typeof( bool ), typeof( ListBoxBehavior ),
|
||||
new UIPropertyMetadata( false, OnScrollOnNewItemChanged ) );
|
||||
|
||||
public static bool GetScrollOnNewItem( DependencyObject obj )
|
||||
{
|
||||
return (bool) obj.GetValue( ScrollOnNewItemProperty );
|
||||
}
|
||||
|
||||
public static void SetScrollOnNewItem( DependencyObject obj, bool value )
|
||||
{
|
||||
obj.SetValue( ScrollOnNewItemProperty, value );
|
||||
}
|
||||
|
||||
public static void OnScrollOnNewItemChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
|
||||
{
|
||||
ListBox listBox = d as ListBox;
|
||||
|
||||
if ( listBox == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool oldValue = (bool) e.OldValue, newValue = (bool) e.NewValue;
|
||||
|
||||
if ( newValue == oldValue )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( newValue )
|
||||
{
|
||||
listBox.Loaded += ListBox_Loaded;
|
||||
listBox.Unloaded += ListBox_Unloaded;
|
||||
PropertyDescriptor itemsSourcePropertyDescriptor =
|
||||
TypeDescriptor.GetProperties( listBox )["ItemsSource"];
|
||||
itemsSourcePropertyDescriptor.AddValueChanged( listBox, ListBox_ItemsSourceChanged );
|
||||
}
|
||||
else
|
||||
{
|
||||
listBox.Loaded -= ListBox_Loaded;
|
||||
listBox.Unloaded -= ListBox_Unloaded;
|
||||
|
||||
if ( Associations.ContainsKey( listBox ) )
|
||||
{
|
||||
Associations[listBox].Dispose();
|
||||
}
|
||||
|
||||
PropertyDescriptor itemsSourcePropertyDescriptor =
|
||||
TypeDescriptor.GetProperties( listBox )["ItemsSource"];
|
||||
itemsSourcePropertyDescriptor.RemoveValueChanged( listBox, ListBox_ItemsSourceChanged );
|
||||
}
|
||||
}
|
||||
|
||||
private static void ListBox_ItemsSourceChanged( object sender, EventArgs e )
|
||||
{
|
||||
ListBox listBox = (ListBox) sender;
|
||||
|
||||
if ( Associations.ContainsKey( listBox ) )
|
||||
{
|
||||
Associations[listBox].Dispose();
|
||||
}
|
||||
|
||||
Associations[listBox] = new Capture( listBox );
|
||||
}
|
||||
|
||||
private static void ListBox_Unloaded( object sender, RoutedEventArgs e )
|
||||
{
|
||||
ListBox listBox = (ListBox) sender;
|
||||
|
||||
if ( Associations.ContainsKey( listBox ) )
|
||||
{
|
||||
Associations[listBox].Dispose();
|
||||
}
|
||||
|
||||
listBox.Unloaded -= ListBox_Unloaded;
|
||||
}
|
||||
|
||||
private static void ListBox_Loaded( object sender, RoutedEventArgs e )
|
||||
{
|
||||
ListBox listBox = (ListBox) sender;
|
||||
|
||||
listBox.Loaded -= ListBox_Loaded;
|
||||
Associations[listBox] = new Capture( listBox );
|
||||
}
|
||||
|
||||
private class Capture : IDisposable
|
||||
{
|
||||
private readonly INotifyCollectionChanged incc;
|
||||
private readonly ListBox listBox;
|
||||
|
||||
public Capture( ListBox listBox )
|
||||
{
|
||||
this.listBox = listBox;
|
||||
incc = listBox.ItemsSource as INotifyCollectionChanged;
|
||||
|
||||
if ( incc != null )
|
||||
{
|
||||
incc.CollectionChanged += incc_CollectionChanged;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if ( incc != null )
|
||||
{
|
||||
incc.CollectionChanged -= incc_CollectionChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void incc_CollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
|
||||
{
|
||||
if ( e.Action == NotifyCollectionChangedAction.Add )
|
||||
{
|
||||
listBox.ScrollIntoView( e.NewItems[0] );
|
||||
listBox.SelectedItem = e.NewItems[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class AutoScrollBehavior
|
||||
{
|
||||
public static readonly DependencyProperty AutoScrollProperty =
|
||||
DependencyProperty.RegisterAttached( "AutoScroll", typeof( bool ), typeof( AutoScrollBehavior ),
|
||||
new PropertyMetadata( false, AutoScrollPropertyChanged ) );
|
||||
|
||||
public static void AutoScrollPropertyChanged( DependencyObject obj, DependencyPropertyChangedEventArgs args )
|
||||
{
|
||||
ScrollViewer scrollViewer = obj as ScrollViewer;
|
||||
|
||||
if ( scrollViewer != null && (bool) args.NewValue )
|
||||
{
|
||||
scrollViewer.ScrollChanged += ScrollViewer_ScrollChanged;
|
||||
scrollViewer.ScrollToEnd();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( scrollViewer != null )
|
||||
{
|
||||
scrollViewer.ScrollChanged -= ScrollViewer_ScrollChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ScrollViewer_ScrollChanged( object sender, ScrollChangedEventArgs e )
|
||||
{
|
||||
// Only scroll to bottom when the extent changed. Otherwise you can't scroll up
|
||||
if ( e.ExtentHeightChange != 0 )
|
||||
{
|
||||
ScrollViewer scrollViewer = sender as ScrollViewer;
|
||||
scrollViewer?.ScrollToBottom();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool GetAutoScroll( DependencyObject obj )
|
||||
{
|
||||
return (bool) obj.GetValue( AutoScrollProperty );
|
||||
}
|
||||
|
||||
public static void SetAutoScroll( DependencyObject obj, bool value )
|
||||
{
|
||||
obj.SetValue( AutoScrollProperty, value );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Interactivity;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
public class AutoScrollTextBoxBehaviour : Behavior<TextBox>
|
||||
{
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
AssociatedObject.TextChanged += OnTextChanged;
|
||||
}
|
||||
|
||||
private void OnTextChanged( object sender, TextChangedEventArgs e )
|
||||
{
|
||||
AssociatedObject.ScrollToEnd();
|
||||
}
|
||||
|
||||
protected override void OnDetaching()
|
||||
{
|
||||
base.OnDetaching();
|
||||
|
||||
if ( AssociatedObject != null )
|
||||
{
|
||||
AssociatedObject.TextChanged -= OnTextChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Interactivity;
|
||||
using ICSharpCode.AvalonEdit;
|
||||
using ICSharpCode.AvalonEdit.Document;
|
||||
using ICSharpCode.AvalonEdit.Editing;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
public class AvalonBindingBehaviour : Behavior<TextEditor>
|
||||
{
|
||||
public static readonly DependencyProperty DocumentBindingProperty = DependencyProperty.Register(
|
||||
"DocumentBinding", typeof( TextDocument ), typeof( AvalonBindingBehaviour ),
|
||||
new FrameworkPropertyMetadata( default( TextDocument ),
|
||||
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, PropertyChangedCallback ) );
|
||||
|
||||
public static readonly DependencyProperty CaretBindingProperty = DependencyProperty.Register( "CaretBinding",
|
||||
typeof( int ), typeof( AvalonBindingBehaviour ),
|
||||
new FrameworkPropertyMetadata( default( int ), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
|
||||
PropertyChangedCallback ) );
|
||||
|
||||
public int CaretBinding
|
||||
{
|
||||
get => (int) GetValue( CaretBindingProperty );
|
||||
set => SetValue( CaretBindingProperty, value );
|
||||
}
|
||||
|
||||
public TextDocument DocumentBinding
|
||||
{
|
||||
get => (TextDocument) GetValue( DocumentBindingProperty );
|
||||
set => SetValue( DocumentBindingProperty, value );
|
||||
}
|
||||
|
||||
private static void PropertyChangedCallback( DependencyObject d, DependencyPropertyChangedEventArgs e )
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
AssociatedObject.Loaded += OnLoaded;
|
||||
AssociatedObject.TextArea.Caret.PositionChanged += CaretOnPositionChanged;
|
||||
}
|
||||
|
||||
protected override void OnDetaching()
|
||||
{
|
||||
base.OnDetaching();
|
||||
|
||||
AssociatedObject.Loaded -= OnLoaded;
|
||||
AssociatedObject.TextArea.Caret.PositionChanged -= CaretOnPositionChanged;
|
||||
}
|
||||
|
||||
private void CaretOnPositionChanged( object sender, EventArgs e )
|
||||
{
|
||||
if ( sender is Caret caret )
|
||||
{
|
||||
CaretBinding = caret.Offset;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLoaded( object sender, RoutedEventArgs args )
|
||||
{
|
||||
if ( sender is TextEditor textEditor )
|
||||
{
|
||||
DocumentBinding = textEditor.Document;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Interactivity;
|
||||
using ICSharpCode.AvalonEdit;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
public sealed class AvalonEditBehaviour : Behavior<TextEditor>
|
||||
{
|
||||
public static readonly DependencyProperty TextBindingProperty = DependencyProperty.Register( "TextBinding",
|
||||
typeof( string ), typeof( AvalonEditBehaviour ),
|
||||
new FrameworkPropertyMetadata( default( string ), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
|
||||
PropertyChangedCallback ) );
|
||||
|
||||
public string TextBinding
|
||||
{
|
||||
get => (string) GetValue( TextBindingProperty );
|
||||
set => SetValue( TextBindingProperty, value );
|
||||
}
|
||||
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
if ( AssociatedObject != null )
|
||||
{
|
||||
AssociatedObject.TextChanged += AssociatedObjectOnTextChanged;
|
||||
AssociatedObject.LostFocus += AssociatedObjectOnLostFocus;
|
||||
}
|
||||
}
|
||||
|
||||
private void AssociatedObjectOnLostFocus( object sender, RoutedEventArgs routedEventArgs )
|
||||
{
|
||||
if ( !( sender is TextEditor textEditor ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( textEditor.Document != null )
|
||||
{
|
||||
TextBinding = textEditor.Document.Text;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDetaching()
|
||||
{
|
||||
base.OnDetaching();
|
||||
|
||||
if ( AssociatedObject != null )
|
||||
{
|
||||
AssociatedObject.TextChanged -= AssociatedObjectOnTextChanged;
|
||||
AssociatedObject.LostFocus -= AssociatedObjectOnLostFocus;
|
||||
}
|
||||
}
|
||||
|
||||
private void AssociatedObjectOnTextChanged( object sender, EventArgs eventArgs )
|
||||
{
|
||||
if ( !( sender is TextEditor textEditor ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( textEditor.Document == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int carot = textEditor.CaretOffset;
|
||||
TextBinding = textEditor.Document.Text;
|
||||
textEditor.CaretOffset = carot;
|
||||
}
|
||||
|
||||
private static void PropertyChangedCallback( DependencyObject dependencyObject,
|
||||
DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs )
|
||||
{
|
||||
AvalonEditBehaviour behavior = dependencyObject as AvalonEditBehaviour;
|
||||
|
||||
TextEditor editor = behavior?.AssociatedObject;
|
||||
|
||||
if ( editor?.Document == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( dependencyPropertyChangedEventArgs.NewValue == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
editor.Document.Text = dependencyPropertyChangedEventArgs.NewValue.ToString();
|
||||
editor.CaretOffset = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Interactivity;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
public class BindableSelectedItemBehavior : Behavior<TreeView>
|
||||
{
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
AssociatedObject.SelectedItemChanged += OnTreeViewSelectedItemChanged;
|
||||
}
|
||||
|
||||
protected override void OnDetaching()
|
||||
{
|
||||
base.OnDetaching();
|
||||
|
||||
if ( AssociatedObject != null )
|
||||
{
|
||||
AssociatedObject.SelectedItemChanged -= OnTreeViewSelectedItemChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnTreeViewSelectedItemChanged( object sender, RoutedPropertyChangedEventArgs<object> e )
|
||||
{
|
||||
SelectedItem = e.NewValue;
|
||||
}
|
||||
|
||||
#region SelectedItem Property
|
||||
|
||||
public object SelectedItem
|
||||
{
|
||||
get => GetValue( SelectedItemProperty );
|
||||
set => SetValue( SelectedItemProperty, value );
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SelectedItemProperty = DependencyProperty.Register( "SelectedItem",
|
||||
typeof( object ), typeof( BindableSelectedItemBehavior ),
|
||||
new UIPropertyMetadata( null, OnSelectedItemChanged ) );
|
||||
|
||||
private static void OnSelectedItemChanged( DependencyObject sender, DependencyPropertyChangedEventArgs e )
|
||||
{
|
||||
if ( e.NewValue is TreeViewItem item )
|
||||
{
|
||||
item.SetValue( TreeViewItem.IsSelectedProperty, true );
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace ClassicAssist.Misc
|
||||
{
|
||||
public class BindingProxy : Freezable
|
||||
{
|
||||
// Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...
|
||||
public static readonly DependencyProperty DataProperty = DependencyProperty.Register( "Data", typeof( object ),
|
||||
typeof( BindingProxy ), new UIPropertyMetadata( null ) );
|
||||
|
||||
public object Data
|
||||
{
|
||||
get => GetValue( DataProperty );
|
||||
set => SetValue( DataProperty, value );
|
||||
}
|
||||
|
||||
#region Overrides of Freezable
|
||||
|
||||
protected override Freezable CreateInstanceCore()
|
||||
{
|
||||
return new BindingProxy();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
|
||||
//https://stackoverflow.com/questions/4305565/wpf-context-menu-on-left-click
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
public class ClickOpensContextMenuBehaviour
|
||||
{
|
||||
private static readonly DependencyProperty ClickOpensContextMenuProperty =
|
||||
DependencyProperty.RegisterAttached( "Enabled", typeof( bool ), typeof( ClickOpensContextMenuBehaviour ),
|
||||
new PropertyMetadata( HandlePropertyChanged ) );
|
||||
|
||||
public static bool GetEnabled( DependencyObject obj )
|
||||
{
|
||||
return (bool) obj.GetValue( ClickOpensContextMenuProperty );
|
||||
}
|
||||
|
||||
public static void SetEnabled( DependencyObject obj, bool value )
|
||||
{
|
||||
obj.SetValue( ClickOpensContextMenuProperty, value );
|
||||
}
|
||||
|
||||
private static void HandlePropertyChanged( DependencyObject obj, DependencyPropertyChangedEventArgs args )
|
||||
{
|
||||
switch ( obj )
|
||||
{
|
||||
case Image image:
|
||||
image.MouseLeftButtonDown -= ExecuteMouseDown;
|
||||
image.MouseLeftButtonDown += ExecuteMouseDown;
|
||||
break;
|
||||
case Hyperlink hyperlink:
|
||||
hyperlink.Click -= ExecuteClick;
|
||||
hyperlink.Click += ExecuteClick;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ExecuteMouseDown( object sender, MouseButtonEventArgs args )
|
||||
{
|
||||
if ( !( sender is DependencyObject obj ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool enabled = (bool) obj.GetValue( ClickOpensContextMenuProperty );
|
||||
|
||||
if ( !enabled )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Image image = sender as Image;
|
||||
|
||||
if ( image?.ContextMenu != null )
|
||||
{
|
||||
image.ContextMenu.IsOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static void ExecuteClick( object sender, RoutedEventArgs args )
|
||||
{
|
||||
if ( !( sender is DependencyObject obj ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bool enabled = (bool) obj.GetValue( ClickOpensContextMenuProperty );
|
||||
|
||||
if ( !enabled )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !( sender is Hyperlink hyperlink ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( hyperlink.ContextMenu != null )
|
||||
{
|
||||
hyperlink.ContextMenu.IsOpen = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interactivity;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
public class ClipboardBehaviour : Behavior<UIElement>
|
||||
{
|
||||
public static readonly DependencyProperty CopyCommandProperty = DependencyProperty.Register( "CopyCommand",
|
||||
typeof( ICommand ), typeof( ClipboardBehaviour ),
|
||||
new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.None ) );
|
||||
|
||||
public static readonly DependencyProperty PasteCommandProperty = DependencyProperty.Register( "PasteCommand",
|
||||
typeof( ICommand ), typeof( ClipboardBehaviour ),
|
||||
new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.None ) );
|
||||
|
||||
public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register(
|
||||
"CommandParameter", typeof( object ), typeof( ClipboardBehaviour ),
|
||||
new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.None ) );
|
||||
|
||||
public object CommandParameter
|
||||
{
|
||||
get => GetValue( CommandParameterProperty );
|
||||
set => SetValue( CommandParameterProperty, value );
|
||||
}
|
||||
|
||||
public ICommand CopyCommand
|
||||
{
|
||||
get => (ICommand) GetValue( CopyCommandProperty );
|
||||
set => SetValue( CopyCommandProperty, value );
|
||||
}
|
||||
|
||||
public ICommand PasteCommand
|
||||
{
|
||||
get => (ICommand) GetValue( PasteCommandProperty );
|
||||
set => SetValue( PasteCommandProperty, value );
|
||||
}
|
||||
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
CommandBinding CopyCommandBinding = new CommandBinding(
|
||||
ApplicationCommands.Copy, CopyCommandExecuted, CopyCommandCanExecute );
|
||||
AssociatedObject.CommandBindings.Add( CopyCommandBinding );
|
||||
|
||||
CommandBinding CutCommandBinding = new CommandBinding(
|
||||
ApplicationCommands.Cut, CutCommandExecuted, CutCommandCanExecute );
|
||||
AssociatedObject.CommandBindings.Add( CutCommandBinding );
|
||||
|
||||
CommandBinding PasteCommandBinding = new CommandBinding( ApplicationCommands.Paste, PasteCommandExecuted,
|
||||
PasteCommandCanExecute );
|
||||
AssociatedObject.CommandBindings.Add( PasteCommandBinding );
|
||||
}
|
||||
|
||||
private void CopyCommandExecuted( object target, ExecutedRoutedEventArgs e )
|
||||
{
|
||||
CopyCommand?.Execute( CommandParameter );
|
||||
}
|
||||
|
||||
private void CopyCommandCanExecute( object target, CanExecuteRoutedEventArgs e )
|
||||
{
|
||||
e.CanExecute = true;
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private void CutCommandExecuted( object target, ExecutedRoutedEventArgs e )
|
||||
{
|
||||
}
|
||||
|
||||
private void CutCommandCanExecute( object target, CanExecuteRoutedEventArgs e )
|
||||
{
|
||||
}
|
||||
|
||||
private void PasteCommandExecuted( object target, ExecutedRoutedEventArgs e )
|
||||
{
|
||||
PasteCommand?.Execute( CommandParameter );
|
||||
}
|
||||
|
||||
private void PasteCommandCanExecute( object target, CanExecuteRoutedEventArgs e )
|
||||
{
|
||||
e.CanExecute = true;
|
||||
e.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Interactivity;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
public class CloseOnClickBehaviour : Behavior<Button>
|
||||
{
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
AssociatedObject.Click += OnClick;
|
||||
}
|
||||
|
||||
protected override void OnDetaching()
|
||||
{
|
||||
AssociatedObject.Click -= OnClick;
|
||||
}
|
||||
|
||||
private void OnClick( object sender, RoutedEventArgs e )
|
||||
{
|
||||
if ( !( sender is Button button ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Window window = Window.GetWindow( button );
|
||||
|
||||
window?.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interactivity;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
public class ComboBoxBehavior : Behavior<ComboBox>
|
||||
{
|
||||
public static readonly DependencyProperty CommandBindingProperty =
|
||||
DependencyProperty.Register( "CommandBinding", typeof( ICommand ), typeof( ComboBoxBehavior ),
|
||||
new FrameworkPropertyMetadata( default( ICommand ), FrameworkPropertyMetadataOptions.None,
|
||||
PropertyChangedCallback ) );
|
||||
|
||||
public static readonly DependencyProperty CommandParameterProperty =
|
||||
DependencyProperty.Register( "CommandParameter", typeof( object ), typeof( ComboBoxBehavior ),
|
||||
new FrameworkPropertyMetadata( default, FrameworkPropertyMetadataOptions.None,
|
||||
PropertyChangedCallback ) );
|
||||
|
||||
public static readonly DependencyProperty OnlyUserTriggeredProperty =
|
||||
DependencyProperty.Register( "OnlyUserTriggered", typeof( bool ), typeof( ComboBoxBehavior ),
|
||||
new FrameworkPropertyMetadata( false, FrameworkPropertyMetadataOptions.None,
|
||||
PropertyChangedCallback ) );
|
||||
|
||||
private bool _userTriggered;
|
||||
|
||||
public ICommand CommandBinding
|
||||
{
|
||||
get => (ICommand) GetValue( CommandBindingProperty );
|
||||
set => SetValue( CommandBindingProperty, value );
|
||||
}
|
||||
|
||||
public object CommandParameter
|
||||
{
|
||||
get => GetValue( CommandParameterProperty );
|
||||
set => SetValue( CommandParameterProperty, value );
|
||||
}
|
||||
|
||||
public bool OnlyUserTriggered
|
||||
{
|
||||
get => (bool) GetValue( OnlyUserTriggeredProperty );
|
||||
set => SetValue( OnlyUserTriggeredProperty, value );
|
||||
}
|
||||
|
||||
private static void PropertyChangedCallback( DependencyObject d, DependencyPropertyChangedEventArgs e )
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
AssociatedObject.SelectionChanged += OnSelectionChanged;
|
||||
AssociatedObject.PreviewMouseDown += OnPreviewMouseDown;
|
||||
}
|
||||
|
||||
private void OnPreviewMouseDown( object sender, MouseButtonEventArgs e )
|
||||
{
|
||||
_userTriggered = true;
|
||||
}
|
||||
|
||||
private void OnSelectionChanged( object sender, SelectionChangedEventArgs e )
|
||||
{
|
||||
if ( OnlyUserTriggered && !_userTriggered )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
CommandBinding?.Execute( AssociatedObject.SelectedItem );
|
||||
_userTriggered = false;
|
||||
}
|
||||
|
||||
protected override void OnDetaching()
|
||||
{
|
||||
AssociatedObject.SelectionChanged -= OnSelectionChanged;
|
||||
AssociatedObject.PreviewMouseDown -= OnPreviewMouseDown;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Windows.Markup;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
/*
|
||||
* https://brianlagunas.com/a-better-way-to-data-bind-enums-in-wpf/
|
||||
*/
|
||||
public class EnumBindingSourceExtension : MarkupExtension
|
||||
{
|
||||
private Type _enumType;
|
||||
|
||||
public EnumBindingSourceExtension()
|
||||
{
|
||||
}
|
||||
|
||||
public EnumBindingSourceExtension( Type enumType )
|
||||
{
|
||||
EnumType = enumType;
|
||||
}
|
||||
|
||||
public Type EnumType
|
||||
{
|
||||
get => _enumType;
|
||||
set
|
||||
{
|
||||
if ( value != _enumType )
|
||||
{
|
||||
if ( null != value )
|
||||
{
|
||||
Type enumType = Nullable.GetUnderlyingType( value ) ?? value;
|
||||
|
||||
if ( !enumType.IsEnum )
|
||||
{
|
||||
throw new ArgumentException( "Type must be for an Enum." );
|
||||
}
|
||||
}
|
||||
|
||||
_enumType = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override object ProvideValue( IServiceProvider serviceProvider )
|
||||
{
|
||||
if ( null == _enumType )
|
||||
{
|
||||
throw new InvalidOperationException( "The EnumType must be specified." );
|
||||
}
|
||||
|
||||
Type actualEnumType = Nullable.GetUnderlyingType( _enumType ) ?? _enumType;
|
||||
Array enumValues = Enum.GetValues( actualEnumType );
|
||||
|
||||
if ( actualEnumType == _enumType )
|
||||
{
|
||||
return enumValues;
|
||||
}
|
||||
|
||||
Array tempArray = Array.CreateInstance( actualEnumType, enumValues.Length + 1 );
|
||||
enumValues.CopyTo( tempArray, 1 );
|
||||
return tempArray;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using System.Collections.Specialized;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Interactivity;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
public class ItemsControlAutoScrollBehaviour : Behavior<ItemsControl>
|
||||
{
|
||||
public static readonly DependencyProperty ScrollViewerProperty = DependencyProperty.Register( "ScrollViewer",
|
||||
typeof( ScrollViewer ), typeof( ItemsControlAutoScrollBehaviour ),
|
||||
new PropertyMetadata( default( ScrollViewer ) ) );
|
||||
|
||||
public ScrollViewer ScrollViewer
|
||||
{
|
||||
get => (ScrollViewer) GetValue( ScrollViewerProperty );
|
||||
set => SetValue( ScrollViewerProperty, value );
|
||||
}
|
||||
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
( (INotifyCollectionChanged) AssociatedObject.Items ).CollectionChanged += OnCollectionChanged;
|
||||
}
|
||||
|
||||
private void OnCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
|
||||
{
|
||||
ScrollViewer?.ScrollToEnd();
|
||||
}
|
||||
|
||||
protected override void OnDetaching()
|
||||
{
|
||||
base.OnDetaching();
|
||||
|
||||
( (INotifyCollectionChanged) AssociatedObject.Items ).CollectionChanged -= OnCollectionChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Specialized;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Interactivity;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
public class ItemsControlSelectNewEntryBehaviour : Behavior<ItemsControl>
|
||||
{
|
||||
public static readonly DependencyProperty SelectedItemProperty =
|
||||
DependencyProperty.Register( nameof( SelectedItem ), typeof( object ),
|
||||
typeof( ItemsControlSelectNewEntryBehaviour ),
|
||||
new FrameworkPropertyMetadata( default, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault ) );
|
||||
|
||||
public static readonly DependencyProperty TypeProperty = DependencyProperty.Register( nameof( Type ),
|
||||
typeof( Type ), typeof( ItemsControlSelectNewEntryBehaviour ),
|
||||
new FrameworkPropertyMetadata( null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault ) );
|
||||
|
||||
public object SelectedItem
|
||||
{
|
||||
get => GetValue( SelectedItemProperty );
|
||||
set => SetValue( SelectedItemProperty, value );
|
||||
}
|
||||
|
||||
public Type Type
|
||||
{
|
||||
get => (Type) GetValue( TypeProperty );
|
||||
set => SetValue( TypeProperty, value );
|
||||
}
|
||||
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
( (INotifyCollectionChanged) AssociatedObject.Items ).CollectionChanged += OnCollectionChanged;
|
||||
}
|
||||
|
||||
protected override void OnDetaching()
|
||||
{
|
||||
base.OnDetaching();
|
||||
|
||||
( (INotifyCollectionChanged) AssociatedObject.Items ).CollectionChanged -= OnCollectionChanged;
|
||||
}
|
||||
|
||||
private void OnCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
|
||||
{
|
||||
if ( !( sender is ItemCollection ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( e.NewItems == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
object firstItem = e.NewItems[0];
|
||||
|
||||
if ( Type != null )
|
||||
{
|
||||
if ( firstItem.GetType() != Type )
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SelectedItem = firstItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interactivity;
|
||||
using ClassicAssist.UI.ViewModels;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
public class ListViewDoubleClickBehaviour : Behavior<ListView>
|
||||
{
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
AssociatedObject.MouseDoubleClick += OnMouseDoubleClick;
|
||||
}
|
||||
|
||||
private void OnMouseDoubleClick( object sender, MouseButtonEventArgs e )
|
||||
{
|
||||
ObjectInspectorViewModel i = (ObjectInspectorViewModel) ( (ListView) sender ).DataContext;
|
||||
|
||||
i.SelectedItem?.OnDoubleClick?.Invoke( i.SelectedItem );
|
||||
}
|
||||
|
||||
protected override void OnDetaching()
|
||||
{
|
||||
base.OnDetaching();
|
||||
|
||||
AssociatedObject.MouseDoubleClick -= OnMouseDoubleClick;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Interactivity;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
/*
|
||||
* https://stackoverflow.com/questions/8088595/synchronizing-multi-select-listbox-with-mvvm
|
||||
*/
|
||||
|
||||
public class ListViewMultiSelectionBehaviour : Behavior<ListView>
|
||||
{
|
||||
public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register( "SelectedItems",
|
||||
typeof( IList ), typeof( ListViewMultiSelectionBehaviour ),
|
||||
new UIPropertyMetadata( null, SelectedItemsChanged ) );
|
||||
|
||||
private bool _isUpdatingSource;
|
||||
|
||||
private bool _isUpdatingTarget;
|
||||
|
||||
public IList SelectedItems
|
||||
{
|
||||
get => (IList) GetValue( SelectedItemsProperty );
|
||||
set => SetValue( SelectedItemsProperty, value );
|
||||
}
|
||||
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
if ( SelectedItems == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AssociatedObject.SelectedItems.Clear();
|
||||
|
||||
foreach ( object item in SelectedItems )
|
||||
{
|
||||
AssociatedObject.SelectedItems.Add( item );
|
||||
}
|
||||
|
||||
AssociatedObject.SelectionChanged += ListViewSelectionChanged;
|
||||
}
|
||||
|
||||
private static void SelectedItemsChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
|
||||
{
|
||||
if ( o == null || !( o is ListViewMultiSelectionBehaviour behavior ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
INotifyCollectionChanged oldValue = (INotifyCollectionChanged) e.OldValue;
|
||||
INotifyCollectionChanged newValue = (INotifyCollectionChanged) e.NewValue;
|
||||
|
||||
if ( oldValue != null )
|
||||
{
|
||||
oldValue.CollectionChanged -= behavior.SourceCollectionChanged;
|
||||
behavior.AssociatedObject.SelectionChanged -= behavior.ListViewSelectionChanged;
|
||||
}
|
||||
|
||||
if ( newValue == null || behavior.AssociatedObject == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
behavior.AssociatedObject.SelectedItems.Clear();
|
||||
|
||||
if ( newValue is IEnumerable items )
|
||||
{
|
||||
foreach ( object item in items )
|
||||
{
|
||||
behavior.AssociatedObject.SelectedItems.Add( item );
|
||||
}
|
||||
}
|
||||
|
||||
behavior.AssociatedObject.SelectionChanged += behavior.ListViewSelectionChanged;
|
||||
newValue.CollectionChanged += behavior.SourceCollectionChanged;
|
||||
}
|
||||
|
||||
private void SourceCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
|
||||
{
|
||||
if ( _isUpdatingSource )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_isUpdatingTarget = true;
|
||||
|
||||
if ( e.OldItems != null )
|
||||
{
|
||||
foreach ( object item in e.OldItems )
|
||||
{
|
||||
AssociatedObject.SelectedItems.Remove( item );
|
||||
}
|
||||
}
|
||||
|
||||
if ( e.NewItems != null )
|
||||
{
|
||||
foreach ( object item in e.NewItems )
|
||||
{
|
||||
AssociatedObject.SelectedItems.Add( item );
|
||||
}
|
||||
}
|
||||
|
||||
if ( e.Action == NotifyCollectionChangedAction.Reset )
|
||||
{
|
||||
AssociatedObject.SelectedItems.Clear();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isUpdatingTarget = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ListViewSelectionChanged( object sender, SelectionChangedEventArgs e )
|
||||
{
|
||||
if ( e.OriginalSource.GetType() != typeof( ListView ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( _isUpdatingTarget )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IList selectedItems = SelectedItems;
|
||||
|
||||
if ( selectedItems == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_isUpdatingSource = true;
|
||||
|
||||
foreach ( object item in e.RemovedItems )
|
||||
{
|
||||
selectedItems.Remove( item );
|
||||
}
|
||||
|
||||
foreach ( object item in e.AddedItems )
|
||||
{
|
||||
selectedItems.Add( item );
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isUpdatingSource = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Interactivity;
|
||||
using ClassicAssist.Shared;
|
||||
using ClassicAssist.Data;
|
||||
using Sentry;
|
||||
using Sentry.Protocol;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
public class LoadOptionsOnWindowLoaded : Behavior<Window>
|
||||
{
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
AssociatedObject.Loaded += OnLoaded;
|
||||
AssociatedObject.Closing += OnClosing;
|
||||
}
|
||||
|
||||
private static void OnClosing( object sender, CancelEventArgs e )
|
||||
{
|
||||
Options.Save( Options.CurrentOptions );
|
||||
AssistantOptions.Save();
|
||||
}
|
||||
|
||||
private static void OnLoaded( object sender, RoutedEventArgs e )
|
||||
{
|
||||
AssistantOptions.OnWindowLoaded();
|
||||
SentrySdk.Init( new SentryOptions
|
||||
{
|
||||
Dsn = new Dsn( "https://7a7c44cd07e64058a3b434e1c86e4c02@o369765.ingest.sentry.io/5325425" ),
|
||||
BeforeSend = SentryBeforeSend
|
||||
} );
|
||||
}
|
||||
|
||||
private static SentryEvent SentryBeforeSend( SentryEvent args )
|
||||
{
|
||||
args.User = new User { Id = AssistantOptions.UserId };
|
||||
args.SetTag( "SessionId", AssistantOptions.SessionId );
|
||||
args.SetExtra( "PlayerName", Engine.Player?.Name ?? "Unknown" );
|
||||
args.SetExtra( "PlayerSerial", Engine.Player?.Serial ?? 0 );
|
||||
args.SetExtra( "Shard", Engine.CurrentShard?.Name ?? "Unknown" );
|
||||
args.SetExtra( "Connected", Engine.Connected );
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
protected override void OnDetaching()
|
||||
{
|
||||
AssociatedObject.Loaded -= OnLoaded;
|
||||
AssociatedObject.Closing -= OnClosing;
|
||||
base.OnDetaching();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Interactivity;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
/*
|
||||
* https://stackoverflow.com/questions/8088595/synchronizing-multi-select-listbox-with-mvvm
|
||||
*/
|
||||
|
||||
public class MultiSelectionBehaviour : Behavior<ListBox>
|
||||
{
|
||||
public static readonly DependencyProperty SelectedItemsProperty = DependencyProperty.Register( "SelectedItems",
|
||||
typeof( IList ), typeof( MultiSelectionBehaviour ), new UIPropertyMetadata( null, SelectedItemsChanged ) );
|
||||
|
||||
private bool _isUpdatingSource;
|
||||
|
||||
private bool _isUpdatingTarget;
|
||||
|
||||
public IList SelectedItems
|
||||
{
|
||||
get => (IList) GetValue( SelectedItemsProperty );
|
||||
set => SetValue( SelectedItemsProperty, value );
|
||||
}
|
||||
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
if ( SelectedItems == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AssociatedObject.SelectedItems.Clear();
|
||||
|
||||
foreach ( object item in SelectedItems )
|
||||
{
|
||||
AssociatedObject.SelectedItems.Add( item );
|
||||
}
|
||||
}
|
||||
|
||||
private static void SelectedItemsChanged( DependencyObject o, DependencyPropertyChangedEventArgs e )
|
||||
{
|
||||
if ( o == null || !( o is MultiSelectionBehaviour behavior ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
INotifyCollectionChanged oldValue = (INotifyCollectionChanged) e.OldValue;
|
||||
INotifyCollectionChanged newValue = (INotifyCollectionChanged) e.NewValue;
|
||||
|
||||
if ( oldValue != null )
|
||||
{
|
||||
oldValue.CollectionChanged -= behavior.SourceCollectionChanged;
|
||||
behavior.AssociatedObject.SelectionChanged -= behavior.ListBoxSelectionChanged;
|
||||
}
|
||||
|
||||
if ( newValue == null || behavior.AssociatedObject == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
behavior.AssociatedObject.SelectedItems.Clear();
|
||||
|
||||
if ( newValue is IEnumerable items )
|
||||
{
|
||||
foreach ( object item in items )
|
||||
{
|
||||
behavior.AssociatedObject.SelectedItems.Add( item );
|
||||
}
|
||||
}
|
||||
|
||||
behavior.AssociatedObject.SelectionChanged += behavior.ListBoxSelectionChanged;
|
||||
newValue.CollectionChanged += behavior.SourceCollectionChanged;
|
||||
}
|
||||
|
||||
private void SourceCollectionChanged( object sender, NotifyCollectionChangedEventArgs e )
|
||||
{
|
||||
if ( _isUpdatingSource )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_isUpdatingTarget = true;
|
||||
|
||||
if ( e.OldItems != null )
|
||||
{
|
||||
foreach ( object item in e.OldItems )
|
||||
{
|
||||
AssociatedObject.SelectedItems.Remove( item );
|
||||
}
|
||||
}
|
||||
|
||||
if ( e.NewItems != null )
|
||||
{
|
||||
foreach ( object item in e.NewItems )
|
||||
{
|
||||
AssociatedObject.SelectedItems.Add( item );
|
||||
}
|
||||
}
|
||||
|
||||
if ( e.Action == NotifyCollectionChangedAction.Reset )
|
||||
{
|
||||
AssociatedObject.SelectedItems.Clear();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isUpdatingTarget = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void ListBoxSelectionChanged( object sender, SelectionChangedEventArgs e )
|
||||
{
|
||||
if ( _isUpdatingTarget )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IList selectedItems = SelectedItems;
|
||||
|
||||
if ( selectedItems == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_isUpdatingSource = true;
|
||||
|
||||
foreach ( object item in e.RemovedItems )
|
||||
{
|
||||
selectedItems.Remove( item );
|
||||
}
|
||||
|
||||
foreach ( object item in e.AddedItems )
|
||||
{
|
||||
selectedItems.Add( item );
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isUpdatingSource = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
public class SkillsGridViewColumn : GridViewColumn
|
||||
{
|
||||
public enum Enums
|
||||
{
|
||||
Name,
|
||||
Value,
|
||||
Base,
|
||||
Delta,
|
||||
Cap,
|
||||
LockStatus
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty SortFieldProperty = DependencyProperty.Register( "SortField",
|
||||
typeof( Enums ), typeof( SkillsGridViewColumn ), new UIPropertyMetadata( null ) );
|
||||
|
||||
public Enums SortField
|
||||
{
|
||||
get => (Enums) GetValue( SortFieldProperty );
|
||||
set => SetValue( SortFieldProperty, value );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ClassicAssist.UI.Misc.ValueConverters
|
||||
{
|
||||
public class CellWidthValueConverter : IValueConverter
|
||||
{
|
||||
private double substractValue = 15;
|
||||
|
||||
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
if ( parameter != null )
|
||||
{
|
||||
substractValue = double.Parse( parameter.ToString() );
|
||||
}
|
||||
|
||||
double? val = (double?) value - substractValue;
|
||||
return val;
|
||||
}
|
||||
|
||||
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
return (double?) value + substractValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ClassicAssist.UI.Misc.ValueConverters
|
||||
{
|
||||
public class DateTimeToTimeSpanValueConverter : IValueConverter
|
||||
{
|
||||
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
return !( value is DateTime dt ) ? null : ( DateTime.Now - dt ).ToString();
|
||||
}
|
||||
|
||||
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ClassicAssist.UI.Misc.ValueConverters
|
||||
{
|
||||
public class EnumMatchToBooleanConverter : IValueConverter
|
||||
{
|
||||
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
if ( value == null || parameter == null )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string checkValue = value.ToString();
|
||||
string targetValue = parameter.ToString();
|
||||
return checkValue.Equals( targetValue, StringComparison.InvariantCultureIgnoreCase );
|
||||
}
|
||||
|
||||
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
if ( value == null || parameter == null )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
bool useValue = (bool) value;
|
||||
string targetValue = parameter.ToString();
|
||||
|
||||
if ( useValue )
|
||||
{
|
||||
return Enum.Parse( targetType, targetValue );
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ClassicAssist.UI.Misc.ValueConverters
|
||||
{
|
||||
public class HexToIntValueConverter : IValueConverter
|
||||
{
|
||||
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
if ( value is string val && val.StartsWith( "0x" ) )
|
||||
{
|
||||
return System.Convert.ToInt32( val, 16 );
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
if ( value is string val && val.StartsWith( "0x" ) )
|
||||
{
|
||||
return System.Convert.ToInt32( val, 16 );
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ClassicAssist.UI.Misc.ValueConverters
|
||||
{
|
||||
public class IntToHexStringValueConverter : IValueConverter
|
||||
{
|
||||
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
if ( value is int val )
|
||||
{
|
||||
return $"0x{val:x8}";
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ClassicAssist.UI.Misc.ValueConverters
|
||||
{
|
||||
public class InverseBooleanConverter : IValueConverter
|
||||
{
|
||||
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
try
|
||||
{
|
||||
bool testValue = (bool) value;
|
||||
return !testValue; // or do whatever you need with this boolean
|
||||
}
|
||||
catch
|
||||
{
|
||||
return true;
|
||||
} // or false
|
||||
}
|
||||
|
||||
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
return Convert( value, targetType, parameter, culture );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ClassicAssist.UI.Misc.ValueConverters
|
||||
{
|
||||
public class JoinArrayValueConverter : IValueConverter
|
||||
{
|
||||
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
if ( !( value is string[] array ) )
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return string.Join( (string) parameter ?? ", ", array );
|
||||
}
|
||||
|
||||
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using ClassicAssist.Misc;
|
||||
using ClassicAssist.UO.Data;
|
||||
|
||||
namespace ClassicAssist.UI.Misc.ValueConverters
|
||||
{
|
||||
public class LockStatusValueConverter : IValueConverter
|
||||
{
|
||||
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
if ( !( value is LockStatus ) )
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
LockStatus lockStatus = (LockStatus) value;
|
||||
|
||||
switch ( lockStatus )
|
||||
{
|
||||
case LockStatus.Up:
|
||||
|
||||
return Properties.Resources.arrow_up.ToImageSource();
|
||||
case LockStatus.Down:
|
||||
|
||||
return Properties.Resources.arrow_down.ToImageSource();
|
||||
case LockStatus.Locked:
|
||||
|
||||
return Properties.Resources.padlock.ToImageSource();
|
||||
default:
|
||||
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ClassicAssist.UI.Misc.ValueConverters
|
||||
{
|
||||
public class PriorityMultiValueConverter : IMultiValueConverter
|
||||
{
|
||||
//https://stackoverflow.com/questions/1915562/wpf-binding-fallbackvalue-set-to-binding
|
||||
public object Convert( object[] values, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
return values.FirstOrDefault( o => o != null );
|
||||
}
|
||||
|
||||
public object[] ConvertBack( object value, Type[] targetTypes, object parameter, CultureInfo culture )
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Windows.Data;
|
||||
using ClassicAssist.Data.Skills;
|
||||
using ClassicAssist.Misc;
|
||||
using ClassicAssist.UO.Data;
|
||||
|
||||
namespace ClassicAssist.UI.Misc.ValueConverters
|
||||
{
|
||||
public class SetSkillLockData
|
||||
{
|
||||
public LockStatus LockStatus { get; set; }
|
||||
public IEnumerable<SkillEntry> SkillEntries { get; set; }
|
||||
}
|
||||
|
||||
public class SetSkillLockMultiValueConverter : IMultiValueConverter
|
||||
{
|
||||
public object Convert( object[] values, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
IList items = (IList) ( (BindingProxy) values[0] ).Data;
|
||||
IEnumerable<SkillEntry> skills = items.Cast<SkillEntry>();
|
||||
|
||||
LockStatus lockStatus = (LockStatus) values[1];
|
||||
|
||||
return new SetSkillLockData { SkillEntries = skills, LockStatus = lockStatus };
|
||||
}
|
||||
|
||||
public object[] ConvertBack( object value, Type[] targetTypes, object parameter, CultureInfo culture )
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using ClassicAssist.Shared;
|
||||
|
||||
namespace ClassicAssist.UI.Misc.ValueConverters
|
||||
{
|
||||
public class StringToResourceConverter : IValueConverter
|
||||
{
|
||||
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
if ( value is string )
|
||||
{
|
||||
if ( targetType.Equals( typeof( ImageSource ) ) )
|
||||
{
|
||||
return BitmapFrame.Create( Engine.GetResourceStream( (string) value ), BitmapCreateOptions.None,
|
||||
BitmapCacheOption.OnLoad );
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Windows.Data;
|
||||
|
||||
namespace ClassicAssist.UI.Misc.ValueConverters
|
||||
{
|
||||
/*
|
||||
* https://stackoverflow.com/questions/2607490/is-there-a-way-to-chain-multiple-value-converters-in-xaml
|
||||
*/
|
||||
public class ValueConverterGroup : List<IValueConverter>, IValueConverter
|
||||
{
|
||||
#region IValueConverter Members
|
||||
|
||||
public object Convert( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
return this.Aggregate( value,
|
||||
( current, converter ) => converter.Convert( current, targetType, parameter, culture ) );
|
||||
}
|
||||
|
||||
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture )
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using ClassicAssist.Misc;
|
||||
using ClassicAssist.Shared.Resources;
|
||||
using MessageBoxButtons = ClassicAssist.Misc.MessageBoxButtons;
|
||||
using WMessageBox = System.Windows.Forms.MessageBox;
|
||||
using WMessageBoxButtons = System.Windows.Forms.MessageBoxButtons;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
internal class WPFMessageBoxProvider : IMessageBoxProvider
|
||||
{
|
||||
public Task<MessageBoxResult> Show( string text, string caption = null,
|
||||
MessageBoxButtons buttons = MessageBoxButtons.OK, MessageBoxImage? icon = null )
|
||||
{
|
||||
if (string.IsNullOrEmpty( caption ))
|
||||
{
|
||||
caption = Strings.Error;
|
||||
}
|
||||
|
||||
DialogResult result = WMessageBox.Show( text, caption,
|
||||
buttons == MessageBoxButtons.YesNo ? WMessageBoxButtons.YesNo : WMessageBoxButtons.OK );
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case DialogResult.OK: return Task.FromResult( MessageBoxResult.OK );
|
||||
case DialogResult.Yes: return Task.FromResult( MessageBoxResult.Yes );
|
||||
default: return Task.FromResult( MessageBoxResult.No );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Interactivity;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
public enum WindowCommand
|
||||
{
|
||||
Minimize,
|
||||
Maximize,
|
||||
Close
|
||||
}
|
||||
|
||||
public class WindowCommandBehaviour : Behavior<Button>
|
||||
{
|
||||
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register( "Command",
|
||||
typeof( WindowCommand ), typeof( WindowCommandBehaviour ),
|
||||
new FrameworkPropertyMetadata( WindowCommand.Close ) );
|
||||
|
||||
public WindowCommand Command
|
||||
{
|
||||
get => (WindowCommand) GetValue( CommandProperty );
|
||||
set => SetValue( CommandProperty, value );
|
||||
}
|
||||
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
AssociatedObject.Click += OnClick;
|
||||
}
|
||||
|
||||
private void OnClick( object sender, RoutedEventArgs e )
|
||||
{
|
||||
if ( !( sender is UIElement element ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Window window = Window.GetWindow( element );
|
||||
|
||||
if ( window == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch ( Command )
|
||||
{
|
||||
case WindowCommand.Minimize:
|
||||
{
|
||||
window.WindowState = WindowState.Minimized;
|
||||
break;
|
||||
}
|
||||
case WindowCommand.Maximize:
|
||||
{
|
||||
window.WindowState = window.WindowState == WindowState.Maximized
|
||||
? WindowState.Normal
|
||||
: WindowState.Maximized;
|
||||
|
||||
break;
|
||||
}
|
||||
case WindowCommand.Close:
|
||||
{
|
||||
window.Close();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnDetaching()
|
||||
{
|
||||
base.OnDetaching();
|
||||
|
||||
AssociatedObject.Click -= OnClick;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interactivity;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
public class WindowMouseDownBehaviour : Behavior<UIElement>
|
||||
{
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
AssociatedObject.MouseDown += OnMouseDown;
|
||||
}
|
||||
|
||||
protected override void OnDetaching()
|
||||
{
|
||||
base.OnDetaching();
|
||||
|
||||
AssociatedObject.MouseDown -= OnMouseDown;
|
||||
}
|
||||
|
||||
private static void OnMouseDown( object sender, MouseButtonEventArgs e )
|
||||
{
|
||||
if ( !( sender is UIElement element ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ( e.ChangedButton == MouseButton.Left )
|
||||
{
|
||||
Window.GetWindow( element )?.DragMove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#region License
|
||||
|
||||
// Copyright (C) 2020 Reetus
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Interactivity;
|
||||
using ClassicAssist.Data;
|
||||
|
||||
namespace ClassicAssist.UI.Misc
|
||||
{
|
||||
public class WindowResizeBehaviour : Behavior<Window>
|
||||
{
|
||||
protected override void OnAttached()
|
||||
{
|
||||
base.OnAttached();
|
||||
|
||||
#if !DEVELOP
|
||||
AssociatedObject.Width = AssistantOptions.WindowWidth;
|
||||
AssociatedObject.Height = AssistantOptions.WindowHeight;
|
||||
#endif
|
||||
|
||||
AssociatedObject.SizeChanged += OnSizeChanged;
|
||||
AssistantOptions.OptionsLoaded += OnOptionsLoaded;
|
||||
}
|
||||
|
||||
private void OnOptionsLoaded( object sender, EventArgs e )
|
||||
{
|
||||
AssociatedObject.Width = AssistantOptions.WindowWidth;
|
||||
AssociatedObject.Height = AssistantOptions.WindowHeight;
|
||||
}
|
||||
|
||||
private static void OnSizeChanged( object sender, SizeChangedEventArgs e )
|
||||
{
|
||||
#if !DEVELOP
|
||||
AssistantOptions.WindowHeight = e.HeightChanged ? e.NewSize.Height : AssistantOptions.WindowHeight;
|
||||
AssistantOptions.WindowWidth = e.WidthChanged ? e.NewSize.Width : AssistantOptions.WindowWidth;
|
||||
#endif
|
||||
}
|
||||
|
||||
protected override void OnDetaching()
|
||||
{
|
||||
base.OnDetaching();
|
||||
|
||||
AssociatedObject.SizeChanged += OnSizeChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user