diff --git a/Arge/App.xaml b/Arge/App.xaml index 92036f5..bd13693 100644 --- a/Arge/App.xaml +++ b/Arge/App.xaml @@ -1,14 +1,10 @@  - - - diff --git a/Arge/App.xaml.cs b/Arge/App.xaml.cs index d44d326..7f9120b 100644 --- a/Arge/App.xaml.cs +++ b/Arge/App.xaml.cs @@ -1,7 +1,41 @@ using System.Windows; +using Arge.Bootstrapper; namespace Arge { 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 + } } diff --git a/Arge/Arge.csproj b/Arge/Arge.csproj index 2f570f6..d565bee 100644 --- a/Arge/Arge.csproj +++ b/Arge/Arge.csproj @@ -36,15 +36,6 @@ Resources\ArgeBee.ico - - ..\packages\Caliburn.Micro.Core.3.0.3\lib\net45\Caliburn.Micro.dll - - - ..\packages\Caliburn.Micro.3.0.3\lib\net45\Caliburn.Micro.Platform.dll - - - ..\packages\Caliburn.Micro.3.0.3\lib\net45\Caliburn.Micro.Platform.Core.dll - ..\packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll @@ -57,18 +48,38 @@ ..\packages\Unity.4.0.1\lib\net45\Microsoft.Practices.Unity.RegistrationByConvention.dll + + ..\packages\reactiveui-core.7.3.0\lib\Net45\ReactiveUI.dll + + + ..\packages\reactiveui-events.7.3.0\lib\Net45\ReactiveUI.Events.dll + ..\packages\RGB.NET.Core.1.0.0\lib\net45\RGB.NET.Core.dll + + ..\packages\Splat.1.4.0\lib\Net45\Splat.dll + - - - ..\packages\Caliburn.Micro.3.0.3\lib\net45\System.Windows.Interactivity.dll - True + + ..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll + + ..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll + + + ..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll + + + ..\packages\Rx-PlatformServices.2.2.5\lib\net45\System.Reactive.PlatformServices.dll + + + ..\packages\Rx-XAML.2.2.5\lib\net45\System.Reactive.Windows.Threading.dll + + @@ -92,21 +103,26 @@ Code - + + - - + + + - - - + + + + + NavigationView.xaml + ShellView.xaml @@ -141,7 +157,6 @@ - @@ -172,6 +187,10 @@ Designer Always + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/Arge/Arge.csproj.DotSettings b/Arge/Arge.csproj.DotSettings new file mode 100644 index 0000000..2b43c4a --- /dev/null +++ b/Arge/Arge.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/Arge/Bootstrapper/ArgeBootstrapper.cs b/Arge/Bootstrapper/ArgeBootstrapper.cs index 22aaef8..6aeb276 100644 --- a/Arge/Bootstrapper/ArgeBootstrapper.cs +++ b/Arge/Bootstrapper/ArgeBootstrapper.cs @@ -1,10 +1,14 @@ -using System.Collections.Generic; +using System; +using System.Diagnostics; using System.Windows; +using System.Windows.Media.Imaging; using Arge.Configuration; +using Arge.Controls.Window; using Arge.Themes; using Arge.ViewModels; -using Caliburn.Micro; +using Arge.Views; using Microsoft.Practices.Unity; +using ReactiveUI; namespace Arge.Bootstrapper { @@ -14,23 +18,40 @@ namespace Arge.Bootstrapper protected override void RegisterTypes() { - RegisterInterface(); + RegisterServices(); + RegisterViews(); + } + private void RegisterServices() + { RegisterSingleton(); } - protected override void OnStartup(object sender, StartupEventArgs e) + private void RegisterViews() + { + RegisterView(); + RegisterView(); + } + + protected override void InitializeHandlers() + { + } + + protected override void Start() { Config.Instance.Load(); Container.Resolve().LoadTheme(Config.Instance[ConfigEntryType.Theme]); - Dictionary settings = new Dictionary - { - { "Title", "Arge" }, - { "Width" , 1280 }, - { "Height" , 720 } - }; - DisplayRootViewFor(settings); + BlurredDecorationWindow window = new BlurredDecorationWindow + { + Width = 1280, + Height = 720, + Icon = new BitmapImage(new Uri("pack://application:,,,/Arge;component/Resources/ArgeBee.ico")), + IconCommand = ReactiveCommand.Create(() => Process.Start("http://arge.be")), + Content = Container.Resolve() + }; + Application.Current.MainWindow = window; + window.Show(); } #endregion diff --git a/Arge/Bootstrapper/ArgeWindowManager.cs b/Arge/Bootstrapper/ArgeWindowManager.cs deleted file mode 100644 index 2fdc1f4..0000000 --- a/Arge/Bootstrapper/ArgeWindowManager.cs +++ /dev/null @@ -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 - } -} diff --git a/Arge/Bootstrapper/NavigationManager.cs b/Arge/Bootstrapper/NavigationManager.cs new file mode 100644 index 0000000..2b47fe3 --- /dev/null +++ b/Arge/Bootstrapper/NavigationManager.cs @@ -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 _viewTypeMapping = new Dictionary(); + + 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(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 + } +} diff --git a/Arge/Bootstrapper/UnityBootstrapper.cs b/Arge/Bootstrapper/UnityBootstrapper.cs index 0fb62ff..13397bb 100644 --- a/Arge/Bootstrapper/UnityBootstrapper.cs +++ b/Arge/Bootstrapper/UnityBootstrapper.cs @@ -1,11 +1,12 @@ using System; -using System.Collections.Generic; -using Caliburn.Micro; +using System.Windows; using Microsoft.Practices.Unity; +using ReactiveUI; +using Splat; namespace Arge.Bootstrapper { - public abstract class UnityBootstrapper : BootstrapperBase + public abstract class UnityBootstrapper { #region Properties & Fields @@ -13,47 +14,38 @@ namespace Arge.Bootstrapper #endregion - #region Constructors - - protected UnityBootstrapper() - { - Initialize(); - } - - #endregion - #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(); RegisterSingleton(Container); - RegisterInterface(); - RegisterTypes(); + Locator.Current = new UnityDependencyResolver(Container); + NavigationManager.Initialize(Container); } protected abstract void RegisterTypes(); - protected override object GetInstance(Type service, string key) - { - return key != null ? Container.Resolve(service, key) : Container.Resolve(service); - } + protected abstract void InitializeHandlers(); - protected override IEnumerable GetAllInstances(Type service) - { - return Container.ResolveAll(service); - } - - protected override void BuildUp(object instance) - { - instance = Container.BuildUp(instance); - base.BuildUp(instance); - } + protected abstract void Start(); #region Container-Registration - protected void RegisterInterface(bool registerTypeToo = true, bool registerAsSingleton = true, string uniqueName = null) + protected void RegisterService(bool registerTypeToo = true, bool registerAsSingleton = true, string uniqueName = null) where TImplementation : TInterface { RegisterTypeIfMissing(typeof(TInterface), typeof(TImplementation), registerAsSingleton, uniqueName); @@ -61,6 +53,16 @@ namespace Arge.Bootstrapper RegisterTypeIfMissing(typeof(TImplementation), typeof(TImplementation), registerAsSingleton, uniqueName); } + protected void RegisterView() + where TView : IViewFor + 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() { RegisterTypeIfMissing(typeof(T), typeof(T), true); diff --git a/Arge/Bootstrapper/UnityDependencyResolver.cs b/Arge/Bootstrapper/UnityDependencyResolver.cs new file mode 100644 index 0000000..624f422 --- /dev/null +++ b/Arge/Bootstrapper/UnityDependencyResolver.cs @@ -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 GetServices(Type serviceType, string contract = null) + { + return _container.ResolveAll(serviceType); + } + + public void Register(Func 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 callback) + { + throw new NotSupportedException(); + } + + #endregion + } +} diff --git a/Arge/Controls/ImageButton.cs b/Arge/Controls/Buttons/ImageButton.cs similarity index 98% rename from Arge/Controls/ImageButton.cs rename to Arge/Controls/Buttons/ImageButton.cs index f36ba21..300b89c 100644 --- a/Arge/Controls/ImageButton.cs +++ b/Arge/Controls/Buttons/ImageButton.cs @@ -2,7 +2,7 @@ using System.Windows.Controls; using System.Windows.Media; -namespace Arge.Controls +namespace Arge.Controls.Buttons { public class ImageButton : Button { diff --git a/Arge/Controls/BlurredDecorationWindow.cs b/Arge/Controls/Window/BlurredDecorationWindow.cs similarity index 97% rename from Arge/Controls/BlurredDecorationWindow.cs rename to Arge/Controls/Window/BlurredDecorationWindow.cs index e62203b..821b1a2 100644 --- a/Arge/Controls/BlurredDecorationWindow.cs +++ b/Arge/Controls/Window/BlurredDecorationWindow.cs @@ -3,14 +3,14 @@ using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; -namespace Arge.Controls +namespace Arge.Controls.Window { [TemplatePart(Name = "PART_Decoration", Type = typeof(FrameworkElement))] [TemplatePart(Name = "PART_Content", Type = typeof(FrameworkElement))] [TemplatePart(Name = "PART_CloseButton", Type = typeof(Button))] [TemplatePart(Name = "PART_MinimizeButton", Type = typeof(Button))] [TemplatePart(Name = "PART_IconButton", Type = typeof(Button))] - public class BlurredDecorationWindow : Window + public class BlurredDecorationWindow : System.Windows.Window { #region DependencyProperties // ReSharper disable InconsistentNaming diff --git a/Arge/Enums/NavigationTargets.cs b/Arge/Enums/NavigationTargets.cs new file mode 100644 index 0000000..391361f --- /dev/null +++ b/Arge/Enums/NavigationTargets.cs @@ -0,0 +1,11 @@ +namespace Arge.Enums +{ + public enum NavigationTargets + { + Navigation, + Layers, + Selection, + Action, + Surface + } +} diff --git a/Arge/Misc/AbstractBindable.cs b/Arge/Misc/AbstractBindable.cs deleted file mode 100644 index f6d25c3..0000000 --- a/Arge/Misc/AbstractBindable.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Runtime.CompilerServices; -using Caliburn.Micro; - -namespace Arge.Misc -{ - public abstract class AbstractBindable : PropertyChangedBase - { - #region Method - - /// - /// Checks if the property already matches the desirec value or needs to be updated. - /// - /// Type of the property. - /// Reference to the backing-filed. - /// Value to apply. - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected virtual bool RequiresUpdate(ref T storage, T value) - { - return !Equals(storage, value); - } - - /// - /// Checks if the property already matches the desired value and updates it if not. - /// - /// Type of the property. - /// Reference to the backing-filed. - /// Value to apply. - /// Name of the property used to notify listeners. This value is optional - /// and can be provided automatically when invoked from compilers that support . - /// true if the value was changed, false if the existing value matched the desired value. - protected virtual bool SetProperty(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 - } -} diff --git a/Arge/Misc/ActionCommand.cs b/Arge/Misc/ActionCommand.cs deleted file mode 100644 index 45ca310..0000000 --- a/Arge/Misc/ActionCommand.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System; -using System.Windows.Input; - -namespace Arge.Misc -{ - public class ActionCommand : ICommand - { - #region Properties & Fields - - private readonly Func _canExecute; - private readonly Action _command; - - #endregion - - #region Constructors - - public ActionCommand(Action command, Func 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 - } -} diff --git a/Arge/Misc/BindingProxy.cs b/Arge/Misc/BindingProxy.cs deleted file mode 100644 index fe63b43..0000000 --- a/Arge/Misc/BindingProxy.cs +++ /dev/null @@ -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 - } -} diff --git a/Arge/Resources/Arge.xaml b/Arge/Resources/Arge.xaml index 9c58a17..69d731f 100644 --- a/Arge/Resources/Arge.xaml +++ b/Arge/Resources/Arge.xaml @@ -1,7 +1,8 @@  + xmlns:buttons="clr-namespace:Arge.Controls.Buttons" + xmlns:window="clr-namespace:Arge.Controls.Window"> @@ -9,8 +10,8 @@ -