1
0
mirror of https://github.com/DarthAffe/Arge.git synced 2022-11-28 19:26:16 +00:00

Moved away from Caliburn and Added some basic stuff with ReactiveUI

(I'm not quite happy with everything so far, but it seems like I'm to stupid to understand how to correctly use routing with the layout I want)
This commit is contained in:
Darth Affe 2017-05-25 20:50:00 +02:00
parent a9f7cbd61c
commit 2576ff2ca2
29 changed files with 464 additions and 282 deletions

View File

@ -1,14 +1,10 @@
<Application x:Class="Arge.App" <Application x:Class="Arge.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:bootstrapper="clr-namespace:Arge.Bootstrapper"
xmlns:resources="clr-namespace:Arge.Resources"> xmlns:resources="clr-namespace:Arge.Resources">
<Application.Resources> <Application.Resources>
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<bootstrapper:ArgeBootstrapper x:Key="Bootstrapper" />
</ResourceDictionary>
<resources:CachedResourceDictionary Source="/Arge;component/Resources/Arge.xaml" /> <resources:CachedResourceDictionary Source="/Arge;component/Resources/Arge.xaml" />
</ResourceDictionary.MergedDictionaries> </ResourceDictionary.MergedDictionaries>
</ResourceDictionary> </ResourceDictionary>

View File

@ -1,7 +1,41 @@
using System.Windows; using System.Windows;
using Arge.Bootstrapper;
namespace Arge namespace Arge
{ {
public partial class App : Application public partial class App : Application
{ } {
#region Properties & Fields
private readonly ArgeBootstrapper _bootstrapper;
#endregion
#region Constructors
public App()
{
_bootstrapper = new ArgeBootstrapper();
}
#endregion
#region Methods
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
_bootstrapper.OnStartup(e);
}
protected override void OnExit(ExitEventArgs e)
{
base.OnExit(e);
_bootstrapper.OnExit(e);
}
#endregion
}
} }

View File

