diff --git a/framework-dotnet/src/lib/MBS.Core/Application.cs b/framework-dotnet/src/lib/MBS.Core/Application.cs index 6773ebe..85822ed 100644 --- a/framework-dotnet/src/lib/MBS.Core/Application.cs +++ b/framework-dotnet/src/lib/MBS.Core/Application.cs @@ -1,4 +1,5 @@ using System.ComponentModel; +using MBS.Core.Extensibility; namespace MBS.Core; @@ -492,4 +493,12 @@ public class Application return true; } + internal void _EnableDisableCommand(Command command, bool enable) + { + } + + protected internal virtual Plugin[] GetAdditionalPlugins() + { + return new Plugin[0]; + } } diff --git a/framework-dotnet/src/lib/MBS.Core/Command.cs b/framework-dotnet/src/lib/MBS.Core/Command.cs new file mode 100644 index 0000000..c838887 --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/Command.cs @@ -0,0 +1,149 @@ +// Copyright (C) 2024 Michael Becker +// +// This file is part of MBS Framework for .NET Core. +// +// MBS Framework for .NET Core 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. +// +// MBS Framework for .NET Core 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 MBS Framework for .NET Core. If not, see . + +namespace MBS.Core; + +public class Command +{ + public class CommandCollection + : System.Collections.ObjectModel.Collection + { + public Command this[string ID] + { + get + { + foreach (Command command in this) + { + if (command.ID == ID) return command; + } + return null; + } + } + } + + public Command() + { + } + public Command(string id, string title, CommandItem[] items = null) + { + ID = id; + Title = title; + if (items != null) + { + for (int i = 0; i < items.Length; i++) + { + Items.Add(items[i]); + } + } + } + /// + /// Determines whether this command displays as checked. + /// + public bool Checked { get; set; } = false; + /// + /// The ID of the command, used to reference it in . + /// + public string ID { get; set; } = String.Empty; + /// + /// The title of the command (including mnemonic prefix, if applicable). + /// + public string Title { get; set; } = String.Empty; + + private string mvarDefaultCommandID = String.Empty; + public string DefaultCommandID { get { return mvarDefaultCommandID; } set { mvarDefaultCommandID = value; } } + + /// + /// A that represents a predefined, platform-themed command. + /// + public StockType StockType { get; set; } = StockType.None; + + private string mvarImageFileName = String.Empty; + /// + /// The file name of the image to be displayed on the command. + /// + public string ImageFileName { get { return mvarImageFileName; } set { mvarImageFileName = value; } } + + + /// + /// The child s that are contained within this . + /// + public CommandItem.CommandItemCollection Items { get; } = new CommandItem.CommandItemCollection(); + + /// + /// The event that is fired when the command is executed. + /// + public event EventHandler Executed; + + /// + /// Determines whether this is enabled in all s and s + /// that reference it. + /// + /// true if visible; otherwise, false. + private bool _Enabled = true; + public bool Enabled { get { return _Enabled; } set { _Enabled = value; Application.Instance._EnableDisableCommand(this, value); } } + + /// + /// Determines whether this is visible in all s and s + /// that reference it. + /// + /// true if visible; otherwise, false. + public bool Visible { get; set; } + + /// + /// Executes this . + /// + [Obsolete("Please use Application.ExecuteCommand. Command.Execute does not always work and will be removed in a future release.")] + public void Execute() + { + if (Executed != null) Executed(this, EventArgs.Empty); + } + + public override string ToString() + { + return String.Format("{0} [{1}]", ID, Title); + } + + private Dictionary _extraData = new Dictionary(); + public T GetExtraData(string key, T defaultValue = default(T)) + { + if (_extraData.ContainsKey(key)) + { + if (_extraData[key] is T) + { + return (T)_extraData[key]; + } + } + return defaultValue; + } + + public void SetExtraData(string key, T value) + { + _extraData[key] = value; + } + + public object GetExtraData(string key, object defaultValue = null) + { + if (_extraData.ContainsKey(key)) + return _extraData[key]; + return defaultValue; + } + + public void SetExtraData(string key, object value) + { + _extraData[key] = value; + } +} \ No newline at end of file diff --git a/framework-dotnet/src/lib/MBS.Core/CommandEventArgs.cs b/framework-dotnet/src/lib/MBS.Core/CommandEventArgs.cs new file mode 100644 index 0000000..a1c1b27 --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/CommandEventArgs.cs @@ -0,0 +1,50 @@ +// Copyright (C) 2024 Michael Becker +// +// This file is part of MBS Framework for .NET Core. +// +// MBS Framework for .NET Core 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. +// +// MBS Framework for .NET Core 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 MBS Framework for .NET Core. If not, see . + +namespace MBS.Core; + +public class CommandEventArgs : EventArgs +{ + public Command Command { get; private set; } + + private Dictionary _NamedParameters = new Dictionary(); + public T GetNamedParameter(string key, T defaultValue = default(T)) + { + if (_NamedParameters.ContainsKey(key)) + return (T)_NamedParameters[key]; + return defaultValue; + } + public object GetNamedParameter(string key, object defaultValue = null) + { + if (_NamedParameters.ContainsKey(key)) + return _NamedParameters[key]; + return defaultValue; + } + + + public CommandEventArgs(Command command, KeyValuePair[] namedParameters = null) + { + Command = command; + if (namedParameters != null) + { + for (int i = 0; i < namedParameters.Length; i++) + { + _NamedParameters[namedParameters[i].Key] = namedParameters[i].Value; + } + } + } +} \ No newline at end of file diff --git a/framework-dotnet/src/lib/MBS.Core/CommandItem.cs b/framework-dotnet/src/lib/MBS.Core/CommandItem.cs new file mode 100644 index 0000000..a259a2f --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/CommandItem.cs @@ -0,0 +1,93 @@ +// Copyright (C) 2024 Michael Becker +// +// This file is part of Mocha.NET. +// +// Mocha.NET 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. +// +// Mocha.NET 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 Mocha.NET. If not, see . + +namespace MBS.Core; + +public abstract class CommandItem +{ + public string InsertAfterID { get; set; } = null; + public string InsertBeforeID { get; set; } = null; + + public class CommandItemCollection + : System.Collections.ObjectModel.Collection + { + public int IndexOf(string value) + { + for (int i = 0; i < Count; i++) + { + if (this[i] is CommandReferenceCommandItem) + { + if ((this[i] as CommandReferenceCommandItem).CommandID.Equals(value)) + return i; + } + } + return -1; + } + } +} +public class ActionCommandItem : CommandItem +{ + public string ID { get; } + public string Title { get; } + + public event EventHandler Executed; + + public void Execute() + { + Executed?.Invoke(this, EventArgs.Empty); + } + + public ActionCommandItem(string id, string title, EventHandler execute = null) + { + ID = id; + Title = title; + if (execute != null) + { + Executed += execute; + } + } +} +public class CommandReferenceCommandItem : CommandItem +{ + private string mvarCommandID = String.Empty; + public string CommandID { get { return mvarCommandID; } set { mvarCommandID = value; } } + + public CommandReferenceCommandItem() + { + } + public CommandReferenceCommandItem(string commandID) + { + mvarCommandID = commandID; + } +} +public class CommandPlaceholderCommandItem : CommandItem +{ + private string mvarPlaceholderID = String.Empty; + public string PlaceholderID { get { return mvarPlaceholderID; } set { mvarPlaceholderID = value; } } + + public CommandPlaceholderCommandItem(string placeholderID) + { + mvarPlaceholderID = placeholderID; + } +} +public class SeparatorCommandItem : CommandItem +{ +} +public class GroupCommandItem : CommandItem +{ + public CommandItemCollection Items { get; } = new CommandItemCollection(); +} \ No newline at end of file diff --git a/framework-dotnet/src/lib/MBS.Core/Context.cs b/framework-dotnet/src/lib/MBS.Core/Context.cs new file mode 100644 index 0000000..4394f02 --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/Context.cs @@ -0,0 +1,115 @@ +// Copyright (C) 2024 Michael Becker +// +// This file is part of Mocha.NET. +// +// Mocha.NET 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. +// +// Mocha.NET 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 Mocha.NET. If not, see . + +namespace MBS.Core; + +public class Context +{ + public class ContextCollection + : System.Collections.ObjectModel.Collection + { + private Dictionary _ItemsByID = new Dictionary(); + + public bool Contains(Guid contextID) + { + return _ItemsByID.ContainsKey(contextID); + } + + public Context this[Guid id] + { + get + { + if (_ItemsByID.ContainsKey(id)) + return _ItemsByID[id]; + return null; + } + } + + protected override void ClearItems() + { + base.ClearItems(); + _ItemsByID.Clear(); + } + protected override void InsertItem(int index, Context item) + { + base.InsertItem(index, item); + _ItemsByID[item.ID] = item; + } + protected override void RemoveItem(int index) + { + _ItemsByID.Remove(this[index].ID); + base.RemoveItem(index); + } + } + + public Guid ID { get; private set; } = Guid.Empty; + public string Name { get; private set; } = String.Empty; + + // public MenuBar MenuBar { get; } = new MenuBar(); + public Command.CommandCollection Commands { get; } = new Command.CommandCollection(); + + public Context(Guid id, string name) + { + ID = id; + Name = name; + } + + public override string ToString() + { + return String.Format("{0} {1}", Name, ID); + } + + private Dictionary> _CommandEventHandlers = new Dictionary>(); + /// + /// Attachs an event handler for the command with the ID specified by . + /// + /// true, if command event handler was attached, false otherwise. + /// The ID of the for which to attach an event handler. + /// The event handler to invoke when the is executed. + public bool AttachCommandEventHandler(string commandID, EventHandler handler) + { + // handle command event handlers attached without a Command instance + if (!_CommandEventHandlers.ContainsKey(commandID)) + { + _CommandEventHandlers.Add(commandID, new List()); + } + if (!_CommandEventHandlers[commandID].Contains(handler)) + { + _CommandEventHandlers[commandID].Add(handler); + return true; + } + return false; + } + /// + /// Executes the command (i.e., calls all attached s for the ) with + /// the given , passing in the given parameters in an instance of . + /// + /// true, if command was executed, false otherwise. + /// Command identifier. + /// Named parameters. + public bool ExecuteCommand(string commandID, KeyValuePair[] namedParameters = null) + { + if (_CommandEventHandlers.ContainsKey(commandID)) + { + for (int i = 0; i < _CommandEventHandlers[commandID].Count; i++) + { + _CommandEventHandlers[commandID][i](this, new CommandEventArgs(Commands[commandID], namedParameters)); + } + } + return false; + } +} \ No newline at end of file diff --git a/framework-dotnet/src/lib/MBS.Core/Extensibility/Feature.cs b/framework-dotnet/src/lib/MBS.Core/Extensibility/Feature.cs new file mode 100644 index 0000000..50c802b --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/Extensibility/Feature.cs @@ -0,0 +1,61 @@ +// Copyright (C) 2024 Michael Becker +// +// This file is part of MBS Framework for .NET Core. +// +// MBS Framework for .NET Core 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. +// +// MBS Framework for .NET Core 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 MBS Framework for .NET Core. If not, see . + +namespace MBS.Core.Extensibility; + +public class Feature +{ + public class FeatureCollection + : System.Collections.ObjectModel.Collection + { + } + + public Guid ID { get; private set; } = Guid.Empty; + public string Title { get; private set; } = null; + + public Feature(Guid id, string title) + { + ID = id; + Title = title; + } + + public override bool Equals(object obj) + { + if (!(this is null) && (obj is null)) return false; + if (this is null && !(obj is null)) return false; + + if (obj is Feature) + { + Feature feat = (obj as Feature); + return feat.ID.Equals(ID); + } + return base.Equals(obj); + } + public override int GetHashCode() + { + return base.GetHashCode(); + } + + public static bool operator ==(Feature left, Feature right) + { + return (left.ID == right.ID); + } + public static bool operator !=(Feature left, Feature right) + { + return (left.ID != right.ID); + } +} \ No newline at end of file diff --git a/framework-dotnet/src/lib/MBS.Core/Extensibility/Plugin.cs b/framework-dotnet/src/lib/MBS.Core/Extensibility/Plugin.cs new file mode 100644 index 0000000..c82f5cb --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/Extensibility/Plugin.cs @@ -0,0 +1,175 @@ +// Copyright (C) 2024 Michael Becker +// +// This file is part of MBS Framework for .NET Core. +// +// MBS Framework for .NET Core 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. +// +// MBS Framework for .NET Core 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 MBS Framework for .NET Core. If not, see . + +namespace MBS.Core.Extensibility; + +public class Plugin +{ + public Context Context { get; protected set; } + public virtual string Title { get; set; } = null; + public Feature.FeatureCollection ProvidedFeatures { get; } = new Feature.FeatureCollection(); + + /// + /// Gets a containing the plugin-specific + /// settings for this . + /// + /// The settings. + public PropertyBag Settings { get; } + + public Plugin() + { + Settings = new PluginPropertyBag(this); + } + + public bool Initialized { get; private set; } = false; + public void Initialize() + { + if (Initialized) + return; + + InitializeInternal(); + + Settings.Initialize(); + Initialized = true; + } + + public Guid ID { get; set; } = Guid.Empty; + + protected virtual void InitializeInternal() + { + // this method intentionally left blank + } + + protected virtual bool AutoRegister => true; + + protected virtual bool IsSupportedInternal() + { + return true; + } + public bool IsSupported() + { + return IsSupportedInternal(); + } + private static Plugin[] _plugins = null; + public static TPlugin[] Get(bool resetCache = false) where TPlugin : Plugin + { + Plugin[] plugins = Get(resetCache); + return plugins.OfType().ToArray(); + } + public static Plugin[] Get(bool resetCache = false) + { + if (resetCache) + { + _plugins = null; // should not be cached? // actually, yes it should... + + // 2020-12-12 20:54 by beckermj + // ACTUALLY, it depends on whether the configuration needs to be persisted across calls to Get() + // [it does] and whether the list of plugins needs to be reloaded when CustomPlugins is modified + // [it shouldn't, but it does] . + // + // The safest way we can handle this RIGHT NOW is to prevent any plugin from being loaded until after CustomPlugins + // is initialized by UIApplication. + // + // We call Plugins.Get(new Feature[] { KnownFeatures.UWTPlatform }) to retrieve the available User Interface plugins + // that supply the UWT Platform implementation (e.g. GTK, Windows Forms, etc.) - and this causes CustomPlugins to not + // load properly since it loads AFTER this initial call to Plugins.Get(). + // + // So I add ed a resetCache parameter that when specified TRUE will clear the cache and then return the appropriate + // plugin. This way we can continue caching future calls to Get() without missing out on CustomPlugins. + } + + if (_plugins == null) + { + Type[] types = Reflection.TypeLoader.GetAvailableTypes(new Type[] { typeof(Plugin) }); + System.Collections.Generic.List plugins = new System.Collections.Generic.List(); + for (int i = 0; i < types.Length; i++) + { + try + { + /* + if (types[i].IsSubclassOf(typeof(ICustomPlugin))) + { + continue; + } + */ + + Plugin plg = (Plugin)types[i].Assembly.CreateInstance(types[i].FullName); + plugins.Add(plg); + } + catch (Exception ex) + { + } + } + + Plugin[] plugins2 = Application.Instance.GetAdditionalPlugins(); + for (int i = 0; i < plugins2.Length; i++) + { + plugins.Add(plugins2[i]); + } + _plugins = plugins.ToArray(); + + if (resetCache) + { + _plugins = null; + return plugins.ToArray(); + } + } + return _plugins; + } + + public static TPlugin[] Get(Feature[] providedFeatures, bool resetCache = false) where TPlugin : Plugin + { + Plugin[] plugins = Get(providedFeatures, resetCache); + return plugins.OfType().ToArray(); + } + public static Plugin[] Get(Feature[] providedFeatures, bool resetCache = false) + { + System.Collections.Generic.List list = new System.Collections.Generic.List(); + Plugin[] plugins = Get(resetCache); + for (int i = 0; i < plugins.Length; i++) + { + if (!plugins[i].AutoRegister) + continue; + + if (!plugins[i].IsSupported()) + continue; + + for (int j = 0; j < providedFeatures.Length; j++) + { + if (plugins[i].ProvidedFeatures.Contains(providedFeatures[j])) + list.Add(plugins[i]); + } + } + return list.ToArray(); + } + + public static TPlugin Get(Guid id) where TPlugin : Plugin + { + Plugin plugin = Get(id); + return (TPlugin)plugin; + } + public static Plugin Get(Guid id) + { + Plugin[] plugins = Get(); + for (int i = 0; i < plugins.Length; i++) + { + if (plugins[i].ID == id) + return plugins[i]; + } + return null; + } +} \ No newline at end of file diff --git a/framework-dotnet/src/lib/MBS.Core/Extensibility/PluginPropertyBag.cs b/framework-dotnet/src/lib/MBS.Core/Extensibility/PluginPropertyBag.cs new file mode 100644 index 0000000..c4a8b11 --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/Extensibility/PluginPropertyBag.cs @@ -0,0 +1,49 @@ +// Copyright (C) 2024 Michael Becker +// +// This file is part of MBS Framework for .NET Core. +// +// MBS Framework for .NET Core 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. +// +// MBS Framework for .NET Core 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 MBS Framework for .NET Core. If not, see . + +namespace MBS.Core.Extensibility; + + +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(PropertyValueRequestedEventArgs e) + { + base.OnPropertyValueRequested(e); + } +} \ No newline at end of file diff --git a/framework-dotnet/src/lib/MBS.Core/Extensibility/PropertyBag.cs b/framework-dotnet/src/lib/MBS.Core/Extensibility/PropertyBag.cs new file mode 100644 index 0000000..db7ae3e --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/Extensibility/PropertyBag.cs @@ -0,0 +1,187 @@ +// Copyright (C) 2024 Michael Becker +// +// This file is part of MBS Framework for .NET Core. +// +// MBS Framework for .NET Core 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. +// +// MBS Framework for .NET Core 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 MBS Framework for .NET Core. If not, see . + +namespace MBS.Core.Extensibility; + +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 : PropertyValueRequestedEventArgs +{ + public new T Value { get { return (T)base.Value; } set { base.Value = value; } } + + public PropertyValueRequestedEventArgs(Guid id, T value) : base(id, value) + { + } +} + +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; + } +} +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; + } +} + +public class PropertyBag +{ + private Dictionary _settings = new Dictionary(); + private Dictionary _names = new Dictionary(); + 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 _PropertyValues = new Dictionary(); + public bool Contains(Guid id) + { + return _PropertyValues.ContainsKey(id); + } + public bool SetValue(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 PropertyValueChanging; + protected virtual void OnPropertyValueChanging(PropertyValueChangingEventArgs e) + { + PropertyValueChanging?.Invoke(this, e); + } + public event EventHandler PropertyValueChanged; + protected virtual void OnPropertyValueChanged(PropertyValueChangedEventArgs e) + { + PropertyValueChanged?.Invoke(this, e); + } + + public T GetValue(Guid id, T defaultValue = default(T)) + { + lock (_PropertyValues) + { + if (_PropertyValues.ContainsKey(id)) + { + if (_PropertyValues[id] is T val) + { + return val; + } + } + else + { + PropertyValueRequestedEventArgs e = new PropertyValueRequestedEventArgs(id, defaultValue); + OnPropertyValueRequested(e); + if (e.Handled) + { + if (e.Cache) + { + _PropertyValues[id] = e.Value; + } + return e.Value; + } + } + } + return defaultValue; + } + + public event EventHandler PropertyValueRequested; + protected virtual void OnPropertyValueRequested(PropertyValueRequestedEventArgs e) + { + PropertyValueRequested?.Invoke(this, e); + } + + public IEnumerable> 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; + } +} \ No newline at end of file diff --git a/framework-dotnet/src/lib/MBS.Core/IO/DirectoryExtensions.cs b/framework-dotnet/src/lib/MBS.Core/IO/DirectoryExtensions.cs new file mode 100644 index 0000000..fdc496b --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/IO/DirectoryExtensions.cs @@ -0,0 +1,35 @@ +// Copyright (C) 2024 Michael Becker +// +// This file is part of Mocha.NET. +// +// Mocha.NET 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. +// +// Mocha.NET 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 Mocha.NET. If not, see . + +namespace MBS.Core.IO; + +public static class DirectoryExtensions +{ + public static string[] GetFiles(string path, string[] searchPatterns, SearchOption options) + { + string[] result = new string[0]; + int j = 0; + foreach (string ext in searchPatterns) + { + string[] filenames = Directory.GetFiles(path, ext, options); + Array.Resize(ref result, result.Length + filenames.Length); + Array.Copy(filenames, 0, result, j, filenames.Length); + j += filenames.Length; + } + return result; + } +} \ No newline at end of file diff --git a/framework-dotnet/src/lib/MBS.Core/StockType.cs b/framework-dotnet/src/lib/MBS.Core/StockType.cs new file mode 100644 index 0000000..9f36272 --- /dev/null +++ b/framework-dotnet/src/lib/MBS.Core/StockType.cs @@ -0,0 +1,137 @@ +// Copyright (C) 2024 Michael Becker +// +// This file is part of MBS Framework for .NET Core. +// +// MBS Framework for .NET Core 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. +// +// MBS Framework for .NET Core 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 MBS Framework for .NET Core. If not, see . + +namespace MBS.Core; + +public enum StockType +{ + None, + About, + Add, + Apply, + + // these four do not have gtk-stock equivalents + ArrowDown, + ArrowLeft, + ArrowRight, + ArrowUp, + + Bold, + Bookmarks, + Cancel, + CapsLockWarning, // not for buttons + CDROM, + Clear, + Close, + ColorPicker, // not for buttons + Connect, + Convert, + Copy, + Cut, + Delete, + DialogAuthentication, // not for buttons + DialogInfo, + DialogWarning, + DialogError, + DialogQuestion, + Directory, // not for buttons + Discard, + Disconnect, + DragAndDrop, // not for buttons + DragAndDropMultiple, // not for buttons + Edit, + Execute, + File, + Find, + FindAndReplace, + Floppy, + Folder, + Fullscreen, + GotoBottom, + GotoFirst, + GotoLast, + GotoTop, + GoBack, + GoDown, + GoForward, + GoUp, + HardDisk, + Help, + Home, + Index, + Indent, + Info, + Italic, + JumpTo, + JustifyCenter, + JustifyFill, + JustifyLeft, + JustifyRight, + LeaveFullscreen, + MissingImage, // not for buttons + MediaForward, + MediaNext, + MediaPause, + MediaPlay, + MediaPrevious, + MediaRecord, + MediaRewind, + MediaStop, + Network, + New, + No, + OK, + Open, + OrientationPortrait, + OrientationLandscape, + OrientationReverseLandscape, + OrientationReversePortrait, + PageSetup, + Paste, + Preferences, + Print, + PrintError, // not for buttons + PrintPaused, // not for buttons + PrintPreview, + PrintReport, // not for buttons + PrintWarning, // not for buttons + Properties, + Quit, + Redo, + Refresh, + Remove, + RevertToSaved, + Save, + SaveAs, + SelectAll, + SelectColor, + SelectFont, + SortAscending, + SortDescending, + SpellCheck, + Stop, + Strikethrough, + Undelete, + Underline, + Undo, + Unindent, + Yes, + Zoom100, + ZoomFit, + ZoomIn, + ZoomOut +} \ No newline at end of file