Improved resource manager, plugin manager

This commit is contained in:
2014-08-14 10:06:20 +03:00
parent dc7eff73b4
commit 03d9848b50
37 changed files with 1071 additions and 89 deletions

View File

@ -47,6 +47,11 @@ namespace RainmeterStudio.Business
/// </summary>
public IEnumerable<IDocumentStorage> Storages { get { return _storages; } }
/// <summary>
/// Gets a list of document templates
/// </summary>
public IEnumerable<DocumentTemplate> DocumentTemplates { get { return _templates; } }
#endregion
#region Private fields

View File

@ -4,10 +4,12 @@ using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Text;
using RainmeterStudio.Core;
using RainmeterStudio.Core.Documents;
using RainmeterStudio.Core.Utils;
using RainmeterStudio.Resources;
namespace RainmeterStudio.Business
{
@ -16,31 +18,84 @@ namespace RainmeterStudio.Business
/// </summary>
public class PluginManager
{
public delegate void RegisterMethod(object objectToRegister);
#region Private fields
List<Assembly> _loadedPlugins = new List<Assembly>();
Dictionary<Type, RegisterMethod> _registerTypes = new Dictionary<Type,RegisterMethod>();
Dictionary<Type, RegisterExportHandler> _registerExportTypes = new Dictionary<Type, RegisterExportHandler>();
#endregion
/// <summary>
/// Gets an enumerable of the loaded plugins
/// </summary>
public IEnumerable<Assembly> LoadedPlugins
{
get
{
return _loadedPlugins;
}
}
/// <summary>
/// A method which registers an object that was exported by a plugin.
/// </summary>
/// <param name="objectToRegister">Object to register</param>
public delegate void RegisterExportHandler(object objectToRegister);
#region Constructor
/// <summary>
/// Initializes the plugin manager
/// </summary>
public PluginManager()
{
}
public void AddRegisterType(Type interfaceType, RegisterMethod method)
#endregion
/// <summary>
/// Adds a handler that registers exported objects of a specific type.
/// </summary>
/// <param name="interfaceType">The data type</param>
/// <param name="method">Handler that does the registring</param>
public void AddRegisterExportTypeHandler(Type interfaceType, RegisterExportHandler method)
{
_registerTypes.Add(interfaceType, method);
_registerExportTypes.Add(interfaceType, method);
}
public void LoadPlugins()
/// <summary>
/// Initializes the plugin manager
/// </summary>
/// <remarks>This will load all the plugins from the "StudioPlugins" folder</remarks>
public void Initialize()
{
// Get "Plugins" folder path
var location = Assembly.GetExecutingAssembly().Location;
var pluginsPath = Path.Combine(Path.GetDirectoryName(location), "Plugins");
// Initialize the executing assembly
InitializePlugin(Assembly.GetExecutingAssembly());
// Load plugins from StudioPlugins folder
var location = Assembly.GetExecutingAssembly().Location;
var pluginsPath = Path.Combine(Path.GetDirectoryName(location), "StudioPlugins");
LoadPlugins(pluginsPath);
}
/// <summary>
/// Loads all the plugins from the specified directory.
/// </summary>
/// <param name="pluginsPath">Directory path</param>
public void LoadPlugins(string pluginsPath)
{
// Load all DLLs from "Plugins" folder
foreach (var file in Directory.EnumerateFiles(pluginsPath, "*.dll"))
LoadPlugin(file);
}
/// <summary>
/// Tries to load the plugin.
/// </summary>
/// <param name="file">File name</param>
/// <remarks>If plugin is not loaded, the function fails silently.</remarks>
public void LoadPlugin(string file)
{
Assembly assembly = null;
@ -58,17 +113,19 @@ namespace RainmeterStudio.Business
// Loaded, do initialization stuff
if (assembly != null)
{
_loadedPlugins.Add(assembly);
Initialize(assembly);
Debug.WriteLine("Loaded plugin: {0}", assembly.FullName);
// Check for the RainmeterStudioPlugin attribute
if (assembly.GetCustomAttributes(typeof(RainmeterStudioPluginAttribute), false).Count() > 0)
{
_loadedPlugins.Add(assembly);
InitializePlugin(assembly);
Debug.WriteLine("Loaded plugin: {0}", (object)assembly.Location);
}
}
}
private void Initialize(Assembly assembly)
private void InitializePlugin(Assembly assembly)
{
// Register factories and stuff
// Register exports
assembly.GetTypes()
// Select only the classes
@ -80,7 +137,7 @@ namespace RainmeterStudio.Business
// Perform register
.ForEach((type) =>
{
foreach (var pair in _registerTypes)
foreach (var pair in _registerExportTypes)
{
if (pair.Key.IsAssignableFrom(type))
{
@ -91,13 +148,13 @@ namespace RainmeterStudio.Business
}
}
});
}
public IEnumerable<Assembly> LoadedPlugins
{
get
// Register .resource files
foreach (var resourceName in assembly.GetManifestResourceNames())
{
return _loadedPlugins;
var name = Path.GetFileNameWithoutExtension(resourceName);
ResourceManager manager = new ResourceManager(name, assembly);
ResourceProvider.RegisterManager(manager, assembly);
}
}
}

View File

@ -31,10 +31,10 @@ namespace RainmeterStudio
// Initialize plugin manager
PluginManager pluginManager = new PluginManager();
pluginManager.AddRegisterType(typeof(IDocumentStorage), obj => documentManager.RegisterStorage((IDocumentStorage)obj));
pluginManager.AddRegisterType(typeof(DocumentTemplate), obj => documentManager.RegisterTemplate((DocumentTemplate)obj));
pluginManager.AddRegisterType(typeof(IDocumentEditorFactory), obj => documentManager.RegisterEditorFactory((IDocumentEditorFactory)obj));
pluginManager.LoadPlugins();
pluginManager.AddRegisterExportTypeHandler(typeof(IDocumentStorage), obj => documentManager.RegisterStorage((IDocumentStorage)obj));
pluginManager.AddRegisterExportTypeHandler(typeof(DocumentTemplate), obj => documentManager.RegisterTemplate((DocumentTemplate)obj));
pluginManager.AddRegisterExportTypeHandler(typeof(IDocumentEditorFactory), obj => documentManager.RegisterEditorFactory((IDocumentEditorFactory)obj));
pluginManager.Initialize();
// Create & run app
var uiManager = new UIManager(projectManager, documentManager);

View File

@ -1,11 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace RainmeterStudio.Rainmeter.DataTypes
{
public class Action
{
}
}

View File

@ -1,63 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace RainmeterStudio.Rainmeter.DataTypes
{
public abstract class Bang
{
/// <summary>
/// Argument info
/// </summary>
public class ArgumentInfo
{
public string Name { get; set; }
public Type DataType { get; set; }
public ArgumentInfo(string name, Type dataType)
{
Name = name;
DataType = dataType;
}
}
/// <summary>
/// Gets the function name of the bang
/// </summary>
public abstract string FunctionName { get; }
/// <summary>
/// Gets the list of arguments
/// </summary>
public abstract IEnumerable<ArgumentInfo> Arguments { get; }
/// <summary>
/// Executes the bang
/// </summary>
public void Execute(params object[] args)
{
}
/// <summary>
/// Gets the string representation of this bang
/// </summary>
/// <returns>String representation</returns>
public override string ToString()
{
StringBuilder builder = new StringBuilder();
builder.AppendFormat("!{0}", FunctionName);
foreach (var arg in Arguments.Select(x => x.ToString()))
{
if (arg.Any(Char.IsWhiteSpace))
builder.AppendFormat(@" ""{0}""", arg);
else builder.AppendFormat(" {0}", arg);
}
return builder.ToString();
}
}
}

View File

@ -1,67 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace RainmeterStudio.Rainmeter
{
/// <summary>
/// Represents a group
/// </summary>
/// <remarks>
/// Skins, meters, and measures can be categorized into groups to allow
/// easier control with group bangs. For example, the !HideMeterGroup
/// bang may be used to hide multiple meters in a single bang (compared
/// to !HideMeter statements for each meter).
/// </remarks>
public abstract class Group
{
#region Imports
[DllImport("Rainmeter.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern bool Group_BelongsToGroup(out bool result, Int32 handle, string group);
[DllImport("Rainmeter.dll", CallingConvention = CallingConvention.Cdecl)]
private static extern bool Group_Destroy(Int32 handle);
#endregion
/// <summary>
/// Gets or sets the associated handle of this object
/// </summary>
protected Int32 Handle { get; private set; }
/// <summary>
/// Tests if belongs to a group
/// </summary>
/// <param name="group">Group name</param>
/// <returns>True if belongs</returns>
public bool BelongsToGroup(string group)
{
bool result;
if (!Group_BelongsToGroup(out result, Handle, group))
throw new ExternalException("Belongs to group failed.");
return result;
}
/// <summary>
/// Initializes this group
/// </summary>
/// <param name="handle">The handle</param>
protected Group(Int32 handle)
{
Handle = handle;
}
/// <summary>
/// Finalizer
/// </summary>
~Group()
{
Group_Destroy(Handle);
}
}
}

View File

@ -1,11 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace RainmeterStudio.Rainmeter
{
public class Measure
{
}
}

View File

@ -1,15 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace RainmeterStudio.Rainmeter
{
public abstract class Meter : Group
{
public Meter(int handle)
: base(handle)
{
}
}
}

View File

@ -1,174 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace RainmeterStudio.Rainmeter
{
public abstract class Section : Group
{
#region Imports
[DllImport("Rainmeter.dll", CallingConvention = CallingConvention.Cdecl)]
static extern bool Section_GetName(out string result, Int32 handle);
[DllImport("Rainmeter.dll", CallingConvention = CallingConvention.Cdecl)]
static extern bool Section_GetOriginalName(out string result, Int32 handle);
[DllImport("Rainmeter.dll", CallingConvention = CallingConvention.Cdecl)]
static extern bool Section_HasDynamicVariables(out bool result, Int32 handle);
[DllImport("Rainmeter.dll", CallingConvention = CallingConvention.Cdecl)]
static extern bool Section_SetDynamicVariables(Int32 handle, bool value);
[DllImport("Rainmeter.dll", CallingConvention = CallingConvention.Cdecl)]
static extern bool Section_ResetUpdateCounter(Int32 handle);
[DllImport("Rainmeter.dll", CallingConvention = CallingConvention.Cdecl)]
static extern bool Section_GetUpdateCounter(out int result, Int32 handle);
[DllImport("Rainmeter.dll", CallingConvention = CallingConvention.Cdecl)]
static extern bool Section_GetUpdateDivider(out int result, Int32 handle);
[DllImport("Rainmeter.dll", CallingConvention = CallingConvention.Cdecl)]
static extern bool Section_GetOnUpdateAction(out string result, Int32 handle);
[DllImport("Rainmeter.dll", CallingConvention = CallingConvention.Cdecl)]
static extern bool Section_DoUpdateAction(Int32 handle);
[DllImport("Rainmeter.dll", CallingConvention = CallingConvention.Cdecl)]
static extern bool Section_Destroy(Int32 handle);
#endregion
protected Section(Int32 handle)
: base(handle)
{
}
~Section()
{
Section_Destroy(Handle);
}
/// <summary>
/// Gets the name of the section
/// </summary>
public string Name
{
get
{
string name;
if (!Section_GetName(out name, Handle))
throw new ExternalException("Get name failed.");
return name;
}
}
/// <summary>
/// Gets the original name of the section
/// </summary>
public string OriginalName
{
get
{
string name;
if (!Section_GetOriginalName(out name, Handle))
throw new ExternalException("Get original name failed.");
return name;
}
}
/// <summary>
/// Gets a value indicating if this section has dynamic variables
/// </summary>
public bool HasDynamicVariables
{
get
{
bool result;
if (!Section_HasDynamicVariables(out result, Handle))
throw new ExternalException("Get dynamic variables has failed.");
return result;
}
set
{
if (!Section_SetDynamicVariables(Handle, value))
throw new ExternalException("Set dynamic variables has failed.");
}
}
/// <summary>
/// Resets the update counter
/// </summary>
public void ResetUpdateCounter()
{
if (!Section_ResetUpdateCounter(Handle))
throw new ExternalException("Reset update counter has failed.");
}
/// <summary>
/// Gets the update counter
/// </summary>
public int UpdateCounter
{
get
{
int result;
if (!Section_GetUpdateCounter(out result, Handle))
throw new ExternalException("Get update counter has failed.");
return result;
}
}
/// <summary>
/// Gets the update divider
/// </summary>
public int UpdateDivider
{
get
{
int result;
if (!Section_GetUpdateDivider(out result, Handle))
throw new ExternalException("Get update divider has failed.");
return result;
}
}
/// <summary>
/// Gets the update divider
/// </summary>
public string OnUpdateAction
{
get
{
string result;
if (!Section_GetOnUpdateAction(out result, Handle))
throw new ExternalException("Get on update action has failed.");
return result;
}
}
/// <summary>
/// Executes the update action
/// </summary>
public void DoUpdateAction()
{
if (!Section_DoUpdateAction(Handle))
throw new ExternalException("Do update action has failed.");
}
}
}

View File

@ -8,7 +8,7 @@
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>RainmeterStudio</RootNamespace>
<AssemblyName>RainmeterEditor</AssemblyName>
<AssemblyName>RainmeterStudio</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
@ -73,17 +73,12 @@
<Compile Include="MainClass.cs" />
<Compile Include="Interop\NativeLibrary.cs" />
<Compile Include="Rainmeter.cs" />
<Compile Include="Rainmeter\DataTypes\Action.cs" />
<Compile Include="Rainmeter\DataTypes\Bang.cs" />
<Compile Include="Rainmeter\Group.cs" />
<Compile Include="Rainmeter\Measure.cs" />
<Compile Include="Rainmeter\Meter.cs" />
<Compile Include="Rainmeter\Section.cs" />
<Compile Include="Resources\Icons.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Icons.resx</DependentUpon>
</Compile>
<Compile Include="Resources\ResourceProvider.cs" />
<Compile Include="Resources\Strings.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>

View File

@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Resources;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace RainmeterStudio.Resources
{
/// <summary>
/// Manages and provides resources
/// </summary>
public static class ResourceProvider
{
/// <summary>
/// Holds information about a resource manager
/// </summary>
private struct ResourceManagerInfo
{
public ResourceManager Manager;
public Assembly Assembly;
}
private static List<ResourceManagerInfo> _resourceManagers = new List<ResourceManagerInfo>();
private static Dictionary<string, string> _cacheStrings = new Dictionary<string, string>();
private static Dictionary<string, ImageSource> _cacheImages = new Dictionary<string, ImageSource>();
/// <summary>
/// Registers a resource manager
/// </summary>
/// <param name="manager">The resource manager</param>
/// <param name="ownerAssembly">The assembly which will contain the non-string resources</param>
public static void RegisterManager(ResourceManager manager, Assembly ownerAssembly)
{
_resourceManagers.Add(new ResourceManagerInfo()
{
Manager = manager,
Assembly = ownerAssembly
});
}
/// <summary>
/// Gets a string from the resource managers
/// </summary>
/// <param name="key">Identifier of the resource</param>
/// <param name="bypassCache">By default, strings are cached. Setting this to true will bypass the cache.</param>
/// <param name="keepInCache">If this parameter is set to true, the obtained string will be cached.</param>
/// <returns>The string, or null if not found</returns>
public static string GetString(string key, bool bypassCache = false, bool keepInCache = true)
{
string value = null;
// Look up in cache
if (bypassCache || !_cacheStrings.TryGetValue(key, out value))
{
// Not found, query resource managers
foreach (var info in _resourceManagers)
{
// Try to get resource
var str = info.Manager.GetString(key);
// Found?
if (str != null)
{
value = str;
if (keepInCache)
_cacheStrings[key] = str;
break;
}
}
}
// Resource not found
return value;
}
/// <summary>
/// Gets an image from the resource manager.
/// </summary>
/// <param name="key">Identifier of the resource</param>
/// <param name="bypassCache">By default, images are cached. Setting this to true will bypass the cache.</param>
/// <param name="keepInCache">If this parameter is set to true, the obtained image will be cached.</param>
/// <returns>The image source, or null if not found</returns>
public static ImageSource GetImage(string key, bool bypassCache = false, bool keepInCache = true)
{
ImageSource image = null;
// Look up in cache
if (bypassCache || !_cacheImages.TryGetValue(key, out image))
{
// Not found, query resource managers
foreach (var info in _resourceManagers)
{
// Try to get resource
var path = info.Manager.GetString(key);
// Found
if (path != null)
{
Uri fullPath = new Uri("/" + info.Assembly.GetName().Name + ";component" + path, UriKind.Relative);
image = new BitmapImage(fullPath);
if (keepInCache)
_cacheImages[key] = image;
break;
}
}
}
// Resource not found
return image;
}
/// <summary>
/// Clears the cache
/// </summary>
public static void ClearCache()
{
_cacheImages.Clear();
_cacheStrings.Clear();
}
}
}

View File

@ -1,9 +1,12 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Linq;
using RainmeterStudio.Business;
using RainmeterStudio.Core.Documents;
using RainmeterStudio.Core.Model.Events;
using RainmeterStudio.UI.Dialogs;
using RainmeterStudio.UI.ViewModel;
namespace RainmeterStudio.UI.Controller
{
@ -60,7 +63,7 @@ namespace RainmeterStudio.UI.Controller
public void CreateWindow(DocumentTemplate defaultFormat = null, string defaultPath = "")
{
// Show dialog
var dialog = new CreateDocumentDialog()
var dialog = new CreateDocumentDialog(this)
{
Owner = OwnerWindow,
SelectedTemplate = defaultFormat,
@ -84,5 +87,15 @@ namespace RainmeterStudio.UI.Controller
DocumentManager.Create(format);
}
/// <summary>
/// Gets a list of document templates view models
/// </summary>
public IEnumerable<DocumentTemplateViewModel> DocumentTemplates
{
get
{
return DocumentManager.DocumentTemplates.Select(t => new DocumentTemplateViewModel(t));
}
}
}
}

View File

@ -7,29 +7,30 @@ using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using RainmeterStudio.Core.Model;
using RainmeterStudio.Resources;
namespace RainmeterStudio.UI.Controller
{
/// <summary>
/// Provides icons
/// </summary>
public static class IconProvider
{
private static Dictionary<string, ImageSource> _loadedImages = new Dictionary<string, ImageSource>();
/// <summary>
/// Gets an icon by resource name
/// </summary>
/// <param name="key">Resource name</param>
/// <returns>The icon</returns>
public static ImageSource GetIcon(string key)
{
if (!_loadedImages.ContainsKey(key))
{
// Try to get the icon file name
string iconPath = Resources.Icons.ResourceManager.GetString(key);
if (iconPath == null)
return null;
// Load the image
var uri = new Uri(iconPath, UriKind.RelativeOrAbsolute);
_loadedImages.Add(key, new BitmapImage(uri));
}
return _loadedImages[key];
return ResourceProvider.GetImage(key);
}
/// <summary>
/// Gets an icon by reference
/// </summary>
/// <param name="item">The reference</param>
/// <returns>The icon</returns>
public static ImageSource GetProjectItemIcon(Reference item)
{
// Resource name
@ -51,6 +52,9 @@ namespace RainmeterStudio.UI.Controller
}
}
/// <summary>
/// Icon provider converter, for use in xaml
/// </summary>
public class IconProviderConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

View File

@ -3,16 +3,29 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Create..." Height="250" Width="400"
WindowStartupLocation="CenterOwner"
WindowStyle="ToolWindow" ShowInTaskbar="False">
WindowStyle="ToolWindow" ShowInTaskbar="False"
Background="WhiteSmoke" >
<Grid Background="WhiteSmoke">
<Grid Margin="2px">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="2" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ListView Name="listCategories" Grid.Row="0" Grid.Column="0"
SelectionChanged="listCategories_SelectionChanged"
Margin="1px"/>
<ListView Name="listFormats" Grid.Row="0">
<GridSplitter Grid.Row="0" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" />
<ListView Name="listFormats" Grid.Row="0" Grid.Column="2" Margin="1px">
<ListView.ItemTemplate>
<DataTemplate>
<DockPanel>
@ -26,18 +39,9 @@
</DockPanel>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock FontWeight="Bold" FontSize="13pt" Text="{Binding Name}" />
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
</ListView>
<Grid Grid.Row="1">
<Grid Grid.Row="1" Grid.ColumnSpan="3">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
@ -49,15 +53,15 @@
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0">Path:</TextBlock>
<TextBox Name="textPath" Grid.Row="0" Grid.Column="1"></TextBox>
<TextBox Name="textPath" Grid.Row="0" Grid.Column="1" Margin="1px"></TextBox>
<Button Grid.Row="0" Grid.Column="2">...</Button>
</Grid>
<StackPanel Grid.Row="2" Orientation="Horizontal"
<StackPanel Grid.Row="2" Grid.ColumnSpan="3" Orientation="Horizontal"
HorizontalAlignment="Right">
<Button Name="buttonCreate" Click="buttonCreate_Click" IsDefault="True">Create</Button>
<Button Name="buttonCancel" Click="buttonCancel_Click" IsCancel="True">Cancel</Button>
<Button Name="buttonCreate" Click="buttonCreate_Click" IsDefault="True" Margin="1px">Create</Button>
<Button Name="buttonCancel" Click="buttonCancel_Click" IsCancel="True" Margin="1px">Cancel</Button>
</StackPanel>
</Grid>

View File

@ -13,6 +13,7 @@ using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using RainmeterStudio.Business;
using RainmeterStudio.Core.Documents;
using RainmeterStudio.UI.Controller;
namespace RainmeterStudio.UI.Dialogs
{
@ -21,6 +22,8 @@ namespace RainmeterStudio.UI.Dialogs
/// </summary>
public partial class CreateDocumentDialog : Window
{
private DocumentController _documentController;
/// <summary>
/// Gets or sets the currently selected file format
/// </summary>
@ -54,20 +57,34 @@ namespace RainmeterStudio.UI.Dialogs
/// <summary>
/// Creates a new instance of CreateDocumentDialog
/// </summary>
public CreateDocumentDialog()
public CreateDocumentDialog(DocumentController docCtrl)
{
InitializeComponent();
_documentController = docCtrl;
PopulateFormats();
PopulateCategories();
RepopulateFormats();
Validate();
}
private void PopulateFormats()
private void PopulateCategories()
{
//listFormats.ItemsSource = DocumentManager.Instance.DocumentFormats;
listCategories.ItemsSource = _documentController.DocumentTemplates
.Select(template => template.Category)
.Where(cat => cat != null)
.Distinct()
.Concat(new[] { "All" });
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(listFormats.ItemsSource);
view.GroupDescriptions.Add(new PropertyGroupDescription("Category"));
listCategories.SelectedIndex = listCategories.Items.Count - 1;
}
private void RepopulateFormats()
{
if (Object.Equals(listCategories.SelectedItem, "All"))
listFormats.ItemsSource = _documentController.DocumentTemplates;
else
listFormats.ItemsSource = _documentController.DocumentTemplates.Where(x => Object.Equals(x.Category, listCategories.SelectedItem));
}
private void buttonCreate_Click(object sender, RoutedEventArgs e)
@ -90,5 +107,10 @@ namespace RainmeterStudio.UI.Dialogs
buttonCreate.IsEnabled = res;
}
private void listCategories_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
RepopulateFormats();
}
}
}