@ -36,15 +36,6 @@
<ApplicationIcon>Resources\ArgeBee.ico</ApplicationIcon> <ApplicationIcon>Resources\ArgeBee.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="Caliburn.Micro, Version=3.0.3.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL">
<HintPath>..\packages\Caliburn.Micro.Core.3.0.3\lib\net45\Caliburn.Micro.dll</HintPath>
</Reference>
<Reference Include="Caliburn.Micro.Platform, Version=3.0.3.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL">
<HintPath>..\packages\Caliburn.Micro.3.0.3\lib\net45\Caliburn.Micro.Platform.dll</HintPath>
</Reference>
<Reference Include="Caliburn.Micro.Platform.Core, Version=3.0.3.0, Culture=neutral, PublicKeyToken=8e5891231f2ed21f, processorArchitecture=MSIL">
<HintPath>..\packages\Caliburn.Micro.3.0.3\lib\net45\Caliburn.Micro.Platform.Core.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.ServiceLocation, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <Reference Include="Microsoft.Practices.ServiceLocation, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll</HintPath> <HintPath>..\packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll</HintPath>
</Reference> </Reference>
@ -57,18 +48,38 @@
<Reference Include="Microsoft.Practices.Unity.RegistrationByConvention, Version=4.0.0.0, Culture=neutral, PublicKeyToken=6d32ff45e0ccc69f, processorArchitecture=MSIL"> <Reference Include="Microsoft.Practices.Unity.RegistrationByConvention, Version=4.0.0.0, Culture=neutral, PublicKeyToken=6d32ff45e0ccc69f, processorArchitecture=MSIL">
<HintPath>..\packages\Unity.4.0.1\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll</HintPath> <HintPath>..\packages\Unity.4.0.1\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll</HintPath>
</Reference> </Reference>
<Reference Include="ReactiveUI, Version=7.3.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\reactiveui-core.7.3.0\lib\Net45\ReactiveUI.dll</HintPath>
</Reference>
<Reference Include="ReactiveUI.Events, Version=7.3.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\reactiveui-events.7.3.0\lib\Net45\ReactiveUI.Events.dll</HintPath>
</Reference>
<Reference Include="RGB.NET.Core, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="RGB.NET.Core, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\RGB.NET.Core.1.0.0\lib\net45\RGB.NET.Core.dll</HintPath> <HintPath>..\packages\RGB.NET.Core.1.0.0\lib\net45\RGB.NET.Core.dll</HintPath>
</Reference> </Reference>
<Reference Include="Splat, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Splat.1.4.0\lib\Net45\Splat.dll</HintPath>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" /> <Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Drawing" /> <Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" /> <Reference Include="System.Reactive.Core, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL"> <HintPath>..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll</HintPath>
<HintPath>..\packages\Caliburn.Micro.3.0.3\lib\net45\System.Windows.Interactivity.dll</HintPath>
<Private>True</Private>
</Reference> </Reference>
<Reference Include="System.Reactive.Interfaces, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Linq, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.PlatformServices, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll</HintPath>
</Reference>
<Reference Include="System.Reactive.Windows.Threading, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Rx-XAML.2.2.5\lib\net45\System.Reactive.Windows.Threading.dll</HintPath>
</Reference>
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
@ -92,21 +103,26 @@
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="Attributes\FileNameAttribute.cs" /> <Compile Include="Attributes\FileNameAttribute.cs" />
<Compile Include="Bootstrapper\ArgeWindowManager.cs" /> <Compile Include="Bootstrapper\NavigationManager.cs" />
<Compile Include="Bootstrapper\UnityBootstrapper.cs" /> <Compile Include="Bootstrapper\UnityBootstrapper.cs" />
<Compile Include="Bootstrapper\UnityDependencyResolver.cs" />
<Compile Include="Configuration\Config.cs" /> <Compile Include="Configuration\Config.cs" />
<Compile Include="Configuration\ConfigEntryType.cs" /> <Compile Include="Configuration\ConfigEntryType.cs" />
<Compile Include="Controls\BlurredDecorationWindow.cs" /> <Compile Include="Controls\Window\BlurredDecorationWindow.cs" />
<Compile Include="Controls\ImageButton.cs" /> <Compile Include="Controls\Buttons\ImageButton.cs" />
<Compile Include="Enums\NavigationTargets.cs" />
<Compile Include="Extensions\EnumExtension.cs" /> <Compile Include="Extensions\EnumExtension.cs" />
<Compile Include="Misc\ActionCommand.cs" />
<Compile Include="Misc\BindingProxy.cs" />
<Compile Include="Resources\CachedResourceDictionary.cs" /> <Compile Include="Resources\CachedResourceDictionary.cs" />
<Compile Include="Resources\ImageSources.cs" /> <Compile Include="Resources\ImageSources.cs" />
<Compile Include="Themes\Theme.cs" /> <Compile Include="Themes\Theme.cs" />
<Compile Include="Themes\ThemeManager.cs" /> <Compile Include="Themes\ThemeManager.cs" />
<Compile Include="Misc\AbstractBindable.cs" /> <Compile Include="ViewModels\AbstractViewModel.cs" />
<Compile Include="ViewModels\NavigationViewModel.cs" />
<Compile Include="ViewModels\ShellViewModel.cs" /> <Compile Include="ViewModels\ShellViewModel.cs" />
<Compile Include="Views\AbstractView.cs" />
<Compile Include="Views\NavigationView.xaml.cs">
<DependentUpon>NavigationView.xaml</DependentUpon>
</Compile>
<Compile Include="Views\ShellView.xaml.cs"> <Compile Include="Views\ShellView.xaml.cs">
<DependentUpon>ShellView.xaml</DependentUpon> <DependentUpon>ShellView.xaml</DependentUpon>
</Compile> </Compile>
@ -141,7 +157,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="AttachedProperties\" /> <Folder Include="AttachedProperties\" />
<Folder Include="Enums\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Page Include="Converter\Converter.xaml"> <Page Include="Converter\Converter.xaml">
@ -172,6 +187,10 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<Page Include="Views\NavigationView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Views\ShellView.xaml"> <Page Include="Views\ShellView.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>

View File

