Permalink
Browse files

Added license issue feature

-License issuance added
-Added Status bar to shell
  • Loading branch information...
1 parent e38f308 commit 68dbd5e4fb97b3e83f761c1f60e47e092466bfe5 @HEskandari HEskandari committed Sep 3, 2010
View
18 Rhino.Licensing.AdminTool.Tests/Models/LicenseModelTests.cs
@@ -0,0 +1,18 @@
+using Rhino.Licensing.AdminTool.Model;
+using Xunit;
+using Caliburn.Testability.Extensions;
+
+namespace Rhino.Licensing.AdminTool.Tests.Models
+{
+ public class LicenseModelTests
+ {
+ [Fact]
+ public void License_Fires_Property_Changed()
+ {
+ var license = new License();
+
+ license.AssertThatAllProperties()
+ .RaiseChangeNotification();
+ }
+ }
+}
View
2 Rhino.Licensing.AdminTool.Tests/Rhino.Licensing.AdminTool.Tests.csproj
@@ -96,7 +96,9 @@
<Compile Include="Dialogs\FileDialogTests.cs" />
<Compile Include="Dialogs\OpenFileDialogTests.cs" />
<Compile Include="Dialogs\SaveFileDialogTests.cs" />
+ <Compile Include="Models\LicenseModelTests.cs" />
<Compile Include="Services\BoolToVisibilityConverterTests.cs" />
+ <Compile Include="Services\StatusServiceTests.cs" />
<Compile Include="Startup\ContainerTests.cs" />
<Compile Include="Startup\GuyWireTests.cs" />
<Compile Include="Models\ProductModelTests.cs" />
View
29 Rhino.Licensing.AdminTool.Tests/Services/ProjectServiceTests.cs
@@ -1,14 +1,16 @@
+using System;
using System.IO;
using Rhino.Licensing.AdminTool.Model;
using Rhino.Licensing.AdminTool.Services;
-using Xunit;
-
+using Xunit;
+using Xunit.Extensions;
+
namespace Rhino.Licensing.AdminTool.Tests.Services
{
public class ProjectServiceTests
{
[Fact]
- public void Can_Save_Project_Graph()
+ public void Can_Save_Project()
{
var p = CreateNewProject();
var service = new ProjectService() as IProjectService;
@@ -24,7 +26,7 @@ public void Can_Save_Project_Graph()
}
[Fact]
- public void Can_Load_Project_Graph()
+ public void Can_Load_Project()
{
var p = CreateNewProject();
var service = new ProjectService() as IProjectService;
@@ -42,6 +44,25 @@ public void Can_Load_Project_Graph()
}
[Fact]
+ public void Can_Load_Project_With_Licenses()
+ {
+ var p = CreateNewProject();
+ var service = new ProjectService() as IProjectService;
+ var fileInfo = new FileInfo(Path.GetTempFileName());
+ var expirationDate = new DateTime(2010, 5, 5);
+
+ p.Product.IssuedLicenses.Add(new License { ExpirationDate = expirationDate, LicenseType = LicenseType.Trial, OwnerName = "John Doe" });
+ service.Save(p, fileInfo);
+ var project = service.Open(fileInfo);
+
+ Assert.NotNull(project);
+ Assert.Equal(1, project.Product.IssuedLicenses.Count);
+ Assert.Equal("John Doe", project.Product.IssuedLicenses[0].OwnerName);
+ Assert.Equal(expirationDate, project.Product.IssuedLicenses[0].ExpirationDate);
+ Assert.Equal(LicenseType.Trial, project.Product.IssuedLicenses[0].LicenseType);
+ }
+
+ [Fact]
public void Can_Create_New_Project()
{
var service = new ProjectService() as IProjectService;
View
34 Rhino.Licensing.AdminTool.Tests/Services/StatusServiceTests.cs
@@ -0,0 +1,34 @@
+using System;
+using Caliburn.PresentationFramework.ApplicationModel;
+using Rhino.Licensing.AdminTool.Factories;
+using Rhino.Licensing.AdminTool.Services;
+using Rhino.Licensing.AdminTool.ViewModels;
+using Rhino.Mocks;
+using Xunit;
+
+namespace Rhino.Licensing.AdminTool.Tests.Services
+{
+ public class StatusServiceTests
+ {
+ private readonly IStatusService _statusService;
+
+ public StatusServiceTests()
+ {
+ var windowManager = MockRepository.GenerateMock<IWindowManager>();
+ var viewModelFactory = MockRepository.GenerateMock<IViewModelFactory>();
+ var projectService = MockRepository.GenerateMock<IProjectService>();
+
+ _statusService = new ShellViewModel(windowManager, viewModelFactory, projectService);
+ }
+
+ [Fact]
+ public void Can_Update_Status_Message()
+ {
+ _statusService.Update("Issued Licenses: {0}", 10);
+
+ var vm = _statusService as IShellViewModel;
+
+ Assert.Equal("Issued Licenses: 10", vm.StatusMessage);
+ }
+ }
+}
View
93 Rhino.Licensing.AdminTool.Tests/ViewModels/ProjectViewModelTests.cs
@@ -2,24 +2,27 @@
using System.Windows;
using Caliburn.Testability;
using Rhino.Licensing.AdminTool.Model;
-using Rhino.Licensing.AdminTool.Services;
+using Rhino.Licensing.AdminTool.Services;
+using Rhino.Licensing.AdminTool.Tests.Base;
using Rhino.Licensing.AdminTool.ViewModels;
using Rhino.Licensing.AdminTool.Views;
using Rhino.Mocks;
using Xunit;
using Caliburn.Testability.Extensions;
namespace Rhino.Licensing.AdminTool.Tests.ViewModels
-{
- public class ProjectViewModelTests
+{
+ public class ProjectViewModelTests : TestBase
{
private readonly IDialogService _dialogService;
- private readonly IProjectService _projectService;
+ private readonly IProjectService _projectService;
+ private readonly IStatusService _statusService;
public ProjectViewModelTests()
{
_dialogService = MockRepository.GenerateMock<IDialogService>();
- _projectService = MockRepository.GenerateMock<IProjectService>();
+ _projectService = MockRepository.GenerateMock<IProjectService>();
+ _statusService = MockRepository.GenerateMock<IStatusService>();
}
[Fact]
@@ -39,14 +42,28 @@ public void Fires_PropertyChange_Notification()
}
[Fact]
- public void Properties_Are_Bound()
+ public void CurrentProject_Properties_Are_Bound()
{
var validator = Validator.For<ProjectView, ProjectViewModel>()
.Validate();
validator.AssertWasBound(x => x.CurrentProject.Product.Name);
validator.AssertWasBound(x => x.CurrentProject.Product.PrivateKey);
validator.AssertWasBound(x => x.CurrentProject.Product.PublicKey);
+ validator.AssertWasBound(x => x.CurrentProject.Product.IssuedLicenses);
+ }
+
+ [Fact]
+ public void IssuedLicense_List_Is_Bound()
+ {
+ var template = Application.Current.FindResource("IssuedLicenseTemplate") as DataTemplate;
+ var validator = Validator.For<License>(template);
+
+ var result = validator.Validate();
+
+ result.AssertWasBound(x => x.LicenseType);
+ result.AssertWasBound(x => x.OwnerName);
+ result.AssertWasBound(x => x.ExpirationDate);
}
[Fact]
@@ -137,7 +154,7 @@ public void Can_Generate_Key_Pair()
[Fact]
public void Default_Project_Save_Dialog()
{
- var vm = new ProjectViewModel(_projectService, _dialogService);
+ var vm = new ProjectViewModel(_projectService, _dialogService, _statusService);
var dialogModel = vm.CreateSaveDialogModel();
Assert.Equal("Rhino License|*.rlic", dialogModel.Filter);
@@ -147,7 +164,7 @@ public void Default_Project_Save_Dialog()
[Fact]
public void Default_Project_Open_Dialog()
{
- var vm = new ProjectViewModel(_projectService, _dialogService);
+ var vm = new ProjectViewModel(_projectService, _dialogService, _statusService);
var dialogModel = vm.CreateOpenDialogModel();
Assert.Equal("Rhino License|*.rlic", dialogModel.Filter);
@@ -191,6 +208,17 @@ public void Open_Shows_OpenDialog()
}
[Fact]
+ public void Open_Returns_False_When_User_Cancels_The_Open_Dialog()
+ {
+ var dialogModel = new OpenFileDialogViewModel { Result = false, FileName = "C:\\" };
+ var vm = CreateViewModel(dialogModel);
+
+ var opened = vm.Open();
+
+ Assert.False(opened);
+ }
+
+ [Fact]
public void Open_Loads_Project()
{
var p = new Project();
@@ -205,28 +233,67 @@ public void Open_Loads_Project()
Assert.Same(p, vm.CurrentProject);
}
+ [Fact]
+ public void Can_Not_Issue_New_License_If_Keys_Are_Not_Generated()
+ {
+ var vm = CreateViewModel();
+
+ vm.CurrentProject = new Project();
+ var canAdd = vm.CanAddLicense();
+
+ Assert.False(canAdd);
+ }
+
+ [Fact]
+ public void Can_Issue_New_License_If_Keys_Are_Generated()
+ {
+ var vm = CreateViewModel();
+
+ vm.CurrentProject = new Project();
+ vm.GenerateKey();
+ var canAdd = vm.CanAddLicense();
+
+ Assert.True(canAdd);
+ }
+
+ [Fact]
+ public void AddLicense_Issues_New_License()
+ {
+ var vm = CreateViewModel();
+
+ vm.CurrentProject = new Project();
+ vm.AddLicense();
+
+ Assert.Equal(1, vm.CurrentProject.Product.IssuedLicenses.Count);
+ }
+
private ProjectViewModel CreateViewModel(ISaveFileDialogViewModel model)
{
- return new TestProjectViewModel(_projectService, _dialogService, model, null);
+ return new TestProjectViewModel(_projectService, _dialogService, model, null, _statusService);
}
private ProjectViewModel CreateViewModel(IOpenFileDialogViewModel model)
{
- return new TestProjectViewModel(_projectService, _dialogService, null, model);
+ return new TestProjectViewModel(_projectService, _dialogService, null, model, _statusService);
}
private ProjectViewModel CreateViewModel()
{
- return new TestProjectViewModel(_projectService, _dialogService, null, null);
+ return new TestProjectViewModel(_projectService, _dialogService, null, null, _statusService);
}
public class TestProjectViewModel : ProjectViewModel
{
private readonly ISaveFileDialogViewModel _saveDialogModel;
private readonly IOpenFileDialogViewModel _openDialogModel;
- public TestProjectViewModel(IProjectService projectService, IDialogService dialogService, ISaveFileDialogViewModel saveModel, IOpenFileDialogViewModel openModel)
- : base(projectService, dialogService)
+ public TestProjectViewModel(
+ IProjectService projectService,
+ IDialogService dialogService,
+ ISaveFileDialogViewModel saveModel,
+ IOpenFileDialogViewModel openModel,
+ IStatusService statusService)
+ : base(projectService, dialogService, statusService)
{
_saveDialogModel = saveModel;
_openDialogModel = openModel;
View
47 Rhino.Licensing.AdminTool.Tests/ViewModels/ShellViewModelTests.cs
@@ -13,17 +13,21 @@ namespace Rhino.Licensing.AdminTool.Tests.ViewModels
{
public class ShellViewModelTests : TestBase
{
- private readonly IViewModelFactory _viewModelFactory;
+ private readonly IViewModelFactory _viewModelFactory;
private readonly IWindowManager _windowManager;
private readonly IProjectService _projectService;
- private readonly IDialogService _dialogService;
+ private readonly IDialogService _dialogService;
+ private readonly IStatusService _statusService;
+ private readonly ProjectViewModel _projectViewModel;
public ShellViewModelTests()
{
_viewModelFactory = MockRepository.GenerateMock<IViewModelFactory>();
_windowManager = MockRepository.GenerateMock<IWindowManager>();
_projectService = MockRepository.GenerateMock<IProjectService>();
- _dialogService = MockRepository.GenerateMock<IDialogService>();
+ _dialogService = MockRepository.GenerateMock<IDialogService>();
+ _statusService = MockRepository.GenerateMock<IStatusService>();
+ _projectViewModel = MockRepository.GenerateMock<ProjectViewModel>(_projectService, _dialogService, _statusService);
}
[Fact]
@@ -33,9 +37,10 @@ public void Shell_Has_Correct_Binding()
.Validate();
validator.AssertNoErrors();
- validator.AssertWasBound(x => x.DisplayName);
- }
-
+ validator.AssertWasBound(x => x.DisplayName);
+ validator.AssertWasBound(x => x.StatusMessage);
+ }
+
[Fact]
public void ShowAbout_Action_Displays_Dialog()
{
@@ -64,30 +69,42 @@ public void CreateNewProject_Opens_ProjectViewModel()
}
[Fact]
- public void OpenProject_Opens_ProjectViewModel()
+ public void OpenProject_Opens_ProjectViewModel_When_User_Accepts_The_Open_Dialog()
{
var shell = CreateShellViewModel();
- var projectViewModel = MockRepository.GenerateMock<ProjectViewModel>(_projectService, _dialogService);
-
- _viewModelFactory.Expect(x => x.Create<ProjectViewModel>()).Return(projectViewModel);
+
+ _projectViewModel.Expect(x => x.Open()).Return(true);
+ _viewModelFactory.Expect(x => x.Create<ProjectViewModel>()).Return(_projectViewModel);
shell.OpenProject();
Assert.NotNull(shell.ActiveItem);
- Assert.Same(projectViewModel, shell.ActiveItem);
+ Assert.Same(_projectViewModel, shell.ActiveItem);
+ }
+
+ [Fact]
+ public void OpenProject_Wont_Show_ProjectViewModel_When_User_Cancels_The_Open_Dialog()
+ {
+ var shell = CreateShellViewModel();
+
+ _projectViewModel.Expect(x => x.Open()).Return(false);
+ _viewModelFactory.Expect(x => x.Create<ProjectViewModel>()).Return(_projectViewModel);
+
+ shell.OpenProject();
+
+ Assert.Null(shell.ActiveItem);
}
[Fact]
public void OpenProject_Calls_Open_On_ProjectViewModel()
{
var shell = CreateShellViewModel();
- var projectViewModel = MockRepository.GenerateMock<ProjectViewModel>(_projectService, _dialogService);
- _viewModelFactory.Expect(x => x.Create<ProjectViewModel>()).Return(projectViewModel);
+ _viewModelFactory.Expect(x => x.Create<ProjectViewModel>()).Return(_projectViewModel);
shell.OpenProject();
- projectViewModel.AssertWasCalled(x => x.Open(), options => options.Repeat.Once());
+ _projectViewModel.AssertWasCalled(x => x.Open(), options => options.Repeat.Once());
}
[Fact]
@@ -105,7 +122,7 @@ public void Opening_New_Screen_Will_Destroy_Previous()
private ProjectViewModel CreateProjectViewModel()
{
- return new ProjectViewModel(_projectService, _dialogService);
+ return new ProjectViewModel(_projectService, _dialogService, _statusService);
}
private ShellViewModel CreateShellViewModel()
View
1 Rhino.Licensing.AdminTool/App.xaml
@@ -8,6 +8,7 @@
<ResourceDictionary Source="pack://application:,,,/Rhino.Licensing.AdminTool;component/Theme/ExpressionDark.xaml" />
<ResourceDictionary Source="pack://application:,,,/Rhino.Licensing.AdminTool;component/Theme/AppStyles.xaml" />
<ResourceDictionary Source="pack://application:,,,/Rhino.Licensing.AdminTool;component/Theme/Animations.xaml" />
+ <ResourceDictionary Source="pack://application:,,,/Rhino.Licensing.AdminTool;component/Theme/DataTemplates.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
View
47 Rhino.Licensing.AdminTool/Model/License.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Runtime.Serialization;
+using Caliburn.PresentationFramework;
+
+namespace Rhino.Licensing.AdminTool.Model
+{
+ [DataContract(Name = "License", Namespace = "http://schemas.hibernatingrhinos.com/")]
+ public class License : PropertyChangedBase
+ {
+ private string _ownerName;
+ private DateTime? _expirationDate;
+ private LicenseType _licenseType;
+
+ [DataMember]
+ public virtual string OwnerName
+ {
+ get { return _ownerName; }
+ set
+ {
+ _ownerName = value;
+ NotifyOfPropertyChange(() => OwnerName);
+ }
+ }
+
+ [DataMember]
+ public virtual DateTime? ExpirationDate
+ {
+ get { return _expirationDate; }
+ set
+ {
+ _expirationDate = value;
+ NotifyOfPropertyChange(() => ExpirationDate);
+ }
+ }
+
+ [DataMember]
+ public virtual LicenseType LicenseType
+ {
+ get { return _licenseType; }
+ set
+ {
+ _licenseType = value;
+ NotifyOfPropertyChange(() => LicenseType);
+ }
+ }
+ }
+}
View
140 Rhino.Licensing.AdminTool/Model/Product.cs
@@ -1,64 +1,78 @@
-using System;
-using System.Runtime.Serialization;
-using Caliburn.PresentationFramework;
-
-namespace Rhino.Licensing.AdminTool.Model
-{
- [DataContract(Name = "Product", Namespace = "http://schemas.hibernatingrhinos.com/")]
- public class Product : PropertyChangedBase
- {
- private string _publicKey;
- private string _name;
- private string _privateKey;
- private Guid _id;
-
- public Product()
- {
- Id = Guid.NewGuid();
- }
-
- [DataMember]
- public virtual Guid Id
- {
- get { return _id; }
- set
- {
- _id = value;
- NotifyOfPropertyChange(() => Id);
- }
- }
-
- [DataMember]
- public virtual string Name
- {
- get { return _name; }
- set
- {
- _name = value;
- NotifyOfPropertyChange(() => Name);
- }
- }
-
- [DataMember]
- public virtual string PrivateKey
- {
- get { return _privateKey; }
- set
- {
- _privateKey = value;
- NotifyOfPropertyChange(() => PrivateKey);
- }
- }
-
- [DataMember]
- public virtual string PublicKey
- {
- get { return _publicKey; }
- set
- {
- _publicKey = value;
- NotifyOfPropertyChange(() => PublicKey);
- }
- }
- }
+using System;
+using System.Collections.ObjectModel;
+using System.Runtime.Serialization;
+using Caliburn.PresentationFramework;
+
+namespace Rhino.Licensing.AdminTool.Model
+{
+ [DataContract(Name = "Product", Namespace = "http://schemas.hibernatingrhinos.com/")]
+ public class Product : PropertyChangedBase
+ {
+ private string _publicKey;
+ private string _name;
+ private string _privateKey;
+ private Guid _id;
+ private ObservableCollection<License> _issuedLicenses;
+
+ public Product()
+ {
+ _id = Guid.NewGuid();
+ _issuedLicenses = new ObservableCollection<License>();
+ }
+
+ [DataMember]
+ public virtual Guid Id
+ {
+ get { return _id; }
+ set
+ {
+ _id = value;
+ NotifyOfPropertyChange(() => Id);
+ }
+ }
+
+ [DataMember]
+ public virtual string Name
+ {
+ get { return _name; }
+ set
+ {
+ _name = value;
+ NotifyOfPropertyChange(() => Name);
+ }
+ }
+
+ [DataMember]
+ public virtual string PrivateKey
+ {
+ get { return _privateKey; }
+ set
+ {
+ _privateKey = value;
+ NotifyOfPropertyChange(() => PrivateKey);
+ }
+ }
+
+ [DataMember]
+ public virtual string PublicKey
+ {
+ get { return _publicKey; }
+ set
+ {
+ _publicKey = value;
+ NotifyOfPropertyChange(() => PublicKey);
+ }
+ }
+
+ [DataMember]
+ public virtual ObservableCollection<License> IssuedLicenses
+ {
+ get { return _issuedLicenses; }
+ private set
+ {
+ _issuedLicenses = value;
+ NotifyOfPropertyChange(() => IssuedLicenses);
+ }
+ }
+ }
}
View
2 Rhino.Licensing.AdminTool/Model/Project.cs
@@ -11,7 +11,7 @@ public class Project : PropertyChangedBase
public Project()
{
- Product = new Product();
+ _product = new Product();
}
[DataMember]
View
12 Rhino.Licensing.AdminTool/Rhino.Licensing.AdminTool.csproj
@@ -123,9 +123,11 @@
<Compile Include="Extensions\StringExtensions.cs" />
<Compile Include="Factories\IDialogFactory.cs" />
<Compile Include="Factories\IViewModelFactory.cs" />
+ <Compile Include="Model\License.cs" />
<Compile Include="Model\Product.cs" />
<Compile Include="Model\Project.cs" />
<Compile Include="Services\DialogService.cs" />
+ <Compile Include="Services\StatusService.cs" />
<Compile Include="Services\ProjectService.cs" />
<Compile Include="Startup\FactoryRegistration.cs" />
<Compile Include="Startup\GuyWire.cs" />
@@ -164,6 +166,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="Theme\DataTemplates.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
<Page Include="Theme\ExpressionDark.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -215,6 +221,12 @@
<Resource Include="Images\Copy.png" />
<Resource Include="Images\Paste.png" />
</ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Rhino.Licensing\Rhino.Licensing.csproj">
+ <Project>{05EFD7EB-F0FB-4B65-8E4A-C8FF8DDC6A78}</Project>
+ <Name>Rhino.Licensing</Name>
+ </ProjectReference>
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
View
24 Rhino.Licensing.AdminTool/Services/ProjectService.cs
@@ -1,3 +1,4 @@
+using System;
using System.IO;
using System.Runtime.Serialization;
using Rhino.Licensing.AdminTool.Model;
@@ -62,10 +63,27 @@ public Project Create()
public Project Open(FileInfo path)
{
- var reader = path.OpenRead();
- var serializer = new DataContractSerializer(typeof(Project));
+ Project project = null;
+ FileStream reader = null;
- return serializer.ReadObject(reader) as Project;
+ try
+ {
+ reader = new FileStream(path.FullName, FileMode.Open, FileAccess.Read);
+
+ var serializer = new DataContractSerializer(typeof (Project));
+
+ project = serializer.ReadObject(reader) as Project;
+ }
+ finally
+ {
+ if (reader != null)
+ {
+ reader.Close();
+ reader.Dispose();
+ }
+ }
+
+ return project;
}
}
}
View
18 Rhino.Licensing.AdminTool/Services/StatusService.cs
@@ -0,0 +1,18 @@
+namespace Rhino.Licensing.AdminTool.Services
+{
+ public interface IStatusService
+ {
+ /// <summary>
+ /// Shows a status message on status bar
+ /// </summary>
+ /// <param name="message"></param>
+ void Update(string message);
+
+ /// <summary>
+ /// Shows a status message on status bar
+ /// </summary>
+ /// <param name="message"></param>
+ /// <param name="args"></param>
+ void Update(string message, params object[] args);
+ }
+}
View
23 Rhino.Licensing.AdminTool/Startup/ViewModelRegistration.cs
@@ -1,7 +1,9 @@
+using System;
using System.Collections.Generic;
using Castle.MicroKernel;
using Castle.MicroKernel.Registration;
-using Rhino.Licensing.AdminTool.Extensions;
+using Rhino.Licensing.AdminTool.Extensions;
+using Rhino.Licensing.AdminTool.Services;
using Rhino.Licensing.AdminTool.ViewModels;
using System.Linq;
@@ -12,10 +14,15 @@ public class ViewModelRegistration : IRegistration
public virtual void Register(IKernel kernel)
{
kernel.Register(AllTypes.FromAssemblyContaining<ViewModelRegistration>()
- .Where(t => ViewModelNamespaces.Contains(t.Namespace))
+ .Where(t => ViewModelNamespaces.Contains(t.Namespace) &&
+ !SkipAutoRegistration.Contains(t))
.WithService.FirstInterfaceOnClass()
- .Configure(c => c.LifeStyle.Transient)
- .ConfigureFor<IShellViewModel>(c => c.LifeStyle.Singleton));
+ .Configure(c => c.LifeStyle.Transient));
+
+ kernel.Register(Component.For<IShellViewModel>()
+ .ImplementedBy<ShellViewModel>()
+ .Forward<IStatusService>()
+ .LifeStyle.Singleton);
}
private static IEnumerable<string> ViewModelNamespaces
@@ -26,5 +33,13 @@ private static IEnumerable<string> ViewModelNamespaces
yield return "Rhino.Licensing.AdminTool.Dialogs";
}
}
+
+ private static IEnumerable<Type> SkipAutoRegistration
+ {
+ get
+ {
+ yield return typeof (ShellViewModel);
+ }
+ }
}
}
View
2 Rhino.Licensing.AdminTool/Startup/ViewRegistration.cs
@@ -1,6 +1,6 @@
using Castle.MicroKernel;
using Castle.MicroKernel.Registration;
-using Rhino.Licensing.AdminTool.Extensions;
+using Rhino.Licensing.AdminTool.Extensions;
using Rhino.Licensing.AdminTool.Views;
namespace Rhino.Licensing.AdminTool.Startup
View
12 Rhino.Licensing.AdminTool/Theme/DataTemplates.xaml
@@ -0,0 +1,12 @@
+<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+
+ <DataTemplate x:Key="IssuedLicenseTemplate">
+ <StackPanel Orientation="Horizontal">
+ <TextBlock Text="{Binding OwnerName}" Margin="2" />
+ <TextBlock Text="{Binding ExpirationDate}" Margin="2" />
+ <TextBlock Text="{Binding LicenseType}" Margin="2" />
+ </StackPanel>
+ </DataTemplate>
+
+</ResourceDictionary>
View
7 Rhino.Licensing.AdminTool/Theme/ExpressionDark.xaml
@@ -1536,10 +1536,15 @@
</Style>
<!--StatusBar-->
- <Style x:Key="{x:Type StatusBar}" TargetType="{x:Type StatusBar}">
+ <Style TargetType="{x:Type StatusBar}">
<Setter Property="Background" Value="{DynamicResource RecessedBrush}" />
<Setter Property="Foreground" Value="{DynamicResource Text1Brush}" />
</Style>
+
+ <!--StatusBarItem-->
+ <Style TargetType="{x:Type StatusBarItem}">
+ <Setter Property="Foreground" Value="{DynamicResource Text1Brush}" />
+ </Style>
<!--ToolTip-->
<Style x:Key="{x:Type ToolTip}" TargetType="{x:Type ToolTip}">
View
41 Rhino.Licensing.AdminTool/ViewModels/ProjectViewModel.cs
@@ -16,14 +16,17 @@ public class ProjectViewModel : Screen
private readonly IProjectService _projectService;
private readonly IDialogService _dialogService;
+ private readonly IStatusService _statusService;
private string _filePath;
public ProjectViewModel(
IProjectService projectService,
- IDialogService dialogService)
+ IDialogService dialogService,
+ IStatusService statusService)
{
_projectService = projectService;
_dialogService = dialogService;
+ _statusService = statusService;
}
public virtual Project CurrentProject
@@ -33,6 +36,15 @@ public virtual Project CurrentProject
{
_project = value;
NotifyOfPropertyChange(() => CurrentProject);
+ OnCurrentProjectChanged();
+ }
+ }
+
+ protected virtual void OnCurrentProjectChanged()
+ {
+ if(_project != null)
+ {
+ _statusService.Update("Loaded {0} license(s).", _project.Product.IssuedLicenses.Count);
}
}
@@ -46,7 +58,8 @@ public virtual void GenerateKey()
public virtual bool CanSave()
{
- return CurrentProject.Product != null &&
+ return CurrentProject != null &&
+ CurrentProject.Product != null &&
CurrentProject.Product.Name.IsNotEmpty();
}
@@ -71,7 +84,7 @@ public virtual void Save()
}
[AutoCheckAvailability]
- public virtual void Open()
+ public virtual bool Open()
{
var model = CreateOpenDialogModel();
@@ -81,7 +94,29 @@ public virtual void Open()
{
_filePath = model.FileName;
CurrentProject = _projectService.Open(new FileInfo(_filePath));
+
+ return true;
}
+
+ return false;
+ }
+
+ [AutoCheckAvailability]
+ public virtual void AddLicense()
+ {
+ CurrentProject.Product.IssuedLicenses.Add(new License
+ {
+ ExpirationDate = DateTime.Now.AddDays(30),
+ LicenseType = LicenseType.Trial,
+ OwnerName = "John Doe"
+ });
+ }
+
+ public bool CanAddLicense()
+ {
+ return CurrentProject != null &&
+ CurrentProject.Product.PublicKey.IsNotEmpty() &&
+ CurrentProject.Product.PrivateKey.IsNotEmpty();
}
public virtual IOpenFileDialogViewModel CreateOpenDialogModel()
View
34 Rhino.Licensing.AdminTool/ViewModels/ShellViewModel.cs
@@ -17,20 +17,27 @@ public interface IShellViewModel : IConductor
/// create a new project
/// </summary>
void CreateNewProject();
+
+ /// <summary>
+ /// Sets the status message on shell
+ /// </summary>
+ string StatusMessage { get; set; }
}
- public class ShellViewModel : Conductor<Screen>, IShellViewModel
+ public class ShellViewModel : Conductor<Screen>, IShellViewModel, IStatusService
{
private readonly IViewModelFactory _viewModelFactory;
private readonly IProjectService _projectService;
private readonly IWindowManager _windowManager;
+ private string _statusMessage;
public ShellViewModel(
IWindowManager windowManager,
IViewModelFactory viewModelFactory,
IProjectService projectService)
{
DisplayName = "Rhino.Licensing.AdminTool";
+ StatusMessage = "Ready.";
_windowManager = windowManager;
_viewModelFactory = viewModelFactory;
@@ -67,9 +74,30 @@ public virtual void OpenProject()
{
var vm = _viewModelFactory.Create<ProjectViewModel>();
- vm.Open();
+ if (vm.Open())
+ {
+ ActiveItem = vm;
+ }
+ }
- ActiveItem = vm;
+ public virtual string StatusMessage
+ {
+ get { return _statusMessage; }
+ set
+ {
+ _statusMessage = value;
+ NotifyOfPropertyChange(() => StatusMessage);
+ }
+ }
+
+ public virtual void Update(string message)
+ {
+ StatusMessage = message;
+ }
+
+ public virtual void Update(string message, params object[] args)
+ {
+ Update(string.Format(message, args));
}
}
}
View
76 Rhino.Licensing.AdminTool/Views/ProjectView.xaml
@@ -27,43 +27,59 @@
<Image Source="/Images/GenerateKey.png" Width="32" Height="32" Style="{DynamicResource ToolbarImageStyle}"/>
</Button>
+ <Button cal:Message.Attach="[Event Click]=[Action AddLicense]" ToolTip="Add License" Margin="2">
+ <Image Source="/Images/NewLicense.png" Width="32" Height="32" Style="{DynamicResource ToolbarImageStyle}"/>
+ </Button>
+
</ToolBarPanel>
- <GroupBox Header="Product Information">
- <Grid>
- <Grid.RowDefinitions>
- <RowDefinition Height="Auto"/>
- <RowDefinition Height="Auto"/>
- <RowDefinition Height="Auto"/>
- </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="Auto"/>
- <ColumnDefinition Width="*"/>
- </Grid.ColumnDefinitions>
+ <Grid>
+
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="*"/>
+ </Grid.RowDefinitions>
+
+ <GroupBox Header="Product Information" Grid.Row="0">
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="Auto"/>
+ <ColumnDefinition Width="*"/>
+ </Grid.ColumnDefinitions>
- <Label Content="Name: " Grid.Column="0" Grid.Row="0" />
- <Label Content="Public Key: " Grid.Column="0" Grid.Row="1"/>
- <Label Content="Private Key: " Grid.Column="0" Grid.Row="2"/>
+ <Label Content="Name: " Grid.Column="0" Grid.Row="0" />
+ <Label Content="Public Key: " Grid.Column="0" Grid.Row="1"/>
+ <Label Content="Private Key: " Grid.Column="0" Grid.Row="2"/>
- <TextBox Text="{Binding Path=CurrentProject.Product.Name}"
- Grid.Column="1" Grid.Row="0" />
+ <TextBox Text="{Binding Path=CurrentProject.Product.Name}"
+ Grid.Column="1" Grid.Row="0" />
- <DockPanel Grid.Column="1" Grid.Row="1">
- <Button DockPanel.Dock="Right" Margin="2" Height="20" Width="20" cal:Message.Attach="[Event Click]=[Action CopyToClipboard(publicKey.Text)]">
- <Image Source="/Images/Copy.png" />
- </Button>
- <TextBox x:Name="publicKey" Text="{Binding Path=CurrentProject.Product.PublicKey}" IsReadOnly="True" />
- </DockPanel>
+ <DockPanel Grid.Column="1" Grid.Row="1">
+ <Button DockPanel.Dock="Right" Margin="2" Height="20" Width="20" cal:Message.Attach="[Event Click]=[Action CopyToClipboard(publicKey.Text)]">
+ <Image Source="/Images/Copy.png" />
+ </Button>
+ <TextBox x:Name="publicKey" Text="{Binding Path=CurrentProject.Product.PublicKey}" IsReadOnly="True" />
+ </DockPanel>
- <DockPanel Grid.Column="1" Grid.Row="2">
- <Button DockPanel.Dock="Right" Margin="2" Height="20" Width="20" cal:Message.Attach="[Event Click]=[Action CopyToClipboard(privateKey.Text)]">
- <Image Source="/Images/Copy.png" />
- </Button>
- <TextBox x:Name="privateKey" Text="{Binding Path=CurrentProject.Product.PrivateKey}" IsReadOnly="True" />
- </DockPanel>
- </Grid>
- </GroupBox>
+ <DockPanel Grid.Column="1" Grid.Row="2">
+ <Button DockPanel.Dock="Right" Margin="2" Height="20" Width="20" cal:Message.Attach="[Event Click]=[Action CopyToClipboard(privateKey.Text)]">
+ <Image Source="/Images/Copy.png" />
+ </Button>
+ <TextBox x:Name="privateKey" Text="{Binding Path=CurrentProject.Product.PrivateKey}" IsReadOnly="True" />
+ </DockPanel>
+ </Grid>
+ </GroupBox>
+ <GroupBox Header="Issued Licenses" Grid.Row="1">
+ <ListBox ItemsSource="{Binding CurrentProject.Product.IssuedLicenses}"
+ ItemTemplate="{DynamicResource IssuedLicenseTemplate}" />
+ </GroupBox>
+ </Grid>
</DockPanel>
</UserControl>
View
6 Rhino.Licensing.AdminTool/Views/ShellView.xaml
@@ -26,9 +26,13 @@
</Menu.Items>
</Menu>
+ <StatusBar DockPanel.Dock="Bottom" Height="22">
+ <StatusBarItem Content="{Binding Path=StatusMessage, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
+ </StatusBar>
+
<lib:TransitionPresenter Transition="{StaticResource ContentSwitchAnimation}"
cal:View.Model="{Binding ActiveItem}" />
-
+
</DockPanel>
</Window>

0 comments on commit 68dbd5e

Please sign in to comment.