various improvements to Framework functionality
This commit is contained in:
parent
a118fb3eef
commit
ab32a58e05
@ -21,6 +21,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using MBS.Framework.Collections.Generic;
|
||||||
|
|
||||||
namespace MBS.Framework
|
namespace MBS.Framework
|
||||||
{
|
{
|
||||||
@ -63,6 +64,13 @@ namespace MBS.Framework
|
|||||||
/// </value>
|
/// </value>
|
||||||
public static Application Instance { get; set; } = null;
|
public static Application Instance { get; set; } = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Searches for the file with the given <paramref name="filename" /> and
|
||||||
|
/// returns all matching fully-qualified file names.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The files.</returns>
|
||||||
|
/// <param name="filename">Filename.</param>
|
||||||
|
/// <param name="options">Options.</param>
|
||||||
public string[] FindFiles(string filename, FindFileOptions options = FindFileOptions.All)
|
public string[] FindFiles(string filename, FindFileOptions options = FindFileOptions.All)
|
||||||
{
|
{
|
||||||
if (filename.StartsWith("~/"))
|
if (filename.StartsWith("~/"))
|
||||||
@ -82,9 +90,16 @@ namespace MBS.Framework
|
|||||||
}
|
}
|
||||||
return files.ToArray();
|
return files.ToArray();
|
||||||
}
|
}
|
||||||
public string FindFile(string fileName, FindFileOptions options = FindFileOptions.All)
|
/// <summary>
|
||||||
|
/// Searches for the file with the given <paramref name="filename" /> and
|
||||||
|
/// returns the first matching fully-qualified file name.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The files.</returns>
|
||||||
|
/// <param name="filename">Filename.</param>
|
||||||
|
/// <param name="options">Options.</param>
|
||||||
|
public string FindFile(string filename, FindFileOptions options = FindFileOptions.All)
|
||||||
{
|
{
|
||||||
string[] files = FindFiles(fileName, options);
|
string[] files = FindFiles(filename, options);
|
||||||
if (files.Length > 0)
|
if (files.Length > 0)
|
||||||
{
|
{
|
||||||
return files[0];
|
return files[0];
|
||||||
@ -92,8 +107,16 @@ namespace MBS.Framework
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a collection of <see cref="EventFilter" />s registered for this
|
||||||
|
/// <see cref="Application" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The event filters.</value>
|
||||||
public EventFilter.EventFilterCollection EventFilters { get; } = new EventFilter.EventFilterCollection();
|
public EventFilter.EventFilterCollection EventFilters { get; } = new EventFilter.EventFilterCollection();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finds the command with the given <paramref name="commandID" />.
|
||||||
|
/// </summary>
|
||||||
protected virtual Command FindCommandInternal(string commandID)
|
protected virtual Command FindCommandInternal(string commandID)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@ -125,10 +148,18 @@ namespace MBS.Framework
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finds the <see cref="Context" /> with the given
|
||||||
|
/// <paramref name="contextID" />.
|
||||||
|
/// </summary>
|
||||||
protected virtual Context FindContextInternal(Guid contextID)
|
protected virtual Context FindContextInternal(Guid contextID)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Finds the <see cref="Context" /> with the given
|
||||||
|
/// <paramref name="contextID" />.
|
||||||
|
/// </summary>
|
||||||
public Context FindContext(Guid contextID)
|
public Context FindContext(Guid contextID)
|
||||||
{
|
{
|
||||||
Context ctx = FindContextInternal(contextID);
|
Context ctx = FindContextInternal(contextID);
|
||||||
@ -303,10 +334,221 @@ namespace MBS.Framework
|
|||||||
Initialized = true;
|
Initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public event ApplicationActivatedEventHandler Activated;
|
||||||
|
protected virtual void OnActivated(ApplicationActivatedEventArgs e)
|
||||||
|
{
|
||||||
|
Activated?.Invoke(this, e);
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual int StartInternal()
|
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, null, cmd.Options))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cline.Command = cmd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// assume filename
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (/* intentionally left blank */; i < args.Length; i++)
|
||||||
|
{
|
||||||
|
cline.FileNames.Add(args[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OnActivated(new ApplicationActivatedEventArgs(true, ApplicationActivationType.CommandLineLaunch, cline));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void PrintUsageStatement(CommandLineCommand command = null)
|
||||||
|
{
|
||||||
|
Console.Write("usage: {0} ", ShortName);
|
||||||
|
foreach (CommandLineOption option in CommandLine.Options)
|
||||||
|
{
|
||||||
|
PrintUsageStatementOption(option);
|
||||||
|
}
|
||||||
|
Console.WriteLine();
|
||||||
|
// 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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];
|
||||||
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
option.Value = value;
|
||||||
|
}
|
||||||
|
list.Add(option);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list.Add(new CommandLineOption() { Name = name });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// we have reached a non-option
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public int Start()
|
public int Start()
|
||||||
{
|
{
|
||||||
if (Application.Instance == null)
|
if (Application.Instance == null)
|
||||||
|
|||||||
41
MBS.Framework/ApplicationActivatedEvent.cs
Normal file
41
MBS.Framework/ApplicationActivatedEvent.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// ApplicationActivatedEvent.cs
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Mike Becker <alcexhim@gmail.com>
|
||||||
|
//
|
||||||
|
// Copyright (c) 2019 Mike Becker
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MBS.Framework
|
||||||
|
{
|
||||||
|
public class ApplicationActivatedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public bool FirstRun { get; } = true;
|
||||||
|
public CommandLine CommandLine { get; } = null;
|
||||||
|
public int ExitCode { get; set; } = 0;
|
||||||
|
public ApplicationActivationType ActivationType { get; } = ApplicationActivationType.Launch;
|
||||||
|
|
||||||
|
public ApplicationActivatedEventArgs(bool firstRun, ApplicationActivationType activationType, CommandLine commandLine)
|
||||||
|
{
|
||||||
|
FirstRun = firstRun;
|
||||||
|
ActivationType = activationType;
|
||||||
|
CommandLine = commandLine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public delegate void ApplicationActivatedEventHandler(object sender, ApplicationActivatedEventArgs e);
|
||||||
|
}
|
||||||
276
MBS.Framework/ApplicationActivationType.cs
Normal file
276
MBS.Framework/ApplicationActivationType.cs
Normal file
@ -0,0 +1,276 @@
|
|||||||
|
//
|
||||||
|
// ActivationType.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.Framework
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Specifies the type of activation when the application is started
|
||||||
|
/// from layout on a layout-aware operating system.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>
|
||||||
|
/// Values are mutually exclusive and cannot be combined. Each one
|
||||||
|
/// relates to a different type of activation, and an app instance can
|
||||||
|
/// be activated in only one way at a time.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// The activation types are based on those supported by Windows 11,
|
||||||
|
/// however the enum values are operating system agnostic. Translation
|
||||||
|
/// (e.g. by an Engine) must be done before calls to operating system
|
||||||
|
/// specific methods are made.
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// On non-layout-aware operating systems, such as Linux, a wrapper
|
||||||
|
/// executable (bootstrapper) must be used to invoke the app activation
|
||||||
|
/// with the desired <see cref="ApplicationActivationType" />.
|
||||||
|
/// </para>
|
||||||
|
/// </remarks>
|
||||||
|
public enum ApplicationActivationType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The activation type was not specified.
|
||||||
|
/// </summary>
|
||||||
|
Unspecified = -1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The user wants to manage appointments that are provided by the
|
||||||
|
/// app.
|
||||||
|
/// </summary>
|
||||||
|
AppointmentsProvider,
|
||||||
|
/// <summary>
|
||||||
|
/// The app was activated as a barcode scanner provider.
|
||||||
|
/// </summary>
|
||||||
|
BarcodeScannerProvider,
|
||||||
|
/// <summary>
|
||||||
|
/// The user wants to save a file for which the app provides content
|
||||||
|
/// management.
|
||||||
|
/// </summary>
|
||||||
|
CachedFileUpdater,
|
||||||
|
/// <summary>
|
||||||
|
/// The app captures photos or video from an attached camera.
|
||||||
|
/// </summary>
|
||||||
|
CameraSettings,
|
||||||
|
/// <summary>
|
||||||
|
/// The app was launched from the command line.
|
||||||
|
/// </summary>
|
||||||
|
CommandLineLaunch,
|
||||||
|
/// <summary>
|
||||||
|
/// Reserved for system use. Introduced in Windows 10, version 1507
|
||||||
|
/// (10.0.10240).
|
||||||
|
/// </summary>
|
||||||
|
ComponentUI,
|
||||||
|
/// <summary>
|
||||||
|
/// The user wants to handle calls or messages for the phone number
|
||||||
|
/// of a contact that is provided by the app.
|
||||||
|
/// </summary>
|
||||||
|
Contact,
|
||||||
|
/// <summary>
|
||||||
|
/// The app was launched from the My People UI. Note: introduced in
|
||||||
|
/// Windows 10, version 1703 (10.0.15063), but not used. Now used
|
||||||
|
/// starting with Windows 10, version 1709 (10.0.16299).
|
||||||
|
/// </summary>
|
||||||
|
ContactPanel,
|
||||||
|
/// <summary>
|
||||||
|
/// The user wants to pick contacts.
|
||||||
|
/// </summary>
|
||||||
|
ContactPicker,
|
||||||
|
/// <summary>
|
||||||
|
/// The app handles AutoPlay.
|
||||||
|
/// </summary>
|
||||||
|
Device,
|
||||||
|
/// <summary>
|
||||||
|
/// This app was activated as a result of pairing a device.
|
||||||
|
/// </summary>
|
||||||
|
DevicePairing,
|
||||||
|
/// <summary>
|
||||||
|
/// This app was launched by another app on a different device by
|
||||||
|
/// using the DIAL protocol.Introduced in Windows 10, version 1507
|
||||||
|
/// (10.0.10240).
|
||||||
|
/// </summary>
|
||||||
|
DialReceiver,
|
||||||
|
/// <summary>
|
||||||
|
/// An app launched a file whose file type this app is registered to
|
||||||
|
/// handle.
|
||||||
|
/// </summary>
|
||||||
|
File,
|
||||||
|
/// <summary>
|
||||||
|
/// The user wants to pick files that are provided by the app.
|
||||||
|
/// </summary>
|
||||||
|
FileOpenPicker,
|
||||||
|
/// <summary>
|
||||||
|
/// Reserved for system use. Introduced in Windows 10, version 1607
|
||||||
|
/// (10.0.14393).
|
||||||
|
/// </summary>
|
||||||
|
FilePickerExperience,
|
||||||
|
/// <summary>
|
||||||
|
/// The user wants to save a file and selected the app as the
|
||||||
|
/// location.
|
||||||
|
/// </summary>
|
||||||
|
FileSavePicker,
|
||||||
|
/// <summary>
|
||||||
|
/// The app was activated because it was launched by the OS due to a
|
||||||
|
/// game's request for Xbox-specific UI. Introduced in Windows 10,
|
||||||
|
/// version 1703 (10.0.15063).
|
||||||
|
/// </summary>
|
||||||
|
GameUIProvider,
|
||||||
|
/// <summary>
|
||||||
|
/// The user launched the app or tapped a content tile.
|
||||||
|
/// </summary>
|
||||||
|
Launch,
|
||||||
|
/// <summary>
|
||||||
|
/// The app was activated as the lock screen. Introduced in Windows
|
||||||
|
/// 10, version 1507 (10.0.10240).
|
||||||
|
/// </summary>
|
||||||
|
LockScreen,
|
||||||
|
/// <summary>
|
||||||
|
/// Windows Store only. The app launches a call from the lock screen.
|
||||||
|
/// If the user wants to accept the call, the app displays its call
|
||||||
|
/// UI directly on the lock screen without requiring the user to
|
||||||
|
/// unlock. A lock-screen call is a special type of launch
|
||||||
|
/// activation.
|
||||||
|
/// </summary>
|
||||||
|
LockScreenCall,
|
||||||
|
/// <summary>
|
||||||
|
/// Reserved for system use. Introduced in Windows 10, version 1703
|
||||||
|
/// (10.0.15063).
|
||||||
|
/// </summary>
|
||||||
|
LockScreenComponent,
|
||||||
|
/// <summary>
|
||||||
|
/// The app was activated in response to a phone call.
|
||||||
|
/// </summary>
|
||||||
|
PhoneCallActivation,
|
||||||
|
/// <summary>
|
||||||
|
/// Windows Phone only. The app was activated after the completion of
|
||||||
|
/// a picker.
|
||||||
|
/// </summary>
|
||||||
|
PickerReturned,
|
||||||
|
/// <summary>
|
||||||
|
/// Windows Phone only. The app was activated after the app was
|
||||||
|
/// suspended for a file picker operation.
|
||||||
|
/// </summary>
|
||||||
|
PickFileContinuation,
|
||||||
|
/// <summary>
|
||||||
|
/// Windows Phone only. The app was activated after the app was
|
||||||
|
/// suspended for a folder picker operation.
|
||||||
|
/// </summary>
|
||||||
|
PickFolderContinuation,
|
||||||
|
/// <summary>
|
||||||
|
/// Windows Phone only. The app was activated after the app was
|
||||||
|
/// suspended for a file save picker operation.
|
||||||
|
/// </summary>
|
||||||
|
PickSaveFileContinuation,
|
||||||
|
/// <summary>
|
||||||
|
/// This app was launched by another app to provide a customized
|
||||||
|
/// printing experience for a 3D printer. Introduced in Windows 10,
|
||||||
|
/// version 1507 (10.0.10240).
|
||||||
|
/// </summary>
|
||||||
|
Print3DWorkflow,
|
||||||
|
/// <summary>
|
||||||
|
/// The app was activated as a print workflow job UI extension.
|
||||||
|
/// </summary>
|
||||||
|
PrintSupportJobUI,
|
||||||
|
/// <summary>
|
||||||
|
/// The app was activated as a print support settings UI extension.
|
||||||
|
/// </summary>
|
||||||
|
PrintSupportSettingsUI,
|
||||||
|
/// <summary>
|
||||||
|
/// The app handles print tasks.
|
||||||
|
/// </summary>
|
||||||
|
PrintTaskSettings,
|
||||||
|
/// <summary>
|
||||||
|
/// The app was activated because the user is printing to a printer
|
||||||
|
/// that has a Print Workflow Application associated with it which
|
||||||
|
/// has requested user input.
|
||||||
|
/// </summary>
|
||||||
|
PrintWorkflowForegroundTask,
|
||||||
|
/// <summary>
|
||||||
|
/// An app launched a URI whose scheme name this app is registered to
|
||||||
|
/// handle.
|
||||||
|
/// </summary>
|
||||||
|
Protocol,
|
||||||
|
/// <summary>
|
||||||
|
/// The app was launched by another app with the expectation that it
|
||||||
|
/// will return a result back to the caller. Introduced in Windows
|
||||||
|
/// 10, version 1507 (10.0.10240).
|
||||||
|
/// </summary>
|
||||||
|
ProtocolForResults,
|
||||||
|
/// <summary>
|
||||||
|
/// Windows Store only. The user launched the restricted app.
|
||||||
|
/// </summary>
|
||||||
|
RestrictedLaunch,
|
||||||
|
/// <summary>
|
||||||
|
/// The user wants to search with the app.
|
||||||
|
/// </summary>
|
||||||
|
Search,
|
||||||
|
/// <summary>
|
||||||
|
/// The app is activated as a target for share operations.
|
||||||
|
/// </summary>
|
||||||
|
ShareTarget,
|
||||||
|
/// <summary>
|
||||||
|
/// The app was activated because the app is specified to launch at
|
||||||
|
/// system startup or user log-in. Introduced in Windows 10, version
|
||||||
|
/// 1703 (10.0.15063).
|
||||||
|
/// </summary>
|
||||||
|
StartupTask,
|
||||||
|
/// <summary>
|
||||||
|
/// The app was activated when a user tapped on the body of a toast
|
||||||
|
/// notification or performed an action inside a toast notification.
|
||||||
|
/// Introduced in Windows 10, version 1507 (10.0.10240).
|
||||||
|
/// </summary>
|
||||||
|
ToastNotification,
|
||||||
|
/// <summary>
|
||||||
|
/// The app was launched to handle the user interface for account
|
||||||
|
/// management. In circumstances where the system would have shown
|
||||||
|
/// the default system user interface, it instead has invoked your
|
||||||
|
/// app with the UserDataAccountProvider contract. The activation
|
||||||
|
/// payload contains information about the type of operation being
|
||||||
|
/// requested and all the information necessary to replicate the
|
||||||
|
/// system-provided user interface. This activation kind is limited
|
||||||
|
/// to 1st party apps. To use this field, you must add the
|
||||||
|
/// userDataAccountsProvider capability in your app's package
|
||||||
|
/// manifest. For more info see App capability declarations.
|
||||||
|
/// Introduced in Windows 10, version 1607 (10.0.14393).
|
||||||
|
/// </summary>
|
||||||
|
UserDataAccountsProvider,
|
||||||
|
/// <summary>
|
||||||
|
/// The app was activated as the result of a voice command.
|
||||||
|
/// </summary>
|
||||||
|
VoiceCommand,
|
||||||
|
/// <summary>
|
||||||
|
/// The app is a VPN foreground app that was activated by the plugin.
|
||||||
|
/// For more details, see VpnChannel.ActivateForeground.
|
||||||
|
/// </summary>
|
||||||
|
VpnForeground,
|
||||||
|
/// <summary>
|
||||||
|
/// The app was activated to perform a Wallet operation.
|
||||||
|
/// </summary>
|
||||||
|
WalletAction,
|
||||||
|
/// <summary>
|
||||||
|
/// The app was activated by a web account provider.
|
||||||
|
/// </summary>
|
||||||
|
WebAccountProvider,
|
||||||
|
/// <summary>
|
||||||
|
/// The app was activated after the app was suspended for a web
|
||||||
|
/// authentication broker operation.
|
||||||
|
/// </summary>
|
||||||
|
WebAuthenticationBrokerContinuation
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -19,10 +19,23 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace MBS.Framework
|
namespace MBS.Framework
|
||||||
{
|
{
|
||||||
public static class ArrayExtensions
|
public static class ArrayExtensions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Splits the <paramref name="array" /> into two arrays at the specified
|
||||||
|
/// <paramref name="index" />, where <paramref name="left" /> contains the
|
||||||
|
/// elements before <paramref name="index" /> and <paramref name="right" />
|
||||||
|
/// contains the elements after <paramref name="index" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="array">The array to split.</param>
|
||||||
|
/// <param name="index">The index at which to split the array.</param>
|
||||||
|
/// <param name="left">The array containing elements before the split point.</param>
|
||||||
|
/// <param name="right">The array containing elements after the split point.</param>
|
||||||
|
/// <typeparam name="T">The <see cref="Type" /> of elements in the array.</typeparam>
|
||||||
public static void Bisect<T>(this T[] array, int index, out T[] left, out T[] right)
|
public static void Bisect<T>(this T[] array, int index, out T[] left, out T[] right)
|
||||||
{
|
{
|
||||||
left = new T[index];
|
left = new T[index];
|
||||||
@ -55,12 +68,25 @@ namespace MBS.Framework
|
|||||||
Array.Copy(sourceArray, 0, destinationArray, start, sourceArray.Length);
|
Array.Copy(sourceArray, 0, destinationArray, start, sourceArray.Length);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool Matches<T>(this T[] array1, T[] array2)
|
/// <summary>
|
||||||
|
/// Determines if <paramref name="array1" /> and <paramref name="array2" />
|
||||||
|
/// contain the same elements.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>
|
||||||
|
/// <see langword="true" /> if both arrays contain the same elements,
|
||||||
|
/// <see langword="false" /> otherwise.</returns>
|
||||||
|
/// <param name="array1">The first array to search.</param>
|
||||||
|
/// <param name="array2">The second array to search.</param>
|
||||||
|
/// <typeparam name="T">The 1st type parameter.</typeparam>
|
||||||
|
public static bool Matches<T>(this IList<T> array1, IList<T> array2)
|
||||||
{
|
{
|
||||||
if (array1.Length != array2.Length)
|
if (array1.Count != array2.Count)
|
||||||
|
{
|
||||||
|
// short-circuit if arrays have different lengths
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < array1.Length; i++)
|
for (int i = 0; i < array1.Count; i++)
|
||||||
{
|
{
|
||||||
if (!array1[i].Equals(array2[i]))
|
if (!array1[i].Equals(array2[i]))
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -40,10 +40,20 @@ namespace MBS.Framework
|
|||||||
public CommandLineParser Parser { get; set; } = null;
|
public CommandLineParser Parser { get; set; } = null;
|
||||||
|
|
||||||
public CommandLineOption.CommandLineOptionCollection Options { get; } = new CommandLineOption.CommandLineOptionCollection();
|
public CommandLineOption.CommandLineOptionCollection Options { get; } = new CommandLineOption.CommandLineOptionCollection();
|
||||||
|
public CommandLineCommand.CommandLineCommandCollection Commands { get; } = new CommandLineCommand.CommandLineCommandCollection();
|
||||||
|
public CommandLineCommand Command { get; internal set; } = null;
|
||||||
|
public string ShortOptionPrefix { get; set; } = null;
|
||||||
|
public string LongOptionPrefix { get; set; } = null;
|
||||||
|
|
||||||
public CommandLine()
|
public CommandLine()
|
||||||
{
|
{
|
||||||
Options.Add(new CommandLineOption() { Name = "activation-type", Description = "The type of activation for this app", Type = CommandLineOptionValueType.Single });
|
string[] args = Environment.GetCommandLineArgs();
|
||||||
|
string[] args2 = new string[args.Length - 1];
|
||||||
|
Array.Copy(args, 1, args2, 0, args2.Length);
|
||||||
|
Arguments = args2;
|
||||||
|
|
||||||
|
Options.Add(new CommandLineOption() { Abbreviation = 'A', Name = "activation-type", Description = "The type of activation for this app", Type = CommandLineOptionValueType.Single, Optional = true });
|
||||||
|
Options.Add(new CommandLineOption() { Name = "help", Description = "Displays help", Type = CommandLineOptionValueType.None, Optional = true });
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
|||||||
59
MBS.Framework/CommandLineCommand.cs
Normal file
59
MBS.Framework/CommandLineCommand.cs
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
//
|
||||||
|
// CommandLineCommand.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;
|
||||||
|
using MBS.Framework.Collections.Generic;
|
||||||
|
|
||||||
|
namespace MBS.Framework
|
||||||
|
{
|
||||||
|
public class CommandLineCommand
|
||||||
|
{
|
||||||
|
public class CommandLineCommandCollection
|
||||||
|
: System.Collections.ObjectModel.Collection<CommandLineCommand>
|
||||||
|
{
|
||||||
|
public CommandLineCommand this[string name]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
foreach (CommandLineCommand item in this)
|
||||||
|
{
|
||||||
|
if (item.Name == name)
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; set; } = null;
|
||||||
|
public string Description { get; set; } = null;
|
||||||
|
|
||||||
|
public CommandLineOption.CommandLineOptionCollection Options { get; } = new CommandLineOption.CommandLineOptionCollection();
|
||||||
|
|
||||||
|
public CommandLineCommand(string command, CommandLineOption[] options = null)
|
||||||
|
{
|
||||||
|
Name = command;
|
||||||
|
if (options != null)
|
||||||
|
{
|
||||||
|
Options.AddRange(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -117,6 +117,12 @@ namespace MBS.Framework
|
|||||||
|
|
||||||
public object DefaultValue { get; set; } = null;
|
public object DefaultValue { get; set; } = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a value indicating whether this <see cref="T:MBS.Framework.CommandLineOption"/> is optional.
|
||||||
|
/// </summary>
|
||||||
|
/// <value><c>true</c> if optional; otherwise, <c>false</c>.</value>
|
||||||
|
public bool Optional { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The description displayed in the help text.
|
/// The description displayed in the help text.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -21,9 +21,20 @@
|
|||||||
using System;
|
using System;
|
||||||
namespace MBS.Framework
|
namespace MBS.Framework
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Controls the behavior of relative file resolution.
|
||||||
|
/// </summary>
|
||||||
public enum FindFileOptions
|
public enum FindFileOptions
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Returns all matching fully-qualified file paths across all global,
|
||||||
|
/// application, and user directories.
|
||||||
|
/// </summary>
|
||||||
All = 0,
|
All = 0,
|
||||||
|
/// <summary>
|
||||||
|
/// Returns only file paths that are writable by the user (i.e., in the
|
||||||
|
/// user's local or roaming data directory).
|
||||||
|
/// </summary>
|
||||||
UserWritable = 1
|
UserWritable = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -135,6 +135,9 @@
|
|||||||
<Compile Include="ConsoleExtensions.cs" />
|
<Compile Include="ConsoleExtensions.cs" />
|
||||||
<Compile Include="MessageSeverity.cs" />
|
<Compile Include="MessageSeverity.cs" />
|
||||||
<Compile Include="Language.cs" />
|
<Compile Include="Language.cs" />
|
||||||
|
<Compile Include="ApplicationActivatedEvent.cs" />
|
||||||
|
<Compile Include="ApplicationActivationType.cs" />
|
||||||
|
<Compile Include="CommandLineCommand.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Logic\" />
|
<Folder Include="Logic\" />
|
||||||
@ -146,5 +149,8 @@
|
|||||||
<Folder Include="Settings\" />
|
<Folder Include="Settings\" />
|
||||||
<Folder Include="UserInterface\" />
|
<Folder Include="UserInterface\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="MemorySettingsProvider.cs" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
82
MBS.Framework/MemorySettingsProvider.cs
Normal file
82
MBS.Framework/MemorySettingsProvider.cs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
//
|
||||||
|
// MemorySettingsProvider.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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using MBS.Framework.Settings;
|
||||||
|
|
||||||
|
namespace MBS.Framework
|
||||||
|
{
|
||||||
|
public class MemorySettingsProvider : SettingsProvider
|
||||||
|
{
|
||||||
|
private Dictionary<Guid, object> _values = new Dictionary<Guid, object>();
|
||||||
|
protected override void LoadSettingsInternal()
|
||||||
|
{
|
||||||
|
base.LoadSettingsInternal();
|
||||||
|
foreach (SettingsGroup sg in SettingsGroups)
|
||||||
|
{
|
||||||
|
foreach (Setting s in sg.Settings)
|
||||||
|
{
|
||||||
|
LoadSetting(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protected override void SaveSettingsInternal()
|
||||||
|
{
|
||||||
|
base.SaveSettingsInternal();
|
||||||
|
foreach (SettingsGroup sg in SettingsGroups)
|
||||||
|
{
|
||||||
|
foreach (Setting s in sg.Settings)
|
||||||
|
{
|
||||||
|
SaveSetting(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadSetting(Setting s)
|
||||||
|
{
|
||||||
|
if (s is GroupSetting)
|
||||||
|
{
|
||||||
|
foreach (Setting s2 in ((GroupSetting)s).Options)
|
||||||
|
{
|
||||||
|
LoadSetting(s2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s.SetValue(_values[s.ID]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void SaveSetting(Setting s)
|
||||||
|
{
|
||||||
|
if (s is GroupSetting)
|
||||||
|
{
|
||||||
|
foreach (Setting s2 in ((GroupSetting)s).Options)
|
||||||
|
{
|
||||||
|
SaveSetting(s2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_values[s.ID] = s.GetValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user