Wrapping all view <-> presenter <-> manager related interactions into Mediator pattern

This commit is contained in:
Anton Kasyanov
2018-02-18 19:51:06 +02:00
parent b3a35cb344
commit 8110b5ce7e
21 changed files with 193 additions and 55 deletions

View File

@@ -113,10 +113,18 @@
<Compile Include="Configuration\IAppConfig.cs" />
<Compile Include="Configuration\IThumbnailConfiguration.cs" />
<Compile Include="Configuration\ZoomAnchor.cs" />
<Compile Include="Mediatr\Handlers\Services\StartServicesHandler.cs" />
<Compile Include="Mediatr\Handlers\Services\StopServicesHandler.cs" />
<Compile Include="Mediatr\Messages\Services\StartServices.cs" />
<Compile Include="Mediatr\Messages\Services\StopServices.cs" />
<Compile Include="Mediator\Handlers\Configuration\SaveConfigurationHandler.cs" />
<Compile Include="Mediator\Handlers\Thumbnails\ThumbnailLocationUpdatedHandler.cs" />
<Compile Include="Mediator\Handlers\Thumbnails\ThumbnailSizeUpdatedHandler.cs" />
<Compile Include="Mediator\Handlers\Services\StartServiceHandler.cs" />
<Compile Include="Mediator\Handlers\Services\StopServiceHandler.cs" />
<Compile Include="Mediator\Messages\Base\NotificationBase.cs" />
<Compile Include="Mediator\Messages\Configuration\SaveConfiguration.cs" />
<Compile Include="Mediator\Messages\Services\StartService.cs" />
<Compile Include="Mediator\Messages\Services\StopService.cs" />
<Compile Include="Mediator\Messages\Thumbnails\ThumbnailLocationUpdated.cs" />
<Compile Include="Mediator\Messages\Thumbnails\ThumbnailSizeUpdated.cs" />
<Compile Include="Presenters\Interface\IMainFormPresenter.cs" />
<Compile Include="Services\Implementation\ProcessInfo.cs" />
<Compile Include="Services\Implementation\ProcessMonitor.cs" />
<Compile Include="Services\Interface\IProcessInfo.cs" />
@@ -134,14 +142,14 @@
<Compile Include="ApplicationBase\IPresenter.cs" />
<Compile Include="Services\Implementation\WindowManager.cs" />
<Compile Include="Services\Interop\User32NativeMethods.cs" />
<Compile Include="Presentation\MainPresenter.cs" />
<Compile Include="Presentation\ViewCloseRequest.cs" />
<Compile Include="Presentation\ViewZoomAnchorConverter.cs" />
<Compile Include="Presenters\Implementation\MainFormPresenter.cs" />
<Compile Include="Presenters\ViewCloseRequest.cs" />
<Compile Include="Presenters\ViewZoomAnchorConverter.cs" />
<Compile Include="UI\Interface\IThumbnailViewFactory.cs" />
<Compile Include="Presentation\IThumbnailManager.cs" />
<Compile Include="Presenters\IThumbnailManager.cs" />
<Compile Include="UI\Implementation\ThumbnailDescriptionView.cs" />
<Compile Include="UI\Factory\ThumbnailDescriptionViewFactory.cs" />
<Compile Include="UI\Interface\IMainView.cs" />
<Compile Include="UI\Interface\IMainFormView.cs" />
<Compile Include="ApplicationBase\IView.cs" />
<Compile Include="UI\Interface\IThumbnailDescriptionView.cs" />
<Compile Include="UI\Interface\IThumbnailDescriptionViewFactory.cs" />
@@ -158,7 +166,7 @@
<Compile Include="Configuration\IConfigurationStorage.cs" />
<Compile Include="UI\Interface\IThumbnailView.cs" />
<Compile Include="UI\Factory\ThumbnailViewFactory.cs" />
<Compile Include="Presentation\ThumbnailManager.cs" />
<Compile Include="Presenters\ThumbnailManager.cs" />
<Compile Include="UI\Implementation\ThumbnailOverlay.cs">
<SubType>Form</SubType>
</Compile>

View File

@@ -0,0 +1,25 @@
using System.Threading;
using System.Threading.Tasks;
using EveOPreview.Configuration;
using EveOPreview.Mediator.Messages;
using MediatR;
namespace EveOPreview.Mediator.Handlers.Configuration
{
sealed class SaveConfigurationHandler : IRequestHandler<SaveConfiguration>
{
private readonly IConfigurationStorage _storage;
public SaveConfigurationHandler(IConfigurationStorage storage)
{
this._storage = storage;
}
public Task Handle(SaveConfiguration message, CancellationToken cancellationToken)
{
this._storage.Save();
return Task.CompletedTask;
}
}
}

