provide a generic property value store for plugin-specific configuration

This commit is contained in:
Michael Becker 2023-07-09 19:25:34 -04:00
parent 935daede06
commit 02e3b9fedc
8 changed files with 385 additions and 26 deletions

View File

@ -223,53 +223,75 @@ namespace MBS.Framework
{ {
List<string> list = new List<string>(); List<string> list = new List<string>();
string[] dataDirectoryNames = null;
if (AdditionalShortNames != null)
{
dataDirectoryNames = new string[AdditionalShortNames.Length + 1];
dataDirectoryNames[0] = DataDirectoryName;
for (int i = 0; i < AdditionalShortNames.Length; i++)
{
dataDirectoryNames[i + 1] = AdditionalShortNames[i];
}
}
else
{
dataDirectoryNames = new string[] { DataDirectoryName };
}
if ((options & FindFileOptions.All) == FindFileOptions.All) if ((options & FindFileOptions.All) == FindFileOptions.All)
{ {
// first look in the application root directory since this will override everything else // first look in the application root directory since this will override everything else
list.Add(BasePath); list.Add(BasePath);
if (Environment.OSVersion.Platform == PlatformID.Unix) foreach (string dataDirName in dataDirectoryNames)
{ {
// if we are on Unix or Mac OS X, look in /etc/... if (Environment.OSVersion.Platform == PlatformID.Unix)
{
// if we are on Unix or Mac OS X, look in /etc/...
list.Add(String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[]
{
String.Empty, // *nix root directory
"etc",
dataDirName
}));
}
// then look in /usr/share/universal-editor or C:\ProgramData\Mike Becker's Software\Universal Editor
list.Add(String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[] list.Add(String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[]
{ {
String.Empty, // *nix root directory System.Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData),
"etc", dataDirName
DataDirectoryName }));
// then look in ~/.local/share/universal-editor or C:\Users\USERNAME\AppData\Local\Mike Becker's Software\Universal Editor
list.Add(String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[]
{
System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData),
dataDirName
})); }));
} }
// then look in /usr/share/universal-editor or C:\ProgramData\Mike Becker's Software\Universal Editor
list.Add(String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[]
{
System.Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData),
DataDirectoryName
}));
// then look in ~/.local/share/universal-editor or C:\Users\USERNAME\AppData\Local\Mike Becker's Software\Universal Editor
list.Add(String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[]
{
System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData),
DataDirectoryName
}));
} }
//fixme: addd finddfileoption.userconfig, localdata, etc. //fixme: addd finddfileoption.userconfig, localdata, etc.
// now for the user-writable locations... // now for the user-writable locations...
// then look in ~/.universal-editor or C:\Users\USERNAME\AppData\Roaming\Mike Becker's Software\Universal Editor foreach (string dataDirName in dataDirectoryNames)
list.Add(String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[]
{ {
System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData), // then look in ~/.universal-editor or C:\Users\USERNAME\AppData\Roaming\Mike Becker's Software\Universal Editor
DataDirectoryName list.Add(String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[]
})); {
System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData),
dataDirName
}));
}
return list.ToArray(); return list.ToArray();
} }
public string ShortName { get; set; } public string ShortName { get; set; }
public virtual string[] AdditionalShortNames => null;
public string Title { get; set; } = String.Empty; public string Title { get; set; } = String.Empty;
public int ExitCode { get; protected set; } = 0; public int ExitCode { get; protected set; } = 0;

View File

@ -141,6 +141,11 @@
<Compile Include="ProgressEvent.cs" /> <Compile Include="ProgressEvent.cs" />
<Compile Include="ICustomPlugin.cs" /> <Compile Include="ICustomPlugin.cs" />
<Compile Include="StringBuilderExtensions.cs" /> <Compile Include="StringBuilderExtensions.cs" />
<Compile Include="PropertyBag.cs" />
<Compile Include="PropertyValueChangedEvent.cs" />
<Compile Include="PropertyValueChangingEvent.cs" />
<Compile Include="PropertyValueRequestedEvent.cs" />
<Compile Include="PluginPropertyBag.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Logic\" /> <Folder Include="Logic\" />

View File

