huh
This commit is contained in:
commit
e5af2f5dec
@ -1,22 +1,228 @@
|
||||
using System.ComponentModel.Design;
|
||||
using System.ComponentModel;
|
||||
using MBS.Core.Extensibility;
|
||||
|
||||
using System.ComponentModel.Design;
|
||||
|
||||
namespace MBS.Core;
|
||||
|
||||
public class Application
|
||||
{
|
||||
public IList<Command> Commands { get; } = new List<Command>();
|
||||
public Command.CommandCollection Commands { get; } = new Command.CommandCollection();
|
||||
|
||||
public static Application? Instance { get; private set; }
|
||||
public CommandLine CommandLine { get; } = new CommandLine();
|
||||
protected virtual void OnStartup(EventArgs e)
|
||||
{
|
||||
}
|
||||
public event ApplicationActivatedEventHandler BeforeActivated;
|
||||
protected virtual void OnBeforeActivated(ApplicationActivatedEventArgs e)
|
||||
{
|
||||
BeforeActivated?.Invoke(this, e);
|
||||
}
|
||||
|
||||
public event ApplicationActivatedEventHandler Activated;
|
||||
protected virtual void OnActivated(ApplicationActivatedEventArgs e)
|
||||
{
|
||||
Activated?.Invoke(this, e);
|
||||
}
|
||||
|
||||
|
||||
public event ApplicationActivatedEventHandler AfterActivated;
|
||||
protected virtual void OnAfterActivated(ApplicationActivatedEventArgs e)
|
||||
{
|
||||
AfterActivated?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses the option.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if option was parsed, <c>false</c> otherwise.</returns>
|
||||
/// <param name="args">Arguments.</param>
|
||||
/// <param name="index">Index.</param>
|
||||
/// <param name="list">The list into which to add the option if it has been specified.</param>
|
||||
/// <param name="optionSet">The set of available options.</param>
|
||||
private bool ParseOption(string[] args, ref int index, IList<CommandLineOption> list, CommandLineOption.CommandLineOptionCollection optionSet)
|
||||
{
|
||||
string longOptionPrefix = "--", shortOptionPrefix = "-";
|
||||
|
||||
bool breakout = false;
|
||||
if (args[index].StartsWith(shortOptionPrefix) && args[index].Length == (shortOptionPrefix.Length + 1))
|
||||
{
|
||||
char shortOptionChar = args[index][args[index].Length - 1];
|
||||
CommandLineOption option = optionSet[shortOptionChar];
|
||||
if (option != null)
|
||||
{
|
||||
if (option.Abbreviation == shortOptionChar)
|
||||
{
|
||||
if (option.Type != CommandLineOptionValueType.None)
|
||||
{
|
||||
index++;
|
||||
option.Value = args[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
option.Value = true;
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
list.Add(option);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add(new CommandLineOption() { Abbreviation = shortOptionChar });
|
||||
}
|
||||
}
|
||||
else if (args[index].StartsWith(longOptionPrefix))
|
||||
{
|
||||
// long option format is --name[=value]
|
||||
string name = args[index].Substring(longOptionPrefix.Length);
|
||||
string value = null;
|
||||
if (name.Contains("="))
|
||||
{
|
||||
int idx = name.IndexOf('=');
|
||||
value = name.Substring(idx + 1);
|
||||
name = name.Substring(0, idx);
|
||||
}
|
||||
CommandLineOption option = optionSet[name];
|
||||
if (option != null)
|
||||
{
|
||||
if (option.Type != CommandLineOptionValueType.None)
|
||||
{
|
||||
// index++;
|
||||
// option.Value = args[index];
|
||||
if (!name.Contains("="))
|
||||
{
|
||||
// already taken care of the true case above
|
||||
if (index + 1 < args.Length)
|
||||
{
|
||||
index++;
|
||||
value = args[index];
|
||||
}
|
||||
}
|
||||
option.Value = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
option.Value = true;
|
||||
}
|
||||
list.Add(option);
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add(new CommandLineOption() { Name = name });
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// we have reached a non-option
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected virtual int StartInternal()
|
||||
{
|
||||
CommandLine cline = new CommandLine();
|
||||
string[] args = CommandLine.Arguments;
|
||||
|
||||
if (args.Length > 0)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < args.Length; i++)
|
||||
{
|
||||
if (ParseOption(args, ref i, cline.Options, CommandLine.Options))
|
||||
break;
|
||||
}
|
||||
|
||||
// we have finished parsing the first set of options ("global" options)
|
||||
// now we see if we have commands
|
||||
if (CommandLine.Commands.Count > 0 && i < args.Length)
|
||||
{
|
||||
// we support commands like git and apt, "appname --app-global-options <command> --command-options"
|
||||
CommandLineCommand cmd = CommandLine.Commands[args[i]];
|
||||
if (cmd != null)
|
||||
{
|
||||
for (i++; i < args.Length; i++)
|
||||
{
|
||||
if (ParseOption(args, ref i, cline.Options, cmd.Options))
|
||||
break;
|
||||
}
|
||||
|
||||
cline.Command = cmd;
|
||||
}
|
||||
else
|
||||
{
|
||||
// assume filename
|
||||
}
|
||||
}
|
||||
|
||||
for (/* intentionally left blank */; i < args.Length; i++)
|
||||
{
|
||||
cline.FileNames.Add(args[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ApplicationActivatedEventArgs e = new ApplicationActivatedEventArgs(true, ApplicationActivationType.CommandLineLaunch, cline);
|
||||
|
||||
if (CommandLine.Options["help"]?.Value is bool && ((bool)CommandLine.Options["help"]?.Value) == true)
|
||||
{
|
||||
if (ShowCommandLineHelp(out int resultCode))
|
||||
{
|
||||
return resultCode;
|
||||
}
|
||||
}
|
||||
|
||||
OnStartup(EventArgs.Empty);
|
||||
if (cline.Command != null && cline.Command.ActivationDelegate != null)
|
||||
{
|
||||
OnBeforeActivated(e);
|
||||
if (!e.Success)
|
||||
{
|
||||
Console.WriteLine(String.Format("Try '{0} --help' for more information.", ShortName));
|
||||
return e.ExitCode;
|
||||
}
|
||||
|
||||
// use the activation delegate instead of calling OnActivated
|
||||
cline.Command.ActivationDelegate(e);
|
||||
if (!e.Success)
|
||||
{
|
||||
Console.WriteLine(String.Format("Try '{0} --help' for more information.", ShortName));
|
||||
return e.ExitCode;
|
||||
}
|
||||
|
||||
OnAfterActivated(e);
|
||||
if (!e.Success)
|
||||
{
|
||||
Console.WriteLine(String.Format("Try '{0} --help' for more information.", ShortName));
|
||||
return e.ExitCode;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OnBeforeActivated(e);
|
||||
if (!e.Success)
|
||||
{
|
||||
Console.WriteLine(String.Format("Try '{0} --help' for more information.", ShortName));
|
||||
return e.ExitCode;
|
||||
}
|
||||
|
||||
OnActivated(e);
|
||||
if (!e.Success)
|
||||
{
|
||||
Console.WriteLine(String.Format("Try '{0} --help' for more information.", ShortName));
|
||||
return e.ExitCode;
|
||||
}
|
||||
|
||||
OnAfterActivated(e);
|
||||
if (!e.Success)
|
||||
{
|
||||
Console.WriteLine(String.Format("Try '{0} --help' for more information.", ShortName));
|
||||
return e.ExitCode;
|
||||
}
|
||||
}
|
||||
return e.ExitCode;
|
||||
/*
|
||||
OnStartup(EventArgs.Empty);
|
||||
|
||||
CommandLine cline = new CommandLine();
|
||||
@ -26,11 +232,24 @@ public class Application
|
||||
OnActivated(e);
|
||||
|
||||
return e.ExitCode;
|
||||
*/
|
||||
}
|
||||
|
||||
public event EventHandler<CancelEventArgs> BeforeStartInternal;
|
||||
protected virtual void OnBeforeStartInternal(CancelEventArgs e)
|
||||
{
|
||||
BeforeStartInternal?.Invoke(this, e);
|
||||
}
|
||||
|
||||
public int Start()
|
||||
{
|
||||
Instance = this;
|
||||
|
||||
CancelEventArgs e = new CancelEventArgs();
|
||||
OnBeforeStartInternal(e);
|
||||
if (e.Cancel)
|
||||
return 2;
|
||||
|
||||
int exitCode = StartInternal();
|
||||
|
||||
Instance = null;
|
||||
@ -46,12 +265,251 @@ public class Application
|
||||
StopInternal(exitCode);
|
||||
}
|
||||
|
||||
private Dictionary<Union<Guid, string>, List<CommandEventHandler>> _commandEventHandlers = new Dictionary<Union<Guid, string>, List<CommandEventHandler>>();
|
||||
public void AttachCommandEventHandler(Union<Guid, string> commandId, CommandEventHandler handler)
|
||||
private string _UniqueName = null;
|
||||
public string UniqueName
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_UniqueName == null)
|
||||
{
|
||||
return ShortName;
|
||||
}
|
||||
return _UniqueName;
|
||||
}
|
||||
set
|
||||
{
|
||||
_UniqueName = value;
|
||||
}
|
||||
}
|
||||
|
||||
private string mvarBasePath = null;
|
||||
public string BasePath
|
||||
{
|
||||
get
|
||||
{
|
||||
if (mvarBasePath == null)
|
||||
{
|
||||
// Set up the base path for the current application. Should this be able to be
|
||||
// overridden with a switch (/basepath:...) ?
|
||||
mvarBasePath = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
|
||||
}
|
||||
return mvarBasePath;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string DataDirectoryName => ShortName;
|
||||
public string[] EnumerateDataPaths() => EnumerateDataPaths(FindFileOptions.All);
|
||||
public string[] EnumerateDataPaths(FindFileOptions options)
|
||||
{
|
||||
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)
|
||||
{
|
||||
// first look in the application root directory since this will override everything else
|
||||
list.Add(BasePath);
|
||||
|
||||
foreach (string dataDirName in dataDirectoryNames)
|
||||
{
|
||||
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[]
|
||||
{
|
||||
System.Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData),
|
||||
dataDirName
|
||||
}));
|
||||
|
||||
// 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
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//fixme: addd finddfileoption.userconfig, localdata, etc.
|
||||
// now for the user-writable locations...
|
||||
|
||||
foreach (string dataDirName in dataDirectoryNames)
|
||||
{
|
||||
// then look in ~/.universal-editor or C:\Users\USERNAME\AppData\Roaming\Mike Becker's Software\Universal Editor
|
||||
list.Add(String.Join(System.IO.Path.DirectorySeparatorChar.ToString(), new string[]
|
||||
{
|
||||
System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData),
|
||||
dataDirName
|
||||
}));
|
||||
}
|
||||
return list.ToArray();
|
||||
}
|
||||
|
||||
public string ShortName { get; set; }
|
||||
public virtual string[] AdditionalShortNames => null;
|
||||
|
||||
protected void PrintUsageStatement(CommandLineCommand command = null)
|
||||
{
|
||||
string shortOptionPrefix = CommandLine.ShortOptionPrefix ?? "-";
|
||||
string longOptionPrefix = CommandLine.LongOptionPrefix ?? "--";
|
||||
|
||||
Console.Write("usage: {0} ", ShortName);
|
||||
foreach (CommandLineOption option in CommandLine.Options)
|
||||
{
|
||||
PrintUsageStatementOption(option);
|
||||
}
|
||||
|
||||
if (CommandLine.HelpTextPrefix != null)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(CommandLine.HelpTextPrefix);
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
|
||||
bool printDescriptions = true;
|
||||
if (printDescriptions)
|
||||
{
|
||||
foreach (CommandLineOption option in CommandLine.Options)
|
||||
{
|
||||
Console.WriteLine(" {0}{1}", option.Abbreviation != '\0' ? String.Format("{0}{1}, {2}{3}", shortOptionPrefix, option.Abbreviation, longOptionPrefix, option.Name) : String.Format("{0}{1}", longOptionPrefix, option.Name), option.Description == null ? null : String.Format(" - {0}", option.Description));
|
||||
}
|
||||
}
|
||||
// Console.Write("[<global-options...>]");
|
||||
|
||||
if (command != null)
|
||||
{
|
||||
Console.WriteLine(" {0}{1}", command.Name, command.Description == null ? null : String.Format(" - {0}", command.Description));
|
||||
foreach (CommandLineOption option in command.Options)
|
||||
{
|
||||
PrintUsageStatementOption(option);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (CommandLine.Commands.Count > 0)
|
||||
{
|
||||
Console.WriteLine(" <command> [<command-options...>]");
|
||||
Console.WriteLine();
|
||||
|
||||
List<CommandLineCommand> commands = new List<CommandLineCommand>(CommandLine.Commands);
|
||||
commands.Sort((x, y) =>
|
||||
{
|
||||
return x.Name.CompareTo(y.Name);
|
||||
});
|
||||
foreach (CommandLineCommand command1 in commands)
|
||||
{
|
||||
Console.WriteLine(" {0}{1}", command1.Name, command1.Description == null ? null : String.Format(" - {0}", command1.Description));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CommandLine.HelpTextSuffix != null)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine(CommandLine.HelpTextSuffix);
|
||||
}
|
||||
}
|
||||
|
||||
private void PrintUsageStatementOption(CommandLineOption option)
|
||||
{
|
||||
Console.Write(" ");
|
||||
if (option.Optional)
|
||||
{
|
||||
Console.Write('[');
|
||||
}
|
||||
|
||||
string shortOptionPrefix = CommandLine.ShortOptionPrefix ?? "-";
|
||||
string longOptionPrefix = CommandLine.LongOptionPrefix ?? "--";
|
||||
|
||||
if (option.Abbreviation != '\0')
|
||||
{
|
||||
Console.Write("{0}{1}", shortOptionPrefix, option.Abbreviation);
|
||||
if (option.Type == CommandLineOptionValueType.Single)
|
||||
{
|
||||
Console.Write(" <value>");
|
||||
}
|
||||
else if (option.Type == CommandLineOptionValueType.Multiple)
|
||||
{
|
||||
Console.Write(" <value1>[,<value2>,...]");
|
||||
}
|
||||
|
||||
Console.Write(" | {0}{1}", longOptionPrefix, option.Name);
|
||||
if (option.Type == CommandLineOptionValueType.Single)
|
||||
{
|
||||
Console.Write("=<value>");
|
||||
}
|
||||
else if (option.Type == CommandLineOptionValueType.Multiple)
|
||||
{
|
||||
Console.Write("=<value1>[,<value2>,...]");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Write(longOptionPrefix ?? "--");
|
||||
Console.Write("{0}", option.Name);
|
||||
if (option.Type == CommandLineOptionValueType.Single)
|
||||
{
|
||||
Console.Write("=<value>");
|
||||
}
|
||||
else if (option.Type == CommandLineOptionValueType.Multiple)
|
||||
{
|
||||
Console.Write("=<value1>[,<value2>,...]");
|
||||
}
|
||||
}
|
||||
if (option.Optional)
|
||||
{
|
||||
Console.Write(']');
|
||||
}
|
||||
// Console.WriteLine();
|
||||
}
|
||||
protected virtual bool ShowCommandLineHelp(out int resultCode)
|
||||
{
|
||||
// bash: cd returns 2 if --help is specified OR invalid option selected, 1 if file not found
|
||||
PrintUsageStatement();
|
||||
resultCode = 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
internal void _EnableDisableCommand(Command command, bool enable)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal virtual Plugin[] GetAdditionalPlugins()
|
||||
{
|
||||
return new Plugin[0];
|
||||
}
|
||||
private Dictionary<Union<Guid, string>, List<EventHandler<CommandEventArgs>>> _commandEventHandlers = new Dictionary<Union<Guid, string>, List<EventHandler<CommandEventArgs>>>();
|
||||
public void AttachCommandEventHandler(Union<Guid, string> commandId, EventHandler<CommandEventArgs> handler)
|
||||
{
|
||||
if (!_commandEventHandlers.ContainsKey(commandId))
|
||||
{
|
||||
_commandEventHandlers[commandId] = new List<CommandEventHandler>();
|
||||
_commandEventHandlers[commandId] = new List<EventHandler<CommandEventArgs>>();
|
||||
}
|
||||
if (!_commandEventHandlers[commandId].Contains(handler))
|
||||
{
|
||||
@ -62,7 +520,7 @@ public class Application
|
||||
{
|
||||
if (_commandEventHandlers.ContainsKey(commandId))
|
||||
{
|
||||
foreach (CommandEventHandler handler in _commandEventHandlers[commandId])
|
||||
foreach (EventHandler<CommandEventArgs> handler in _commandEventHandlers[commandId])
|
||||
{
|
||||
handler(this, new CommandEventArgs(commandId));
|
||||
}
|
||||
|
||||
31
framework-dotnet/src/lib/MBS.Core/CardinalDirection.cs
Executable file
31
framework-dotnet/src/lib/MBS.Core/CardinalDirection.cs
Executable file
@ -0,0 +1,31 @@
|
||||
//
|
||||
// CardinalDirection.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2021 Mike Becker's Software
|
||||
//
|
||||
// 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.Core
|
||||
{
|
||||
public enum CardinalDirection
|
||||
{
|
||||
Top,
|
||||
Left,
|
||||
Bottom,
|
||||
Right
|
||||
}
|
||||
}
|
||||
@ -27,7 +27,7 @@ namespace MBS.Core.Collections
|
||||
{
|
||||
public static class ExtensionMethods
|
||||
{
|
||||
public static bool ContainsAny<T>(this IEnumerable enumerable, T[] item)
|
||||
public static bool ContainsAny<T>(this IEnumerable enumerable, IEnumerable<T> item)
|
||||
{
|
||||
foreach (object item1 in enumerable)
|
||||
{
|
||||
|
||||
@ -55,13 +55,20 @@ namespace MBS.Core.Collections.Generic
|
||||
return ((List<T>)(cacheOfT[obj][typeof(T)])).ToArray();
|
||||
}
|
||||
|
||||
public static void AddRange<T>(this IList<T> list, IEnumerable<T> items)
|
||||
public static void AddRange<T>(this ICollection<T> list, IEnumerable<T> items)
|
||||
{
|
||||
foreach (T item in items)
|
||||
{
|
||||
list.Add(item);
|
||||
}
|
||||
}
|
||||
public static void AddRange<TKey, TValue>(this ICollection<KeyValuePair<TKey, TValue>> list, IEnumerable<KeyValuePair<TKey, TValue>> items)
|
||||
{
|
||||
foreach (KeyValuePair<TKey, TValue> kvp in items)
|
||||
{
|
||||
list.Add(kvp);
|
||||
}
|
||||
}
|
||||
|
||||
public static T[] ToNullTerminatedArray<T>(this IEnumerable<T> enumerable) where T : class
|
||||
{
|
||||
|
||||
@ -1,31 +1,149 @@
|
||||
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// This file is part of editor-dotnet.
|
||||
// This file is part of MBS Framework for .NET Core.
|
||||
//
|
||||
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||
// 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.
|
||||
//
|
||||
// editor-dotnet is distributed in the hope that it will be useful,
|
||||
// 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 editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||
// along with MBS Framework for .NET Core. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace MBS.Core;
|
||||
|
||||
public class Command
|
||||
{
|
||||
public Command(Union<string, Guid> id, string title)
|
||||
public class CommandCollection
|
||||
: System.Collections.ObjectModel.Collection<Command>
|
||||
{
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Determines whether this command displays as checked.
|
||||
/// </summary>
|
||||
public bool Checked { get; set; } = false;
|
||||
/// <summary>
|
||||
/// The ID of the command, used to reference it in <see cref="CommandReferenceCommandItem"/>.
|
||||
/// </summary>
|
||||
public string ID { get; set; } = String.Empty;
|
||||
/// <summary>
|
||||
/// The title of the command (including mnemonic prefix, if applicable).
|
||||
/// </summary>
|
||||
public string Title { get; set; } = String.Empty;
|
||||
|
||||
private string mvarDefaultCommandID = String.Empty;
|
||||
public string DefaultCommandID { get { return mvarDefaultCommandID; } set { mvarDefaultCommandID = value; } }
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="StockType"/> that represents a predefined, platform-themed command.
|
||||
/// </summary>
|
||||
public StockType StockType { get; set; } = StockType.None;
|
||||
|
||||
private string mvarImageFileName = String.Empty;
|
||||
/// <summary>
|
||||
/// The file name of the image to be displayed on the command.
|
||||
/// </summary>
|
||||
public string ImageFileName { get { return mvarImageFileName; } set { mvarImageFileName = value; } }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// The child <see cref="CommandItem"/>s that are contained within this <see cref="Command"/>.
|
||||
/// </summary>
|
||||
public CommandItem.CommandItemCollection Items { get; } = new CommandItem.CommandItemCollection();
|
||||
|
||||
/// <summary>
|
||||
/// The event that is fired when the command is executed.
|
||||
/// </summary>
|
||||
public event EventHandler Executed;
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this <see cref="Command" /> is enabled in all <see cref="CommandBar" />s and <see cref="MenuBar" />s
|
||||
/// that reference it.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
|
||||
private bool _Enabled = true;
|
||||
public bool Enabled { get { return _Enabled; } set { _Enabled = value; Application.Instance._EnableDisableCommand(this, value); } }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether this <see cref="Command" /> is visible in all <see cref="CommandBar" />s and <see cref="MenuBar" />s
|
||||
/// that reference it.
|
||||
/// </summary>
|
||||
/// <value><c>true</c> if visible; otherwise, <c>false</c>.</value>
|
||||
public bool Visible { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Executes this <see cref="Command"/>.
|
||||
/// </summary>
|
||||
[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 Union<string, Guid> ID { get; }
|
||||
public string Title { get; set; }
|
||||
public IEnumerable<CommandItem> Items { get; set; }
|
||||
public override string ToString()
|
||||
{
|
||||
return String.Format("{0} [{1}]", ID, Title);
|
||||
}
|
||||
|
||||
private Dictionary<string, object> _extraData = new Dictionary<string, object>();
|
||||
public T GetExtraData<T>(string key, T defaultValue = default(T))
|
||||
{
|
||||
if (_extraData.ContainsKey(key))
|
||||
{
|
||||
if (_extraData[key] is T)
|
||||
{
|
||||
return (T)_extraData[key];
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public void SetExtraData<T>(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;
|
||||
}
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||
*
|
||||
* This file is part of editor-dotnet.
|
||||
*
|
||||
* editor-dotnet 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.
|
||||
*
|
||||
* editor-dotnet 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 editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace MBS.Core;
|
||||
|
||||
public delegate void CommandEventHandler(object sender, CommandEventArgs e);
|
||||
public class CommandEventArgs : EventArgs
|
||||
{
|
||||
public Union<Guid, string> CommandID { get; }
|
||||
|
||||
public CommandEventArgs(Union<Guid, string> commandId)
|
||||
{
|
||||
CommandID = commandId;
|
||||
}
|
||||
}
|
||||
56
framework-dotnet/src/lib/MBS.Core/CommandEventArgs.cs
Normal file
56
framework-dotnet/src/lib/MBS.Core/CommandEventArgs.cs
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace MBS.Core;
|
||||
|
||||
public class CommandEventArgs : EventArgs
|
||||
{
|
||||
public Command? Command { get; private set; }
|
||||
|
||||
private Dictionary<string, object> _NamedParameters = new Dictionary<string, object>();
|
||||
public T GetNamedParameter<T>(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 Union<Guid, string> CommandID { get; }
|
||||
|
||||
public CommandEventArgs(Union<Guid, string> commandId)
|
||||
{
|
||||
CommandID = commandId;
|
||||
}
|
||||
|
||||
public CommandEventArgs(Command command, KeyValuePair<string, object>[] namedParameters = null)
|
||||
{
|
||||
Command = command;
|
||||
if (namedParameters != null)
|
||||
{
|
||||
for (int i = 0; i < namedParameters.Length; i++)
|
||||
{
|
||||
_NamedParameters[namedParameters[i].Key] = namedParameters[i].Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,25 +1,79 @@
|
||||
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// This file is part of editor-dotnet.
|
||||
// This file is part of Mocha.NET.
|
||||
//
|
||||
// editor-dotnet is free software: you can redistribute it and/or modify
|
||||
// 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.
|
||||
//
|
||||
// editor-dotnet is distributed in the hope that it will be useful,
|
||||
// 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 editor-dotnet. If not, see <https://www.gnu.org/licenses/>.
|
||||
// along with Mocha.NET. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace MBS.Core;
|
||||
|
||||
/// <summary>
|
||||
/// The base class from which all command items derive.
|
||||
/// </summary>
|
||||
public abstract class CommandItem
|
||||
{
|
||||
public string InsertAfterID { get; set; } = null;
|
||||
public string InsertBeforeID { get; set; } = null;
|
||||
|
||||
public class CommandItemCollection
|
||||
: System.Collections.ObjectModel.Collection<CommandItem>
|
||||
{
|
||||
public int IndexOf(string value)
|
||||
{
|
||||
for (int i = 0; i < Count; i++)
|
||||
{
|
||||
if (this[i] is CommandReferenceCommandItem crci)
|
||||
{
|
||||
if (crci.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 CommandPlaceholderCommandItem : CommandItem
|
||||
{
|
||||
private string mvarPlaceholderID = String.Empty;
|
||||
public string PlaceholderID { get { return mvarPlaceholderID; } set { mvarPlaceholderID = value; } }
|
||||
|
||||
public CommandPlaceholderCommandItem(string placeholderID)
|
||||
{
|
||||
mvarPlaceholderID = placeholderID;
|
||||
}
|
||||
}
|
||||
|
||||
public class GroupCommandItem : CommandItem
|
||||
{
|
||||
public CommandItemCollection Items { get; } = new CommandItemCollection();
|
||||
}
|
||||
115
framework-dotnet/src/lib/MBS.Core/Context.cs
Normal file
115
framework-dotnet/src/lib/MBS.Core/Context.cs
Normal file
@ -0,0 +1,115 @@
|
||||
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace MBS.Core;
|
||||
|
||||
public class Context
|
||||
{
|
||||
public class ContextCollection
|
||||
: System.Collections.ObjectModel.Collection<Context>
|
||||
{
|
||||
private Dictionary<Guid, Context> _ItemsByID = new Dictionary<Guid, Context>();
|
||||
|
||||
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<string, List<EventHandler>> _CommandEventHandlers = new Dictionary<string, List<EventHandler>>();
|
||||
/// <summary>
|
||||
/// Attachs an event handler for the command with the ID specified by <paramref name="commandID" />.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if command event handler was attached, <c>false</c> otherwise.</returns>
|
||||
/// <param name="commandID">The ID of the <see cref="Command" /> for which to attach an event handler.</param>
|
||||
/// <param name="handler">The event handler to invoke when the <see cref="Command" /> is executed.</param>
|
||||
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<EventHandler>());
|
||||
}
|
||||
if (!_CommandEventHandlers[commandID].Contains(handler))
|
||||
{
|
||||
_CommandEventHandlers[commandID].Add(handler);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// Executes the command (i.e., calls all attached <see cref="EventHandler" />s for the <see cref="Command" />) with
|
||||
/// the given <paramref name="commandID" />, passing in the given parameters in an instance of <see cref="CommandEventArgs" />.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if command was executed, <c>false</c> otherwise.</returns>
|
||||
/// <param name="commandID">Command identifier.</param>
|
||||
/// <param name="namedParameters">Named parameters.</param>
|
||||
public bool ExecuteCommand(string commandID, KeyValuePair<string, object>[] 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;
|
||||
}
|
||||
}
|
||||
61
framework-dotnet/src/lib/MBS.Core/Extensibility/Feature.cs
Normal file
61
framework-dotnet/src/lib/MBS.Core/Extensibility/Feature.cs
Normal file
@ -0,0 +1,61 @@
|
||||
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
namespace MBS.Core.Extensibility;
|
||||
|
||||
public class Feature
|
||||
{
|
||||
public class FeatureCollection
|
||||
: System.Collections.ObjectModel.Collection<Feature>
|
||||
{
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
181
framework-dotnet/src/lib/MBS.Core/Extensibility/Plugin.cs
Normal file
181
framework-dotnet/src/lib/MBS.Core/Extensibility/Plugin.cs
Normal file
@ -0,0 +1,181 @@
|
||||
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
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();
|
||||
|
||||
/// <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 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<TPlugin>(bool resetCache = false) where TPlugin : Plugin
|
||||
{
|
||||
Plugin[] plugins = Get(resetCache);
|
||||
return plugins.OfType<TPlugin>().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<Plugin> plugins = new System.Collections.Generic.List<Plugin>();
|
||||
for (int i = 0; i < types.Length; i++)
|
||||
{
|
||||
if (types[i].IsAbstract)
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
/*
|
||||
if (types[i].IsSubclassOf(typeof(ICustomPlugin)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
Plugin plg = (Plugin)types[i].Assembly.CreateInstance(types[i].FullName);
|
||||
plugins.Add(plg);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if (Application.Instance != null)
|
||||
{
|
||||
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<TPlugin>(Feature[] providedFeatures, bool resetCache = false) where TPlugin : Plugin
|
||||
{
|
||||
Plugin[] plugins = Get(providedFeatures, resetCache);
|
||||
return plugins.OfType<TPlugin>().ToArray();
|
||||
}
|
||||
public static Plugin[] Get(Feature[] providedFeatures, bool resetCache = false)
|
||||
{
|
||||
System.Collections.Generic.List<Plugin> list = new System.Collections.Generic.List<Plugin>();
|
||||
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<TPlugin>(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;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
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<T>(PropertyValueRequestedEventArgs<T> e)
|
||||
{
|
||||
base.OnPropertyValueRequested(e);
|
||||
}
|
||||
}
|
||||
187
framework-dotnet/src/lib/MBS.Core/Extensibility/PropertyBag.cs
Normal file
187
framework-dotnet/src/lib/MBS.Core/Extensibility/PropertyBag.cs
Normal file
@ -0,0 +1,187 @@
|
||||
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
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<T> : 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<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;
|
||||
}
|
||||
}
|
||||
45
framework-dotnet/src/lib/MBS.Core/FindFileOptions.cs
Normal file
45
framework-dotnet/src/lib/MBS.Core/FindFileOptions.cs
Normal file
@ -0,0 +1,45 @@
|
||||
//
|
||||
// FindFileOptions.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2022 Mike Becker's Software
|
||||
//
|
||||
// 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.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Controls the behavior of relative file resolution.
|
||||
/// </summary>
|
||||
[Flags()]
|
||||
public enum FindFileOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns all matching fully-qualified file paths across all global,
|
||||
/// application, and user directories.
|
||||
/// </summary>
|
||||
All = 1,
|
||||
/// <summary>
|
||||
/// Returns only file paths that are writable by the user (i.e., in the
|
||||
/// user's local or roaming data directory).
|
||||
/// </summary>
|
||||
UserWritable = 2,
|
||||
/// <summary>
|
||||
/// Allows the user to create a file if it does not exist (i.e., returns
|
||||
/// a file name even if it does not exist)
|
||||
/// </summary>
|
||||
Create = 4
|
||||
}
|
||||
35
framework-dotnet/src/lib/MBS.Core/IO/DirectoryExtensions.cs
Normal file
35
framework-dotnet/src/lib/MBS.Core/IO/DirectoryExtensions.cs
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
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<string>(ref result, result.Length + filenames.Length);
|
||||
Array.Copy(filenames, 0, result, j, filenames.Length);
|
||||
j += filenames.Length;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@ -164,6 +164,11 @@ namespace MBS.Core
|
||||
public const string DefaultAlphabet = "_-0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
public const string DefaultAlphabetNoSpecialChars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
public const string CapitalAlphabetNoSpecialChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
public const string CapitalAlphanumeric = "_-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
public const string CapitalAlphanumericNoSpecialChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
private static readonly CryptoRandom Random = new CryptoRandom();
|
||||
/// <summary>
|
||||
///
|
||||
|
||||
@ -0,0 +1,48 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace MBS.Core.Reflection;
|
||||
|
||||
public static class TypeExtensions
|
||||
{
|
||||
public static bool IsSubclassOfGeneric(this Type toCheck, Type generic)
|
||||
{
|
||||
// thanks https://stackoverflow.com/a/457708
|
||||
|
||||
while (toCheck != null && toCheck != typeof(object))
|
||||
{
|
||||
var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
|
||||
if (generic == cur)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Type[] intfs = toCheck.GetInterfaces();
|
||||
foreach (Type intf in intfs)
|
||||
{
|
||||
// !!! HACK HACK HACK !!!
|
||||
bool hack = intf.Namespace.Equals(generic.Namespace) && intf.Name.Equals(generic.Name);
|
||||
if (hack)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
toCheck = toCheck.BaseType;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static PropertyInfo? GetProperty(this MethodBase methodBase)
|
||||
{
|
||||
Type declType = methodBase.DeclaringType;
|
||||
foreach (PropertyInfo pi in declType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
|
||||
{
|
||||
if (pi.GetMethod == methodBase
|
||||
|| pi.SetMethod == methodBase)
|
||||
{
|
||||
return pi;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@ -129,12 +129,12 @@ public class TypeLoader
|
||||
}
|
||||
|
||||
private static Type[] mvarAvailableTypes = null;
|
||||
public static T[] GetAvailableTypes<T>(Assembly[] additionalAssemblies = null) where T : class
|
||||
public static T[] GetAvailableTypes<T>(Assembly[] additionalAssemblies = null, bool resetCache = false) where T : class
|
||||
{
|
||||
Type[] ts = null;
|
||||
try
|
||||
{
|
||||
ts = GetAvailableTypes(new Type[] { typeof(T) }, additionalAssemblies);
|
||||
ts = GetAvailableTypes(new Type[] { typeof(T) }, additionalAssemblies, resetCache);
|
||||
}
|
||||
catch (ReflectionTypeLoadException ex)
|
||||
{
|
||||
@ -156,8 +156,12 @@ public class TypeLoader
|
||||
}
|
||||
return list.ToArray();
|
||||
}
|
||||
public static Type[] GetAvailableTypes(Type[] inheritsFrom = null, Assembly[] additionalAssemblies = null)
|
||||
public static Type[] GetAvailableTypes(Type[] inheritsFrom = null, Assembly[] additionalAssemblies = null, bool resetCache = false)
|
||||
{
|
||||
if (resetCache)
|
||||
{
|
||||
mvarAvailableTypes = null;
|
||||
}
|
||||
if (mvarAvailableTypes == null)
|
||||
{
|
||||
List<Type> types = new List<Type>();
|
||||
@ -197,16 +201,30 @@ public class TypeLoader
|
||||
}
|
||||
}
|
||||
mvarAvailableTypes = types.ToArray();
|
||||
/*
|
||||
foreach (Type t in mvarAvailableTypes)
|
||||
{
|
||||
Console.WriteLine("Type load: {0}", t.FullName);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
if (inheritsFrom != null)
|
||||
{
|
||||
List<Type> retval = new List<Type>();
|
||||
for (int iTyp = 0; iTyp < mvarAvailableTypes.Length; iTyp++)
|
||||
foreach (Type t in mvarAvailableTypes)
|
||||
{
|
||||
for (int jInh = 0; jInh < inheritsFrom.Length; jInh++)
|
||||
string typeFullName = t.FullName;
|
||||
foreach (Type inheritsFromType in inheritsFrom)
|
||||
{
|
||||
if (mvarAvailableTypes[iTyp].IsSubclassOf(inheritsFrom[jInh])) retval.Add(mvarAvailableTypes[iTyp]);
|
||||
if (t.FullName.Contains("Mini."))
|
||||
{
|
||||
// Console.WriteLine(inheritsFromType.FullName + " ? inherits ? " + t.FullName);
|
||||
}
|
||||
if (t.IsSubclassOf(inheritsFromType))
|
||||
{
|
||||
retval.Add(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
return retval.ToArray();
|
||||
|
||||
137
framework-dotnet/src/lib/MBS.Core/StockType.cs
Normal file
137
framework-dotnet/src/lib/MBS.Core/StockType.cs
Normal file
@ -0,0 +1,137 @@
|
||||
// Copyright (C) 2024 Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
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
|
||||
}
|
||||
@ -19,6 +19,8 @@
|
||||
// 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.Net.Http.Headers;
|
||||
|
||||
namespace MBS.Core;
|
||||
|
||||
public static class StreamExtensions
|
||||
@ -96,4 +98,33 @@ public static class StreamExtensions
|
||||
}
|
||||
_streamPositions[st].Push(st.Position);
|
||||
}
|
||||
|
||||
private const long BUFFER_SIZE=4096;
|
||||
public static byte[] ReadToEnd(this Stream st)
|
||||
{
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
byte[] output = new byte[0];
|
||||
int i = 0;
|
||||
bool done = false;
|
||||
while (!done)
|
||||
{
|
||||
int length = st.Read(buffer, 0, buffer.Length);
|
||||
if (length == 0)
|
||||
{
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (length < BUFFER_SIZE)
|
||||
{
|
||||
Array.Resize<byte>(ref buffer, length);
|
||||
done = true;
|
||||
}
|
||||
|
||||
Array.Resize<byte>(ref output, output.Length + buffer.Length);
|
||||
Array.Copy(buffer, 0, output, i, buffer.Length);
|
||||
i += buffer.Length;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user