View File

@@ -4,18 +4,18 @@ using EveOPreview.Mediator.Messages;
using EveOPreview.UI;
using MediatR;
namespace EveOPreview.Mediator.Handlers
namespace EveOPreview.Mediator.Handlers.Services
{
sealed class StartServicesHandler : INotificationHandler<StartServices>
sealed class StartServiceHandler : IRequestHandler<StartService>
{
private readonly IThumbnailManager _manager;
public StartServicesHandler(IThumbnailManager manager)
public StartServiceHandler(IThumbnailManager manager)
{
this._manager = manager;
}
public Task Handle(StartServices message, CancellationToken cancellationToken)
public Task Handle(StartService message, CancellationToken cancellationToken)
{
this._manager.Activate();

View File

@@ -4,18 +4,18 @@ using EveOPreview.Mediator.Messages;
using EveOPreview.UI;
using MediatR;
namespace EveOPreview.Mediator.Handlers
namespace EveOPreview.Mediator.Handlers.Services
{
sealed class StopServicesHandler : INotificationHandler<StopServices>
sealed class StopServiceHandler : IRequestHandler<StopService>
{
private readonly IThumbnailManager _manager;
public StopServicesHandler(IThumbnailManager manager)
public StopServiceHandler(IThumbnailManager manager)
{
this._manager = manager;
}
public Task Handle(StopServices message, CancellationToken cancellationToken)
public Task Handle(StopService message, CancellationToken cancellationToken)
{
this._manager.Deactivate();

View File

@@ -0,0 +1,27 @@
using System.Threading;
using System.Threading.Tasks;
using EveOPreview.Configuration;
using EveOPreview.Mediator.Messages;
using MediatR;
namespace EveOPreview.Mediator.Handlers.Thumbnails
{
sealed class ThumbnailLocationUpdatedHandler : INotificationHandler<ThumbnailLocationUpdated>
{
private readonly IMediator _mediator;
private readonly IThumbnailConfiguration _configuration;
public ThumbnailLocationUpdatedHandler(IMediator mediator, IThumbnailConfiguration configuration)
{
this._mediator = mediator;
this._configuration = configuration;
}
public Task Handle(ThumbnailLocationUpdated notification, CancellationToken cancellationToken)
{
this._configuration.SetThumbnailLocation(notification.ThumbnailName, notification.ActiveClientName, notification.Location);
return this._mediator.Send(new SaveConfiguration(), cancellationToken);
}
}
}

View File

@@ -0,0 +1,25 @@
using System.Threading;
using System.Threading.Tasks;
using EveOPreview.Mediator.Messages;
using EveOPreview.Presenters;
using MediatR;
namespace EveOPreview.Mediator.Handlers.Thumbnails
{
sealed class ThumbnailSizeUpdatedHandler : INotificationHandler<ThumbnailSizeUpdated>
{
private readonly IMainFormPresenter _presenter;
public ThumbnailSizeUpdatedHandler(MainFormPresenter presenter)
{
this._presenter = presenter;
}
public Task Handle(ThumbnailSizeUpdated notification, CancellationToken cancellationToken)
{
this._presenter.UpdateThumbnailSize(notification.Value);
return Task.CompletedTask;
}
}
}

View File

@@ -0,0 +1,14 @@
using MediatR;
namespace EveOPreview.Mediator.Messages
{
abstract class NotificationBase<TValue> : INotification
{
protected NotificationBase(TValue value)
{
this.Value = value;
}
public TValue Value { get; }
}
}

View File

@@ -2,7 +2,7 @@
namespace EveOPreview.Mediator.Messages
{
sealed class StopServices : INotification
sealed class SaveConfiguration : IRequest
{
}
}

View File

@@ -2,7 +2,7 @@
namespace EveOPreview.Mediator.Messages
{
sealed class StartServices : INotification
sealed class StartService : IRequest
{
}
}

View File

@@ -0,0 +1,8 @@
using MediatR;
namespace EveOPreview.Mediator.Messages
{
sealed class StopService : IRequest
{
}
}

View File

@@ -0,0 +1,21 @@
using System.Drawing;
using MediatR;
namespace EveOPreview.Mediator.Messages
{
sealed class ThumbnailLocationUpdated : INotification
{
public ThumbnailLocationUpdated(string thumbnailName, string activeClientName, Point location)
{
this.ThumbnailName = thumbnailName;
this.ActiveClientName = activeClientName;
this.Location = location;
}
public string ThumbnailName { get; }
public string ActiveClientName { get; }
public Point Location { get; }
}
}

View File

@@ -0,0 +1,12 @@
using System.Drawing;
namespace EveOPreview.Mediator.Messages
{
sealed class ThumbnailSizeUpdated : NotificationBase<Size>
{
public ThumbnailSizeUpdated(Size size)
: base(size)
{
}
}
}

View File

@@ -16,8 +16,5 @@ namespace EveOPreview.UI
Action<IList<IThumbnailView>> ThumbnailsAdded { get; set; }
Action<IList<IThumbnailView>> ThumbnailsUpdated { get; set; }
Action<IList<IThumbnailView>> ThumbnailsRemoved { get; set; }
Action<String, String, Point> ThumbnailPositionChanged { get; set; }
Action<Size> ThumbnailSizeChanged { get; set; }
}
}

View File

@@ -4,11 +4,12 @@ using System.Diagnostics;
using System.Drawing;
using EveOPreview.Configuration;
using EveOPreview.Mediator.Messages;
using EveOPreview.UI;
using MediatR;
namespace EveOPreview.UI
namespace EveOPreview.Presenters
{
public class MainPresenter : Presenter<IMainView>
public class MainFormPresenter : Presenter<IMainFormView>, IMainFormPresenter
{
#region Private constants
private const string ForumUrl = @"https://meta.eveonline.com/t/4202";
@@ -25,7 +26,7 @@ namespace EveOPreview.UI
private bool _exitApplication;
#endregion
public MainPresenter(IApplicationController controller, IMainView view, IMediator mediator, IThumbnailConfiguration configuration, IConfigurationStorage configurationStorage,
public MainFormPresenter(IApplicationController controller, IMainFormView view, IMediator mediator, IThumbnailConfiguration configuration, IConfigurationStorage configurationStorage,
IThumbnailManager thumbnailManager, IThumbnailDescriptionViewFactory thumbnailDescriptionViewFactory)
: base(controller, view)
{
@@ -51,22 +52,19 @@ namespace EveOPreview.UI
this._thumbnailManager.ThumbnailsAdded = this.ThumbnailsAdded;
this._thumbnailManager.ThumbnailsUpdated = this.ThumbnailsUpdated;
this._thumbnailManager.ThumbnailsRemoved = this.ThumbnailsRemoved;
this._thumbnailManager.ThumbnailPositionChanged = this.ThumbnailPositionChanged;
this._thumbnailManager.ThumbnailSizeChanged = this.ThumbnailSizeChanged;
}
private void Activate()
{
this.LoadApplicationSettings();
this.View.SetDocumentationUrl(MainPresenter.ForumUrl);
this.View.SetDocumentationUrl(MainFormPresenter.ForumUrl);
this.View.SetVersionInfo(this.GetApplicationVersion());
if (this._configuration.MinimizeToTray)
{
this.View.Minimize();
}
this._mediator.Publish(new StartServices());
this._mediator.Send(new StartService());
}
private void Minimize()
@@ -83,7 +81,7 @@ namespace EveOPreview.UI
{
if (this._exitApplication || !this.View.MinimizeToTray)
{
this._mediator.Publish(new StopServices()).Wait();
this._mediator.Send(new StopService()).Wait();
this._thumbnailManager.Deactivate();
this._configurationStorage.Save();
@@ -215,17 +213,6 @@ namespace EveOPreview.UI
return thumbnailViews;
}
private void ThumbnailPositionChanged(String thumbnailName, String activeClientName, Point location)
{
this._configuration.SetThumbnailLocation(thumbnailName, activeClientName, location);
this._configurationStorage.Save();
}
private void ThumbnailSizeChanged(Size size)
{
this.View.ThumbnailSize = size;
}
private void UpdateThumbnailState(IntPtr thumbnailId)
{
this._thumbnailManager.SetThumbnailState(thumbnailId, this._thumbnailDescriptionViews[thumbnailId].IsDisabled);
@@ -233,7 +220,7 @@ namespace EveOPreview.UI
private void OpenDocumentationLink()
{
ProcessStartInfo processStartInfo = new ProcessStartInfo(new Uri(MainPresenter.ForumUrl).AbsoluteUri);
ProcessStartInfo processStartInfo = new ProcessStartInfo(new Uri(MainFormPresenter.ForumUrl).AbsoluteUri);
Process.Start(processStartInfo);
}
@@ -248,5 +235,10 @@ namespace EveOPreview.UI
this._exitApplication = true;
this.View.Close();
}
public void UpdateThumbnailSize(Size size)
{
this.View.ThumbnailSize = size;
}
}
}

View File

@@ -0,0 +1,9 @@
using System.Drawing;
namespace EveOPreview.Presenters
{
interface IMainFormPresenter
{
void UpdateThumbnailSize(Size size);
}
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Drawing;
using System.Windows.Threading;
using EveOPreview.Configuration;
using EveOPreview.Mediator.Messages;
using EveOPreview.Services;
using MediatR;
@@ -18,6 +19,7 @@ namespace EveOPreview.UI
#endregion
#region Private fields
private readonly IMediator _mediator;
private readonly IProcessMonitor _processMonitor;
private readonly IWindowManager _windowManager;
private readonly IThumbnailConfiguration _configuration;
@@ -34,6 +36,7 @@ namespace EveOPreview.UI
public ThumbnailManager(IMediator mediator, IThumbnailConfiguration configuration, IProcessMonitor processMonitor, IWindowManager windowManager, IThumbnailViewFactory factory)
{
this._mediator = mediator;
this._processMonitor = processMonitor;
this._windowManager = windowManager;
this._configuration = configuration;
@@ -59,10 +62,6 @@ namespace EveOPreview.UI
public Action<IList<IThumbnailView>> ThumbnailsRemoved { get; set; }
public Action<String, String, Point> ThumbnailPositionChanged { get; set; }
public Action<Size> ThumbnailSizeChanged { get; set; }
public void Activate()
{
this._thumbnailUpdateTimer.Start();
@@ -96,7 +95,7 @@ namespace EveOPreview.UI
entry.Value.Refresh(false);
}
this.ThumbnailSizeChanged?.Invoke(size);
this._mediator.Publish(new ThumbnailSizeUpdated(size)); // This one runs asynchronously
this.EnableViewEvents();
}
@@ -372,7 +371,7 @@ namespace EveOPreview.UI
view.Refresh(false);
}
private void ThumbnailViewMoved(IntPtr id)
private async void ThumbnailViewMoved(IntPtr id)
{
if (this._ignoreViewEvents)
{
@@ -383,7 +382,7 @@ namespace EveOPreview.UI
if (this.IsManageableThumbnail(view))
{
this.ThumbnailPositionChanged?.Invoke(view.Title, this._activeClientTitle, view.ThumbnailLocation);
await this._mediator.Publish(new ThumbnailLocationUpdated(view.Title, this._activeClientTitle, view.ThumbnailLocation));
}
view.Refresh(false);

View File

@@ -2,6 +2,7 @@ using System;
using System.Threading;
using System.Windows.Forms;
using EveOPreview.Configuration;
using EveOPreview.Presenters;
using EveOPreview.Services;
using EveOPreview.UI;
using MediatR;
@@ -34,7 +35,7 @@ namespace EveOPreview
IApplicationController controller = Program.InitializeApplicationController();
Program.InitializeWinForms();
controller.Run<MainPresenter>();
controller.Run<MainFormPresenter>();
}
private static object GetInstanceToken()
@@ -97,7 +98,7 @@ namespace EveOPreview
IApplicationController controller = new ApplicationController(container);
// UI classes
controller.RegisterView<IMainView, MainForm>()
controller.RegisterView<IMainFormView, MainForm>()
.RegisterView<IThumbnailView, ThumbnailView>()
.RegisterView<IThumbnailDescriptionView, ThumbnailDescriptionView>()
.RegisterInstance(new ApplicationContext());

View File

@@ -5,7 +5,7 @@ using System.Windows.Forms;
namespace EveOPreview.UI
{
public partial class MainForm : Form, IMainView
public partial class MainForm : Form, IMainFormView
{
#region Private fields
private readonly ApplicationContext _context;

View File

@@ -8,7 +8,7 @@ namespace EveOPreview.UI
/// Main view interface
/// Presenter uses it to access GUI properties
/// </summary>
public interface IMainView : IView
public interface IMainFormView : IView
{
bool MinimizeToTray { get; set; }