@ -25,9 +25,22 @@ namespace MBS.Framework
{ {
public class Plugin public class Plugin
{ {
public Context Context { get; protected set; }
public virtual string Title { get; set; } = null; public virtual string Title { get; set; } = null;
public Feature.FeatureCollection ProvidedFeatures { get; } = new Feature.FeatureCollection(); public Feature.FeatureCollection ProvidedFeatures { get; } = new Feature.FeatureCollection();
/// <summary>
/// Gets a <see cref="PropertyBag" /> containing the plugin-specific
/// settings for this <see cref="Plugin" />.
/// </summary>
/// <value>The settings.</value>
public PropertyBag Settings { get; }
public Plugin()
{
Settings = new PluginPropertyBag(this);
}
public bool Initialized { get; private set; } = false; public bool Initialized { get; private set; } = false;
public void Initialize() public void Initialize()
{ {
@ -35,6 +48,8 @@ namespace MBS.Framework
return; return;
InitializeInternal(); InitializeInternal();
Settings.Initialize();
Initialized = true; Initialized = true;
} }

View File

@ -0,0 +1,53 @@
//
// PluginPropertyBag.cs
//
// Author:
// beckermj <>
//
// Copyright (c) 2023 ${CopyrightHolder}
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
namespace MBS.Framework
{
public class PluginPropertyBag : PropertyBag
{
private Plugin Plugin { get; }
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
string[] paths = Application.Instance.EnumerateDataPaths();
foreach (string datapath in paths)
{
string path = String.Format("{0}/plugins/{1}/config.xml", datapath, this.Plugin.ID.ToString("b"));
if (System.IO.File.Exists(path))
{
Console.WriteLine("found config in {0}", path);
}
}
}
internal PluginPropertyBag(Plugin plugin)
{
Plugin = plugin;
}
protected override void OnPropertyValueRequested<T>(PropertyValueRequestedEventArgs<T> e)
{
base.OnPropertyValueRequested(e);
}
}
}

View File

@ -0,0 +1,144 @@
//
// PropertyBag.cs
//
// Author:
// beckermj <>
//
// Copyright (c) 2023 ${CopyrightHolder}
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
namespace MBS.Framework
{
public class PropertyBag
{
private Dictionary<Guid, object> _settings = new Dictionary<Guid, object>();
private Dictionary<Guid, string> _names = new Dictionary<Guid, string>();
public string GetName(Guid id)
{
if (_names.ContainsKey(id))
return _names[id];
return null;
}
public void SetName(Guid id, string name)
{
_names[id] = name;
}
private Dictionary<Guid, object> _PropertyValues = new Dictionary<Guid, object>();
public bool Contains(Guid id)
{
return _PropertyValues.ContainsKey(id);
}
public bool SetValue<T>(Guid id, T value)
{
bool changed = false;
lock (_PropertyValues)
{
object oldValue = null;
if (!_PropertyValues.ContainsKey(id) || (!(
(_PropertyValues[id] == null && (value as object) == null) ||
(_PropertyValues[id] != null && _PropertyValues[id].Equals(value)))))
{
changed = true;
}
if (_PropertyValues.ContainsKey(id))
{
oldValue = _PropertyValues[id];
}
if (changed)
{
PropertyValueChangingEventArgs e = new PropertyValueChangingEventArgs(id, oldValue, value);
OnPropertyValueChanging(e);
if (e.Cancel)
{
return false;
}
}
_PropertyValues[id] = value;
if (changed)
{
OnPropertyValueChanged(new PropertyValueChangedEventArgs(id, oldValue, value));
}
}
return changed;
}
public event EventHandler<PropertyValueChangingEventArgs> PropertyValueChanging;
protected virtual void OnPropertyValueChanging(PropertyValueChangingEventArgs e)
{
PropertyValueChanging?.Invoke(this, e);
}
public event EventHandler<PropertyValueChangedEventArgs> PropertyValueChanged;
protected virtual void OnPropertyValueChanged(PropertyValueChangedEventArgs e)
{
PropertyValueChanged?.Invoke(this, e);
}
public T GetValue<T>(Guid id, T defaultValue = default(T))
{
lock (_PropertyValues)
{
if (_PropertyValues.ContainsKey(id))
{
if (_PropertyValues[id] is T val)
{
return val;
}
}
else
{
PropertyValueRequestedEventArgs<T> e = new PropertyValueRequestedEventArgs<T>(id, defaultValue);
OnPropertyValueRequested(e);
if (e.Handled)
{
if (e.Cache)
{
_PropertyValues[id] = e.Value;
}
return e.Value;
}
}
}
return defaultValue;
}
public event EventHandler<PropertyValueRequestedEventArgs> PropertyValueRequested;
protected virtual void OnPropertyValueRequested<T>(PropertyValueRequestedEventArgs<T> e)
{
PropertyValueRequested?.Invoke(this, e);
}
public IEnumerable<KeyValuePair<Guid, object>> GetAll()
{
return _PropertyValues;
}
public bool Initialized { get; private set; } = false;
protected virtual void OnInitialized(EventArgs e)
{
}
public void Initialize()
{
if (Initialized)
return;
OnInitialized(EventArgs.Empty);
Initialized = true;
}
}
}

View File

@ -0,0 +1,37 @@
//
// PropertyValueChangedEvent.cs
//
// Author:
// beckermj <>
//
// Copyright (c) 2023 ${CopyrightHolder}
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
namespace MBS.Framework
{
public class PropertyValueChangedEventArgs : EventArgs
{
public Guid ID { get; }
public object OldValue { get; }
public object NewValue { get; }
public PropertyValueChangedEventArgs(Guid id, object oldValue, object newValue)
{
ID = id;
OldValue = oldValue;
NewValue = newValue;
}
}
}

View File

@ -0,0 +1,37 @@
//
// PropertyValueChangedEvent.cs
//
// Author:
// beckermj <>
//
// Copyright (c) 2023 ${CopyrightHolder}
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
namespace MBS.Framework
{
public class PropertyValueChangingEventArgs : System.ComponentModel.CancelEventArgs
{
public Guid ID { get; }
public object OldValue { get; }
public object NewValue { get; set; }
public PropertyValueChangingEventArgs(Guid id, object oldValue, object newValue)
{
ID = id;
OldValue = oldValue;
NewValue = newValue;
}
}
}

View File

@ -0,0 +1,46 @@
//
// PropertyValueRequestedEvent.cs
//
// Author:
// beckermj <>
//
// Copyright (c) 2023 ${CopyrightHolder}
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
namespace MBS.Framework
{
public class PropertyValueRequestedEventArgs : EventArgs
{
public Guid ID { get; }
public object Value { get; set; }
public bool Cache { get; set; } = true;
public bool Handled { get; set; } = false;
public PropertyValueRequestedEventArgs(Guid id, object value)
{
ID = id;
Value = value;
}
}
public class PropertyValueRequestedEventArgs<T> : PropertyValueRequestedEventArgs
{
public new T Value { get { return (T)base.Value; } set { base.Value = value; } }
public PropertyValueRequestedEventArgs(Guid id, T value) : base(id, value)
{
}
}
}