using System;
using System.Diagnostics;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using MLEM.Formatting.Codes;
namespace MLEM.Misc {
///
/// MlemPlatform is a wrapper around some of MonoGame's platform-dependent behavior to allow for MLEM to stay platform-independent.
/// See , and for information on the specific platforms.
/// The MLEM demos' main classes also make use of this functionality: https://github.com/Ellpeck/MLEM/blob/main/Demos.DesktopGL/Program.cs#L8 and https://github.com/Ellpeck/MLEM/blob/main/Demos.Android/Activity1.cs#L33.
///
public abstract class MlemPlatform {
///
/// The current MLEM platform
/// Set this value before starting your game if you want to use platform-dependent MLEM features.
///
///
public static MlemPlatform Current;
///
/// Opens the on-screen keyboard if one is required by the platform.
/// Note that, if no on-screen keyboard is required, a null string should be returned.
///
/// Title of the dialog box.
/// Description of the dialog box.
/// Default text displayed in the input area.
/// If password mode is enabled, the characters entered are not displayed.
/// Text entered by the player. Null if back was used.
public abstract Task OpenOnScreenKeyboard(string title, string description, string defaultText, bool usePasswordMode);
///
/// Adds a text input listener to this platform, if supported.
/// The supplied listener will be called whenever a character is input.
///
/// The game's window
/// The callback that should be called whenever a character is pressed
public abstract void AddTextInputListener(GameWindow window, TextInputCallback callback);
///
/// A method that should be executed to open a link in the browser or a file explorer.
/// This method is currently used only by MLEM.Ui's implementation of the formatting code.
///
public abstract void OpenLinkOrFile(string link);
///
/// Ensures that is set to a valid value by throwing an exception if is null.
///
/// If is null
public static void EnsureExists() {
if (Current == null)
throw new InvalidOperationException("MlemPlatform was not initialized. For more information, see the MlemPlatform class or https://mlem.ellpeck.de/api/MLEM.Misc.MlemPlatform");
}
///
/// A delegate method that can be used for
///
/// The object that sent the event. The used in most cases.
/// The key that was pressed
/// The character that corresponds to that key
public delegate void TextInputCallback(object sender, Keys key, char character);
///
/// The MLEM DesktopGL platform.
/// This platform uses the built-in MonoGame TextInput event, which makes this listener work with any keyboard localization natively.
/// This platform is initialized as follows:
///
/// MlemPlatform.Current = new MlemPlatform.DesktopGl<TextInputEventArgs>((w, c) => w.TextInput += c);
///
///
///
public class DesktopGl : MlemPlatform {
private FieldInfo key;
private FieldInfo character;
private readonly Action> addListener;
///
/// Creates a new DesktopGL-based platform
/// See class documentation for more detailed information.
///
/// The function that is used to add a text input listener
public DesktopGl(Action> addListener) {
this.addListener = addListener;
}
///
public override Task OpenOnScreenKeyboard(string title, string description, string defaultText, bool usePasswordMode) {
return Task.FromResult(null);
}
///
public override void AddTextInputListener(GameWindow window, TextInputCallback callback) {
this.addListener(window, (sender, args) => {
if (this.key == null)
this.key = args.GetType().GetField("Key");
if (this.character == null)
this.character = args.GetType().GetField("Character");
callback.Invoke(sender, (Keys) this.key.GetValue(args), (char) this.character.GetValue(args));
});
}
///
public override void OpenLinkOrFile(string link) {
Process.Start(new ProcessStartInfo(link) {UseShellExecute = true});
}
}
///
/// The MLEM platform for mobile platforms as well as consoles.
/// This platform opens an on-screen keyboard using the KeyboardInput class on mobile devices.
/// Additionally, it starts a new activity whenever is called.
/// This listener is initialized as follows in the game's Activity class:
///
/// MlemPlatform.Current = new MlemPlatform.Mobile(KeyboardInput.Show, l => this.StartActivity(new Intent(Intent.ActionView, Uri.Parse(l))));
///
///
public class Mobile : MlemPlatform {
private readonly OpenOnScreenKeyboardDelegate openOnScreenKeyboard;
private readonly Action openLink;
///
/// Creates a new mobile- and console-based platform.
/// See class documentation for more detailed information.
///
/// The function that is used to display the on-screen keyboard
/// The action that is invoked to open a link in the browser, which is used for
public Mobile(OpenOnScreenKeyboardDelegate openOnScreenKeyboard, Action openLink = null) {
this.openOnScreenKeyboard = openOnScreenKeyboard;
this.openLink = openLink;
}
///
public override Task OpenOnScreenKeyboard(string title, string description, string defaultText, bool usePasswordMode) {
return this.openOnScreenKeyboard(title, description, defaultText, usePasswordMode);
}
///
public override void AddTextInputListener(GameWindow window, TextInputCallback callback) {
}
///
public override void OpenLinkOrFile(string link) {
this.openLink?.Invoke(link);
}
///
/// A delegate method used for
///
/// Title of the dialog box.
/// Description of the dialog box.
/// Default text displayed in the input area.
/// If password mode is enabled, the characters entered are not displayed.
/// Text entered by the player. Null if back was used.
public delegate Task OpenOnScreenKeyboardDelegate(string title, string description, string defaultText, bool usePasswordMode);
}
///
/// A MLEM platform implementation that does nothing.
/// This can be used if no platform-dependent code is required for the game.
///
public class None : MlemPlatform {
///
public override Task OpenOnScreenKeyboard(string title, string description, string defaultText, bool usePasswordMode) {
return Task.FromResult(null);
}
///
public override void AddTextInputListener(GameWindow window, TextInputCallback callback) {
}
///
public override void OpenLinkOrFile(string link) {
}
}
}
}