@ -0,0 +1,2 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=views_005Cbase/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -1,10 +1,14 @@
using System.Collections.Generic; using System;
using System.Diagnostics;
using System.Windows; using System.Windows;
using System.Windows.Media.Imaging;
using Arge.Configuration; using Arge.Configuration;
using Arge.Controls.Window;
using Arge.Themes; using Arge.Themes;
using Arge.ViewModels; using Arge.ViewModels;
using Caliburn.Micro; using Arge.Views;
using Microsoft.Practices.Unity; using Microsoft.Practices.Unity;
using ReactiveUI;
namespace Arge.Bootstrapper namespace Arge.Bootstrapper
{ {
@ -14,23 +18,40 @@ namespace Arge.Bootstrapper
protected override void RegisterTypes() protected override void RegisterTypes()
{ {
RegisterInterface<IWindowManager, ArgeWindowManager>(); RegisterServices();
RegisterViews();
}
private void RegisterServices()
{
RegisterSingleton<ThemeManager>(); RegisterSingleton<ThemeManager>();
} }
protected override void OnStartup(object sender, StartupEventArgs e) private void RegisterViews()
{
RegisterView<ShellView, ShellViewModel>();
RegisterView<NavigationView, NavigationViewModel>();
}
protected override void InitializeHandlers()
{
}
protected override void Start()
{ {
Config.Instance.Load(); Config.Instance.Load();
Container.Resolve<ThemeManager>().LoadTheme(Config.Instance[ConfigEntryType.Theme]); Container.Resolve<ThemeManager>().LoadTheme(Config.Instance[ConfigEntryType.Theme]);
Dictionary<string, object> settings = new Dictionary<string, object> BlurredDecorationWindow window = new BlurredDecorationWindow
{ {
{ "Title", "Arge" }, Width = 1280,
{ "Width" , 1280 }, Height = 720,
{ "Height" , 720 } Icon = new BitmapImage(new Uri("pack://application:,,,/Arge;component/Resources/ArgeBee.ico")),
}; IconCommand = ReactiveCommand.Create(() => Process.Start("http://arge.be")),
DisplayRootViewFor<ShellViewModel>(settings); Content = Container.Resolve<ShellView>()
};
Application.Current.MainWindow = window;
window.Show();
} }
#endregion #endregion

View File

@ -1,48 +0,0 @@
using System;
using System.Diagnostics;
using System.Windows;
using System.Windows.Media.Imaging;
using Arge.Controls;
using Arge.Misc;
using Caliburn.Micro;
namespace Arge.Bootstrapper
{
public class ArgeWindowManager : WindowManager
{
#region Methods
protected override Window EnsureWindow(object model, object view, bool isDialog)
{
Window window = view as Window;
if (window == null)
{
window = new BlurredDecorationWindow()
{
Content = view,
SizeToContent = SizeToContent.Manual,
Icon = new BitmapImage(new Uri("pack://application:,,,/Arge;component/Resources/ArgeBee.ico")),
IconCommand = new ActionCommand(() => Process.Start("http://arge.be"))
};
window.SetValue(View.IsGeneratedProperty, true);
Window owner = InferOwnerOf(window);
if (owner != null)
{
window.WindowStartupLocation = WindowStartupLocation.CenterOwner;
window.Owner = owner;
}
else
window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
}
else
{
Window owner = InferOwnerOf(window);
if ((owner != null) && isDialog)
window.Owner = owner;
}
return window;
}
#endregion
}
}

View File

@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using Arge.Enums;
using Microsoft.Practices.Unity;
namespace Arge.Bootstrapper
{
//TODO DarthAffe 21.05.2017: This allows some sort of fake VM-first - One day I should make this cleaner ...
public class NavigationManager
{
#region Properties & Fields
public static NavigationManager Instance { get; private set; }
private readonly Dictionary<Type, Type> _viewTypeMapping = new Dictionary<Type, Type>();
private readonly IUnityContainer _container;
public object Navigation { get; private set; }
public object Layers { get; private set; }
public object Selection { get; private set; }
public object Action { get; private set; }
public object Surface { get; private set; }
#endregion
#region Constructors
private NavigationManager(IUnityContainer container)
{
this._container = container;
}
#endregion
#region Methods
public static void Initialize(IUnityContainer container)
{
Instance = new NavigationManager(container);
}
public void RegisterViewTypes(Type viewType, Type viewModelType)
{
_viewTypeMapping[viewModelType] = viewType;
}
public void Navigate<TTarget>(NavigationTargets target)
{
Navigate(target, typeof(TTarget));
}
public void Navigate(NavigationTargets target, Type targetType)
{
Type viewType;
if (!_viewTypeMapping.TryGetValue(targetType, out viewType))
viewType = targetType;
Navigate(target, _container.Resolve(viewType));
}
public void Navigate(NavigationTargets target, object view)
{
switch (target)
{
case NavigationTargets.Navigation:
Navigation = view;
break;
case NavigationTargets.Layers:
Layers = view;
break;
case NavigationTargets.Selection:
Selection = view;
break;
case NavigationTargets.Action:
Action = view;
break;
case NavigationTargets.Surface:
Surface = view;
break;
}
}
#endregion
}
}

View File

@ -1,11 +1,12 @@
using System; using System;
using System.Collections.Generic; using System.Windows;
using Caliburn.Micro;
using Microsoft.Practices.Unity; using Microsoft.Practices.Unity;
using ReactiveUI;
using Splat;
namespace Arge.Bootstrapper namespace Arge.Bootstrapper
{ {
public abstract class UnityBootstrapper : BootstrapperBase public abstract class UnityBootstrapper
{ {
#region Properties & Fields #region Properties & Fields
@ -13,47 +14,38 @@ namespace Arge.Bootstrapper
#endregion #endregion
#region Constructors
protected UnityBootstrapper()
{
Initialize();
}
#endregion
#region Methods #region Methods
protected override void Configure() public virtual void OnStartup(StartupEventArgs e)
{
Configure();
RegisterTypes();
InitializeHandlers();
Start();
}
public virtual void OnExit(ExitEventArgs e)
{
}
protected virtual void Configure()
{ {
Container = new UnityContainer(); Container = new UnityContainer();
RegisterSingleton(Container); RegisterSingleton(Container);
RegisterInterface<IEventAggregator, EventAggregator>();
RegisterTypes(); Locator.Current = new UnityDependencyResolver(Container);
NavigationManager.Initialize(Container);
} }
protected abstract void RegisterTypes(); protected abstract void RegisterTypes();
protected override object GetInstance(Type service, string key) protected abstract void InitializeHandlers();
{
return key != null ? Container.Resolve(service, key) : Container.Resolve(service);
}
protected override IEnumerable<object> GetAllInstances(Type service) protected abstract void Start();
{
return Container.ResolveAll(service);
}
protected override void BuildUp(object instance)
{
instance = Container.BuildUp(instance);
base.BuildUp(instance);
}
#region Container-Registration #region Container-Registration
protected void RegisterInterface<TInterface, TImplementation>(bool registerTypeToo = true, bool registerAsSingleton = true, string uniqueName = null) protected void RegisterService<TInterface, TImplementation>(bool registerTypeToo = true, bool registerAsSingleton = true, string uniqueName = null)
where TImplementation : TInterface where TImplementation : TInterface
{ {
RegisterTypeIfMissing(typeof(TInterface), typeof(TImplementation), registerAsSingleton, uniqueName); RegisterTypeIfMissing(typeof(TInterface), typeof(TImplementation), registerAsSingleton, uniqueName);
@ -61,6 +53,16 @@ namespace Arge.Bootstrapper
RegisterTypeIfMissing(typeof(TImplementation), typeof(TImplementation), registerAsSingleton, uniqueName); RegisterTypeIfMissing(typeof(TImplementation), typeof(TImplementation), registerAsSingleton, uniqueName);
} }
protected void RegisterView<TView, TViewModel>()
where TView : IViewFor<TViewModel>
where TViewModel : class, IReactiveObject
{
RegisterTypeIfMissing(typeof(TView), typeof(TView), false);
RegisterTypeIfMissing(typeof(TViewModel), typeof(TViewModel), false);
NavigationManager.Instance.RegisterViewTypes(typeof(TView), typeof(TViewModel));
}
protected void RegisterSingleton<T>() protected void RegisterSingleton<T>()
{ {
RegisterTypeIfMissing(typeof(T), typeof(T), true); RegisterTypeIfMissing(typeof(T), typeof(T), true);

View File

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using Microsoft.Practices.Unity;
using Splat;
namespace Arge.Bootstrapper
{
//HACK DarthAffe 21.05.2017: I've no idea if this a good implementation - don't think so but it seems to work ...
public class UnityDependencyResolver : IMutableDependencyResolver
{
#region Properties & Fields
private readonly IUnityContainer _container;
private int _defaultCounter = 0;
#endregion
#region Constructors
public UnityDependencyResolver(IUnityContainer container)
{
this._container = container;
}
#endregion
#region Methods
public void Dispose() { }
public object GetService(Type serviceType, string contract = null)
{
return _container.Resolve(serviceType, contract ?? "default");
}
public IEnumerable<object> GetServices(Type serviceType, string contract = null)
{
return _container.ResolveAll(serviceType);
}
public void Register(Func<object> factory, Type serviceType, string contract = null)
{
if (_container.IsRegistered(serviceType, contract ?? "default"))
contract = $"{(contract ?? "default")}_{_defaultCounter++}";
_container.RegisterType(serviceType, serviceType, contract ?? "default", new InjectionFactory(c => factory()));
}
public IDisposable ServiceRegistrationCallback(Type serviceType, string contract, Action<IDisposable> callback)
{
throw new NotSupportedException();
}
#endregion
}
}

View File

@ -2,7 +2,7 @@
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media; using System.Windows.Media;
namespace Arge.Controls namespace Arge.Controls.Buttons
{ {
public class ImageButton : Button public class ImageButton : Button
{ {

View File

@ -3,14 +3,14 @@ using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
namespace Arge.Controls namespace Arge.Controls.Window
{ {
[TemplatePart(Name = "PART_Decoration", Type = typeof(FrameworkElement))] [TemplatePart(Name = "PART_Decoration", Type = typeof(FrameworkElement))]
[TemplatePart(Name = "PART_Content", Type = typeof(FrameworkElement))] [TemplatePart(Name = "PART_Content", Type = typeof(FrameworkElement))]
[TemplatePart(Name = "PART_CloseButton", Type = typeof(Button))] [TemplatePart(Name = "PART_CloseButton", Type = typeof(Button))]
[TemplatePart(Name = "PART_MinimizeButton", Type = typeof(Button))] [TemplatePart(Name = "PART_MinimizeButton", Type = typeof(Button))]
[TemplatePart(Name = "PART_IconButton", Type = typeof(Button))] [TemplatePart(Name = "PART_IconButton", Type = typeof(Button))]
public class BlurredDecorationWindow : Window public class BlurredDecorationWindow : System.Windows.Window
{ {
#region DependencyProperties #region DependencyProperties
// ReSharper disable InconsistentNaming // ReSharper disable InconsistentNaming

View File

@ -0,0 +1,11 @@
namespace Arge.Enums
{
public enum NavigationTargets
{
Navigation,
Layers,
Selection,
Action,
Surface
}
}

View File

@ -1,44 +0,0 @@
using System.Runtime.CompilerServices;
using Caliburn.Micro;
namespace Arge.Misc
{
public abstract class AbstractBindable : PropertyChangedBase
{
#region Method
/// <summary>
/// Checks if the property already matches the desirec value or needs to be updated.
/// </summary>
/// <typeparam name="T">Type of the property.</typeparam>
/// <param name="storage">Reference to the backing-filed.</param>
/// <param name="value">Value to apply.</param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected virtual bool RequiresUpdate<T>(ref T storage, T value)
{
return !Equals(storage, value);
}
/// <summary>
/// Checks if the property already matches the desired value and updates it if not.
/// </summary>
/// <typeparam name="T">Type of the property.</typeparam>
/// <param name="storage">Reference to the backing-filed.</param>
/// <param name="value">Value to apply.</param>
/// <param name="propertyName">Name of the property used to notify listeners. This value is optional
/// and can be provided automatically when invoked from compilers that support <see cref="CallerMemberNameAttribute"/>.</param>
/// <returns><c>true</c> if the value was changed, <c>false</c> if the existing value matched the desired value.</returns>
protected virtual bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (!RequiresUpdate(ref storage, value)) return false;
storage = value;
// ReSharper disable once ExplicitCallerInfoArgument
NotifyOfPropertyChange(propertyName);
return true;
}
#endregion
}
}

View File

@ -1,50 +0,0 @@
using System;
using System.Windows.Input;
namespace Arge.Misc
{
public class ActionCommand : ICommand
{
#region Properties & Fields
private readonly Func<bool> _canExecute;
private readonly Action _command;
#endregion
#region Constructors
public ActionCommand(Action command, Func<bool> canExecute = null)
{
this._command = command;
this._canExecute = canExecute;
}
#endregion
#region Methods
public bool CanExecute(object parameter)
{
return _canExecute?.Invoke() ?? true;
}
public void Execute(object parameter)
{
_command?.Invoke();
}
public void RaiseCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, new EventArgs());
}
#endregion
#region Events
public event EventHandler CanExecuteChanged;
#endregion
}
}

View File

@ -1,28 +0,0 @@
using System.Windows;
namespace Arge.Misc
{
public class BindingProxy : Freezable
{
#region Properties & Fields
// ReSharper disable InconsistentNaming
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);
}
// ReSharper restore InconsistentNaming
#endregion
#region Methods
protected override Freezable CreateInstanceCore() => new BindingProxy();
#endregion
}
}

View File

@ -1,7 +1,8 @@
<resources:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <resources:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:resources="clr-namespace:Arge.Resources" xmlns:resources="clr-namespace:Arge.Resources"
xmlns:controls="clr-namespace:Arge.Controls"> xmlns:buttons="clr-namespace:Arge.Controls.Buttons"
xmlns:window="clr-namespace:Arge.Controls.Window">
<resources:CachedResourceDictionary.MergedDictionaries> <resources:CachedResourceDictionary.MergedDictionaries>
<resources:CachedResourceDictionary Source="/Arge;component/Styles/BlurredDecorationWindow.xaml" /> <resources:CachedResourceDictionary Source="/Arge;component/Styles/BlurredDecorationWindow.xaml" />
@ -9,8 +10,8 @@
<resources:CachedResourceDictionary Source="/Arge;component/Styles/ToolTip.xaml" /> <resources:CachedResourceDictionary Source="/Arge;component/Styles/ToolTip.xaml" />
</resources:CachedResourceDictionary.MergedDictionaries> </resources:CachedResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type controls:BlurredDecorationWindow}" BasedOn="{StaticResource StyleBlurredDecorationWindow}" /> <Style TargetType="{x:Type window:BlurredDecorationWindow}" BasedOn="{StaticResource StyleBlurredDecorationWindow}" />
<Style TargetType="{x:Type controls:ImageButton}" BasedOn="{StaticResource StyleImageButton}" /> <Style TargetType="{x:Type buttons:ImageButton}" BasedOn="{StaticResource StyleImageButton}" />
<Style TargetType="ToolTip" BasedOn="{StaticResource StyleToolTip}" /> <Style TargetType="ToolTip" BasedOn="{StaticResource StyleToolTip}" />
</resources:CachedResourceDictionary> </resources:CachedResourceDictionary>

View File

@ -4,11 +4,11 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System.Windows.Media; using System.Windows.Media;
using Arge.Attributes; using Arge.Attributes;
using Arge.Misc; using ReactiveUI;
namespace Arge.Resources namespace Arge.Resources
{ {
public class ImageSources : AbstractBindable public class ImageSources : ReactiveObject
{ {
#region Properties & Fields #region Properties & Fields
@ -47,7 +47,8 @@ namespace Arge.Resources
if (string.IsNullOrWhiteSpace(fileName)) continue; if (string.IsNullOrWhiteSpace(fileName)) continue;
propertyInfo.SetValue(this, ConvertToImageSource(files.FirstOrDefault(x => string.Equals(Path.GetFileNameWithoutExtension(x), fileName, StringComparison.OrdinalIgnoreCase)))); propertyInfo.SetValue(this, ConvertToImageSource(files.FirstOrDefault(x => string.Equals(Path.GetFileNameWithoutExtension(x), fileName, StringComparison.OrdinalIgnoreCase))));
NotifyOfPropertyChange(propertyInfo.Name); // ReSharper disable once ExplicitCallerInfoArgument - impossible!
this.RaisePropertyChanged(propertyInfo.Name);
} }
} }

View File

@ -1,7 +1,8 @@
<resources:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <resources:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Arge.Controls" xmlns:resources="clr-namespace:Arge.Resources"
xmlns:resources="clr-namespace:Arge.Resources"> xmlns:buttons="clr-namespace:Arge.Controls.Buttons"
xmlns:window="clr-namespace:Arge.Controls.Window">
<resources:CachedResourceDictionary.MergedDictionaries> <resources:CachedResourceDictionary.MergedDictionaries>
<resources:CachedResourceDictionary Source="/Arge;component/Styles/ImageButton.xaml" /> <resources:CachedResourceDictionary Source="/Arge;component/Styles/ImageButton.xaml" />
@ -10,7 +11,7 @@
<Style x:Key="StyleImageButtonWindow" <Style x:Key="StyleImageButtonWindow"
BasedOn="{StaticResource StyleImageButtonWithOpacity}" BasedOn="{StaticResource StyleImageButtonWithOpacity}"
TargetType="{x:Type controls:ImageButton}"> TargetType="{x:Type buttons:ImageButton}">
<Setter Property="Padding" Value="4" /> <Setter Property="Padding" Value="4" />
<Setter Property="Margin" Value="4" /> <Setter Property="Margin" Value="4" />
<Setter Property="VerticalAlignment" Value="Top" /> <Setter Property="VerticalAlignment" Value="Top" />
@ -19,7 +20,7 @@
</Style> </Style>
<Style x:Key="StyleBlurredDecorationWindow" <Style x:Key="StyleBlurredDecorationWindow"
TargetType="{x:Type controls:BlurredDecorationWindow}"> TargetType="{x:Type window:BlurredDecorationWindow}">
<Setter Property="WindowStyle" Value="None" /> <Setter Property="WindowStyle" Value="None" />
<Setter Property="ResizeMode" Value="CanResize" /> <Setter Property="ResizeMode" Value="CanResize" />
<Setter Property="AllowsTransparency" Value="True" /> <Setter Property="AllowsTransparency" Value="True" />
@ -30,7 +31,6 @@
<Setter Property="BorderBrush" Value="{DynamicResource BrushWindowBorder}" /> <Setter Property="BorderBrush" Value="{DynamicResource BrushWindowBorder}" />
<Setter Property="Background" Value="{DynamicResource BrushWindowBackground}" /> <Setter Property="Background" Value="{DynamicResource BrushWindowBackground}" />
<Setter Property="BackgroundImage" Value="{Binding Source={x:Static resources:ImageSources.Instance}, Path=WindowBackground}" /> <Setter Property="BackgroundImage" Value="{Binding Source={x:Static resources:ImageSources.Instance}, Path=WindowBackground}" />
<Setter Property="ToolTip" Value="http://arge.be" />
<Setter Property="MinWidth" Value="256" /> <Setter Property="MinWidth" Value="256" />
<Setter Property="MinHeight" Value="144" /> <Setter Property="MinHeight" Value="144" />
<Setter Property="SnapsToDevicePixels" Value="True" /> <Setter Property="SnapsToDevicePixels" Value="True" />
@ -43,7 +43,7 @@
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type controls:BlurredDecorationWindow}"> <ControlTemplate TargetType="{x:Type window:BlurredDecorationWindow}">
<Grid Background="{TemplateBinding Background}"> <Grid Background="{TemplateBinding Background}">
<Grid Margin="-12,-12,-12,0"> <Grid Margin="-12,-12,-12,0">
<Viewbox HorizontalAlignment="Center" Stretch="UniformToFill"> <Viewbox HorizontalAlignment="Center" Stretch="UniformToFill">
@ -87,25 +87,25 @@
Height="{TemplateBinding DecorationHeight}" Height="{TemplateBinding DecorationHeight}"
Background="{TemplateBinding BorderBrush}"> Background="{TemplateBinding BorderBrush}">
<DockPanel HorizontalAlignment="Stretch" Margin="4" LastChildFill="False"> <DockPanel HorizontalAlignment="Stretch" Margin="4" LastChildFill="False">
<controls:ImageButton x:Name="PART_CloseButton" <buttons:ImageButton x:Name="PART_CloseButton"
DockPanel.Dock="Right" DockPanel.Dock="Right"
Style="{StaticResource StyleImageButtonWindow}" Style="{StaticResource StyleImageButtonWindow}"
Image="{Binding Source={x:Static resources:ImageSources.Instance}, Path=WindowClose}" Image="{Binding Source={x:Static resources:ImageSources.Instance}, Path=WindowClose}"
ToolTip="Close" /> ToolTip="Close" />
<controls:ImageButton x:Name="PART_MinimizeButton" <buttons:ImageButton x:Name="PART_MinimizeButton"
DockPanel.Dock="Right" DockPanel.Dock="Right"
Style="{StaticResource StyleImageButtonWindow}" Style="{StaticResource StyleImageButtonWindow}"
Image="{Binding Source={x:Static resources:ImageSources.Instance}, Path=WindowMinimize}" Image="{Binding Source={x:Static resources:ImageSources.Instance}, Path=WindowMinimize}"
ToolTip="Minimize" /> ToolTip="Minimize" />
<controls:ImageButton x:Name="PART_IconButton" <buttons:ImageButton x:Name="PART_IconButton"
DockPanel.Dock="Left" DockPanel.Dock="Left"
VerticalAlignment="Center" VerticalAlignment="Center"
Margin="8" Margin="8"
Style="{StaticResource StyleImageButtonWithOpacity}" Style="{StaticResource StyleImageButtonWithOpacity}"
Image="{TemplateBinding Icon}" Image="{TemplateBinding Icon}"
ToolTip="{TemplateBinding ToolTip}" /> ToolTip="http://arge.be" />
</DockPanel> </DockPanel>
</Border> </Border>

View File

@ -1,15 +1,15 @@
<resources:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" <resources:CachedResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Arge.Controls" xmlns:resources="clr-namespace:Arge.Resources"
xmlns:resources="clr-namespace:Arge.Resources"> xmlns:buttons="clr-namespace:Arge.Controls.Buttons">
<Style x:Key="StyleImageButton" <Style x:Key="StyleImageButton"
TargetType="{x:Type controls:ImageButton}"> TargetType="{x:Type buttons:ImageButton}">
<Setter Property="Padding" Value="0" /> <Setter Property="Padding" Value="0" />
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type controls:ImageButton}"> <ControlTemplate TargetType="{x:Type buttons:ImageButton}">
<Grid Background="Transparent"> <Grid Background="Transparent">
<Image x:Name="ImageNormal" Margin="{TemplateBinding Padding}" <Image x:Name="ImageNormal" Margin="{TemplateBinding Padding}"
Source="{TemplateBinding Image}" Stretch="Uniform" /> Source="{TemplateBinding Image}" Stretch="Uniform" />
@ -62,13 +62,13 @@
</Style> </Style>
<Style x:Key="StyleImageButtonWithOpacity" <Style x:Key="StyleImageButtonWithOpacity"
TargetType="{x:Type controls:ImageButton}"> TargetType="{x:Type buttons:ImageButton}">
<Setter Property="Opacity" Value="0.66" /> <Setter Property="Opacity" Value="0.66" />
<Setter Property="Padding" Value="0" /> <Setter Property="Padding" Value="0" />
<Setter Property="Template"> <Setter Property="Template">
<Setter.Value> <Setter.Value>
<ControlTemplate TargetType="{x:Type controls:ImageButton}"> <ControlTemplate TargetType="{x:Type buttons:ImageButton}">
<Grid Background="Transparent"> <Grid Background="Transparent">
<Image x:Name="ImageNormal" Margin="{TemplateBinding Padding}" <Image x:Name="ImageNormal" Margin="{TemplateBinding Padding}"
Source="{TemplateBinding Image}" Stretch="Uniform" /> Source="{TemplateBinding Image}" Stretch="Uniform" />
@ -99,7 +99,7 @@
<Style x:Key="StyleImageButtonMenu" <Style x:Key="StyleImageButtonMenu"
BasedOn="{StaticResource StyleImageButton}" BasedOn="{StaticResource StyleImageButton}"
TargetType="{x:Type controls:ImageButton}"> TargetType="{x:Type buttons:ImageButton}">
<Setter Property="Width" Value="180" /> <Setter Property="Width" Value="180" />
<Setter Property="Height" Value="90" /> <Setter Property="Height" Value="90" />
<Setter Property="Margin" Value="0,16" /> <Setter Property="Margin" Value="0,16" />

View File

@ -1,8 +1,8 @@
using Arge.Misc; using ReactiveUI;
namespace Arge.Themes namespace Arge.Themes
{ {
public class Theme : AbstractBindable public class Theme : ReactiveObject
{ {
#region Properties & Fields #region Properties & Fields

View File

@ -0,0 +1,13 @@
using ReactiveUI;
namespace Arge.ViewModels
{
public abstract class AbstractViewModel : ReactiveObject, ISupportsActivation
{
#region Properties & Fields
public ViewModelActivator Activator { get; } = new ViewModelActivator();
#endregion
}
}

View File

@ -0,0 +1,7 @@
using ReactiveUI;
namespace Arge.ViewModels
{
public class NavigationViewModel : ReactiveObject
{ }
}

View File

@ -1,8 +1,32 @@
using Arge.Misc; using System;
using Arge.Bootstrapper;
using Arge.Enums;
using ReactiveUI;
namespace Arge.ViewModels namespace Arge.ViewModels
{ {
public class ShellViewModel : AbstractBindable public class ShellViewModel : AbstractViewModel
{ {
#region Properties & Fields
public NavigationManager NavigationManager => NavigationManager.Instance;
#endregion
#region Constructors
public ShellViewModel()
{
this.WhenActivated(delegate (Action<IDisposable> action)
{
NavigationManager.Navigate<NavigationViewModel>(NavigationTargets.Navigation);
});
}
#endregion
#region Methods
#endregion
} }
} }

View File

@ -0,0 +1,17 @@
using ReactiveUI;
namespace Arge.Views
{
public class AbstractView<TViewModel> : ReactiveUserControl<TViewModel>
where TViewModel : class
{
#region Constructors
protected AbstractView()
{
this.WhenAnyValue(x => x.ViewModel).BindTo(this, x => x.DataContext);
}
#endregion
}
}

View File

@ -0,0 +1,14 @@
<local:NavigationViewBase x:Class="Arge.Views.NavigationView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Arge.Views"
xmlns:viewModels="clr-namespace:Arge.ViewModels"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=viewModels:NavigationViewModel, IsDesignTimeCreatable=true}"
d:DesignWidth="300" d:DesignHeight="72">
<Grid>
</Grid>
</local:NavigationViewBase>

View File

@ -0,0 +1,18 @@
using Arge.ViewModels;
using ReactiveUI;
namespace Arge.Views
{
public class NavigationViewBase : ReactiveUserControl<NavigationViewModel>
{ }
public partial class NavigationView : NavigationViewBase
{
public NavigationView(NavigationViewModel viewModel)
{
InitializeComponent();
this.ViewModel = viewModel;
}
}
}

View File

@ -1,11 +1,20 @@
<UserControl x:Class="Arge.Views.ShellView" <views:ShellViewBase x:Class="Arge.Views.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:viewModels="clr-namespace:Arge.ViewModels" xmlns:viewModels="clr-namespace:Arge.ViewModels"
mc:Ignorable="d" xmlns:views="clr-namespace:Arge.Views"
d:DataContext="{d:DesignInstance Type=viewModels:ShellViewModel, IsDesignTimeCreatable=true}"> mc:Ignorable="d"
d:DataContext="{d:DesignInstance Type=viewModels:ShellViewModel, IsDesignTimeCreatable=true}">
<Grid>
</UserControl> <ContentControl x:Name="TargetNavigation" HorizontalAlignment="Stretch" VerticalAlignment="Top" Height="72" Margin="80,-72,72,0" />
<DockPanel LastChildFill="True">
<ContentControl x:Name="TargetLayers" DockPanel.Dock="Left" />
<ContentControl x:Name="TargetSelection" DockPanel.Dock="Right" />
<ContentControl x:Name="TargetActions" DockPanel.Dock="Bottom" />
<ContentControl x:Name="TargetSurface" />
</DockPanel>
</Grid>
</views:ShellViewBase>

View File

@ -1,14 +1,24 @@
using System.Windows.Controls; using Arge.ViewModels;
using ReactiveUI;
namespace Arge.Views namespace Arge.Views
{ {
public partial class ShellView : UserControl public class ShellViewBase : AbstractView<ShellViewModel> { }
public partial class ShellView : ShellViewBase
{ {
#region Constructors #region Constructors
public ShellView() public ShellView(ShellViewModel viewModel)
{ {
InitializeComponent(); InitializeComponent();
this.ViewModel = viewModel;
this.WhenActivated(d =>
{
d(this.OneWayBind(ViewModel, vm => vm.NavigationManager.Navigation, v => v.TargetNavigation.Content));
});
} }
#endregion #endregion

View File

@ -1,8 +1,16 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Caliburn.Micro" version="3.0.3" targetFramework="net45" />
<package id="Caliburn.Micro.Core" version="3.0.3" targetFramework="net45" />
<package id="CommonServiceLocator" version="1.3" targetFramework="net45" /> <package id="CommonServiceLocator" version="1.3" targetFramework="net45" />
<package id="reactiveui" version="7.3.0" targetFramework="net45" />
<package id="reactiveui-core" version="7.3.0" targetFramework="net45" />
<package id="reactiveui-events" version="7.3.0" targetFramework="net45" />
<package id="RGB.NET.Core" version="1.0.0" targetFramework="net45" /> <package id="RGB.NET.Core" version="1.0.0" targetFramework="net45" />
<package id="Rx-Core" version="2.2.5" targetFramework="net45" />
<package id="Rx-Interfaces" version="2.2.5" targetFramework="net45" />
<package id="Rx-Linq" version="2.2.5" targetFramework="net45" />
<package id="Rx-Main" version="2.2.5" targetFramework="net45" />
<package id="Rx-PlatformServices" version="2.2.5" targetFramework="net45" />
<package id="Rx-XAML" version="2.2.5" targetFramework="net45" />
<package id="Splat" version="1.4.0" targetFramework="net45" />
<package id="Unity" version="4.0.1" targetFramework="net45" /> <package id="Unity" version="4.0.1" targetFramework="net45" />
</packages> </packages>