mirror of
https://github.com/chibicitiberiu/rainmeter-studio.git
synced 2024-02-24 04:33:31 +00:00
Improved resource manager, plugin manager
This commit is contained in:
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -1,11 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace RainmeterStudio.Rainmeter.DataTypes
|
||||
{
|
||||
public class Action
|
||||
{
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace RainmeterStudio.Rainmeter
|
||||
{
|
||||
public class Measure
|
||||
{
|
||||
}
|
||||
}
|
@ -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)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -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.");
|
||||
}
|
||||
}
|
||||
}
|
@ -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>
|
||||
|
126
RainmeterStudio/Resources/ResourceProvider.cs
Normal file
126
RainmeterStudio/Resources/ResourceProvider.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user