first commit

This commit is contained in:
Beyhan Oğur
2026-09-03 04:45:36 +03:00
commit d5f52cc3d3
1038 changed files with 169579 additions and 0 deletions
@@ -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
}
}
+26
View File
@@ -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();
}
}
}
+79
View File
@@ -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;
}
}
}