preliminary implementation of GTK engine for .NET core
This commit is contained in:
parent
faf0327f6a
commit
bb7fdd9291
@ -0,0 +1,49 @@
|
||||
using MBS.Core.Drawing;
|
||||
using MBS.Desktop.Controls;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GTK.Classes;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GTK.Constants;
|
||||
|
||||
namespace MBS.Desktop.Engines.GTK3.ControlImplementations;
|
||||
|
||||
public abstract class ContainerImplementation : GTK3NativeImplementation, Container.IImplementation
|
||||
{
|
||||
public void InsertControl(Control control, int index)
|
||||
{
|
||||
Container container = (Container)Control;
|
||||
GtkContainer native = (GtkContainer)((GTK3NativeHandle)container.Layout.Implementation.Handle).Handle;
|
||||
|
||||
control.CreateImplementation();
|
||||
|
||||
|
||||
//!FIXME: we need to use the Layout here
|
||||
native.Add(((GTK3NativeHandle)control.Implementation.Handle).Handle);
|
||||
}
|
||||
|
||||
public void RemoveControl(Control control)
|
||||
{
|
||||
GtkContainer container = (GtkContainer)((GTK3NativeHandle)Handle).Handle;
|
||||
container.Remove(((GTK3NativeHandle)control.Implementation.Handle).Handle);
|
||||
}
|
||||
|
||||
public void RemoveAllControls()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void OnNativeHandleCreated(EventArgs e)
|
||||
{
|
||||
base.OnNativeHandleCreated(e);
|
||||
|
||||
Container container = (Container)Control;
|
||||
Layout layout = container.Layout;
|
||||
|
||||
GTK3NativeHandle nhControl = (GTK3NativeHandle)Handle;
|
||||
|
||||
layout.CreateImplementation();
|
||||
GTK3NativeHandle nhLayout = (GTK3NativeHandle)layout.Implementation.Handle;
|
||||
|
||||
GtkContainer ct = (GtkContainer)nhControl.Handle;
|
||||
ct.Add(nhLayout.Handle);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
using MBS.Core.Drawing;
|
||||
using MBS.Desktop.Controls;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GTK.Classes;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GTK.Constants;
|
||||
|
||||
namespace MBS.Desktop.Engines.GTK3.ControlImplementations;
|
||||
|
||||
[ImplementsFor(typeof(Label))]
|
||||
public class LabelImplementation : GTK3NativeImplementation, Label.IImplementation
|
||||
{
|
||||
protected override NativeHandle CreateNativeHandle()
|
||||
{
|
||||
return new GTK3NativeHandle(new GtkLabel());
|
||||
}
|
||||
public string GetText()
|
||||
{
|
||||
return ((GtkLabel)((GTK3NativeHandle)Handle).Handle).Text;
|
||||
}
|
||||
|
||||
public void SetText(string value)
|
||||
{
|
||||
((GtkLabel)((GTK3NativeHandle)Handle).Handle).Text = value;
|
||||
}
|
||||
public bool GetUseMarkup()
|
||||
{
|
||||
return ((GtkLabel)((GTK3NativeHandle)Handle).Handle).UseMarkup;
|
||||
}
|
||||
|
||||
public void SetUseMarkup(bool value)
|
||||
{
|
||||
((GtkLabel)((GTK3NativeHandle)Handle).Handle).UseMarkup = value;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
using MBS.Core.Drawing;
|
||||
using MBS.Desktop.Controls;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GTK.Classes;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GTK.Constants;
|
||||
|
||||
namespace MBS.Desktop.Engines.GTK3.ControlImplementations;
|
||||
|
||||
[ImplementsFor(typeof(Window))]
|
||||
public class WindowImplementation : ContainerImplementation, Window.IImplementation
|
||||
{
|
||||
public void Show()
|
||||
{
|
||||
GtkWindow window = (GtkWindow)((GTK3NativeHandle)Handle).Handle;
|
||||
window.ShowAll();
|
||||
}
|
||||
public bool GetVisible()
|
||||
{
|
||||
GtkWindow window = (GtkWindow)((GTK3NativeHandle)Handle).Handle;
|
||||
return window.IsVisible;
|
||||
}
|
||||
public void SetVisible(bool value)
|
||||
{
|
||||
GtkWindow window = (GtkWindow)((GTK3NativeHandle)Handle).Handle;
|
||||
if (value)
|
||||
{
|
||||
window.ShowAll();
|
||||
}
|
||||
else
|
||||
{
|
||||
window.Hide();
|
||||
}
|
||||
}
|
||||
|
||||
public string GetTitle()
|
||||
{
|
||||
GtkWindow window = (GtkWindow)((GTK3NativeHandle)Handle).Handle;
|
||||
return window.Title;
|
||||
}
|
||||
public void SetTitle(string value)
|
||||
{
|
||||
GtkWindow window = (GtkWindow)((GTK3NativeHandle)Handle).Handle;
|
||||
window.Title = value;
|
||||
}
|
||||
|
||||
public Dimension2D GetDefaultSize()
|
||||
{
|
||||
GtkWindow window = (GtkWindow)((GTK3NativeHandle)Handle).Handle;
|
||||
int width = 0, height = 0;
|
||||
window.GetDefaultSize(out width, out height);
|
||||
|
||||
return new Dimension2D(width, height);
|
||||
}
|
||||
public void SetDefaultSize(Dimension2D value)
|
||||
{
|
||||
GtkWindow window = (GtkWindow)((GTK3NativeHandle)Handle).Handle;
|
||||
window.SetDefaultSize((int)value.Width, (int)value.Height);
|
||||
}
|
||||
|
||||
protected override NativeHandle CreateNativeHandle()
|
||||
{
|
||||
Window window = (Window)Control;
|
||||
GtkWindow native = new GtkWindow(((GTK3DesktopApplicationEngine)((DesktopApplication)DesktopApplication.Instance).Engine).ApplicationHandle);
|
||||
return new GTK3NativeHandle(native);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
namespace MBS.Desktop.Engines.GTK3;
|
||||
|
||||
using MBS.Core;
|
||||
using MBS.Core.Reflection;
|
||||
using MBS.Desktop.Controls;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GIO.Constants;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GTK.Classes;
|
||||
using static MBS.Desktop.Engines.GTK3.Internal.GObject.Delegates;
|
||||
|
||||
public class GTK3DesktopApplicationEngine : DesktopApplicationEngine
|
||||
{
|
||||
protected string GetApplicationId()
|
||||
{
|
||||
return "net.alcetech.framework.desktop__" + this.GetType().FullName;
|
||||
}
|
||||
|
||||
public GtkApplication? ApplicationHandle { get; private set; }
|
||||
|
||||
protected override void InitializeInternal()
|
||||
{
|
||||
ApplicationHandle = new GtkApplication(GetApplicationId(), GApplicationFlags.HandlesCommandLine);
|
||||
}
|
||||
|
||||
Action2P startup_d;
|
||||
Action2P activate_d;
|
||||
Action3P commandline_d;
|
||||
|
||||
public GTK3DesktopApplicationEngine()
|
||||
{
|
||||
startup_d = new Action2P(startup);
|
||||
activate_d = new Action2P(activate);
|
||||
commandline_d = new Action3P(commandline);
|
||||
}
|
||||
|
||||
private void activate(IntPtr application, IntPtr user_data)
|
||||
{
|
||||
// Invoker.Invoke(Application.Instance, "OnStartup", new object[] { EventArgs.Empty });
|
||||
Console.WriteLine("activate() called , we should be using commandline ()");
|
||||
}
|
||||
private void startup(IntPtr application, IntPtr user_data)
|
||||
{
|
||||
Console.WriteLine("startup() called");
|
||||
Invoker.Invoke(Application.Instance, "OnStartup", new object[] { EventArgs.Empty });
|
||||
}
|
||||
|
||||
private static bool _firstRun = true;
|
||||
private void commandline(IntPtr handle, IntPtr commandLine, IntPtr data)
|
||||
{
|
||||
Console.WriteLine("commandline() called");
|
||||
|
||||
int argc = 0;
|
||||
IntPtr hwpp = Internal.GIO.Methods.g_application_command_line_get_arguments(commandLine, ref argc);
|
||||
|
||||
string[] arguments = MBS.Core.Interop.InteropServices.PtrToStringArray(hwpp, argc);
|
||||
|
||||
CommandLine cline = new CommandLine(arguments);
|
||||
ApplicationActivatedEventArgs e = new ApplicationActivatedEventArgs(_firstRun, ApplicationActivationType.Launch, cline);
|
||||
Invoker.Invoke(Application.Instance, "OnActivated", new object[] { e });
|
||||
}
|
||||
|
||||
protected override int StartInternal()
|
||||
{
|
||||
ApplicationHandle.Connect("startup", startup_d);
|
||||
ApplicationHandle.Connect("activate", activate_d);
|
||||
ApplicationHandle.Connect("command_line", commandline_d);
|
||||
|
||||
int retval = ApplicationHandle.Run();
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GTK.Classes;
|
||||
|
||||
namespace MBS.Desktop.Engines.GTK3;
|
||||
|
||||
public class GTK3NativeHandle : NativeHandle
|
||||
{
|
||||
public GtkWidget Handle { get; private set; }
|
||||
|
||||
public GTK3NativeHandle(GtkWidget handle)
|
||||
{
|
||||
Handle = handle;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
namespace MBS.Desktop.Engines.GTK3;
|
||||
|
||||
public abstract class GTK3NativeImplementation : NativeImplementation
|
||||
{
|
||||
|
||||
}
|
||||
@ -0,0 +1,18 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GIO.Constants;
|
||||
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GIO.Classes;
|
||||
|
||||
public class GApplication : GObject.Classes.GObject
|
||||
{
|
||||
[DllImport(LIBRARY_FILENAME_GIO)]
|
||||
private static extern int g_application_run(IntPtr /*GApplication*/ application, int argc, string[] argv);
|
||||
|
||||
public int Run()
|
||||
{
|
||||
string[] argv = Environment.GetCommandLineArgs();
|
||||
int argc = argv.Length;
|
||||
int retval = g_application_run(Handle, argc, argv);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,63 @@
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GIO.Constants;
|
||||
|
||||
/// <summary>
|
||||
/// Flags used to define the behaviour of a <see cref="GApplication" />.
|
||||
/// </summary>
|
||||
public enum GApplicationFlags
|
||||
{
|
||||
/// <summary>
|
||||
/// Default. Deprecated in 2.74, use G_APPLICATION_DEFAULT_FLAGS instead.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
/// <summary>
|
||||
/// Default flags. Since: 2.74
|
||||
/// </summary>
|
||||
Default = 0,
|
||||
/// <summary>
|
||||
/// Run as a service. In this mode, registration fails if the service is already running, and the application will initially wait up to 10 seconds for an initial activation message to arrive.
|
||||
/// </summary>
|
||||
Service = (1 << 0),
|
||||
/// <summary>
|
||||
/// Don't try to become the primary instance.
|
||||
/// </summary>
|
||||
Launcher = (1 << 1),
|
||||
/// <summary>
|
||||
/// This application handles opening files (in the primary instance). Note that this flag
|
||||
/// only affects the default implementation of local_command_line(), and has no effect if
|
||||
/// G_APPLICATION_HANDLES_COMMAND_LINE is given. See g_application_run() for details.
|
||||
/// </summary>
|
||||
HandlesOpen = (1 << 2),
|
||||
/// <summary>
|
||||
/// This application handles command line arguments (in the primary instance). Note that
|
||||
/// this flag only affect the default implementation of local_command_line(). See
|
||||
/// g_application_run() for details.
|
||||
/// </summary>
|
||||
HandlesCommandLine = (1 << 3),
|
||||
/// <summary>
|
||||
/// Send the environment of the launching process to the primary instance. Set this flag
|
||||
/// if your application is expected to behave differently depending on certain environment
|
||||
/// variables. For instance, an editor might be expected to use the GIT_COMMITTER_NAME
|
||||
/// environment variable when editing a git commit message. The environment is available to
|
||||
/// the "command-line" signal handler, via g_application_command_line_getenv().
|
||||
/// </summary>
|
||||
SendEnvironment = (1 << 4),
|
||||
/// <summary>
|
||||
/// Make no attempts to do any of the typical single-instance application negotiation,
|
||||
/// even if the application ID is given. The application neither attempts to become the
|
||||
/// owner of the application ID nor does it check if an existing owner already exists.
|
||||
/// Everything occurs in the local process. Since: 2.30.
|
||||
/// </summary>
|
||||
NonUnique = (1 << 5),
|
||||
/// <summary>
|
||||
/// Allow users to override the application ID from the command line with --gapplication-app-id. Since: 2.48
|
||||
/// </summary>
|
||||
CanOverrideAppId = (1 << 6),
|
||||
/// <summary>
|
||||
/// Allow another instance to take over the bus name. Since: 2.60
|
||||
/// </summary>
|
||||
AllowReplacement = (1 << 7),
|
||||
/// <summary>
|
||||
/// Take over from another instance. This flag is usually set by passing --gapplication-replace on the commandline. Since: 2.60
|
||||
/// </summary>
|
||||
Replace = (1 << 8)
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GIO;
|
||||
|
||||
internal static class Methods
|
||||
{
|
||||
public const string LIBRARY_FILENAME_GIO = "gio-2.0";
|
||||
|
||||
[DllImport(LIBRARY_FILENAME_GIO)]
|
||||
public static extern IntPtr g_application_command_line_get_arguments(IntPtr command_line, ref int argc);
|
||||
}
|
||||
@ -0,0 +1,106 @@
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection.Metadata.Ecma335;
|
||||
using System.Runtime.InteropServices;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GObject.Constants;
|
||||
using static MBS.Desktop.Engines.GTK3.Internal.GObject.Delegates;
|
||||
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GObject.Classes;
|
||||
|
||||
/// <summary>
|
||||
/// The base object type
|
||||
/// </summary>
|
||||
public class GObject
|
||||
{
|
||||
public const string LIBRARY_FILENAME_GTK = "gtk-3";
|
||||
public const string LIBRARY_FILENAME_GLIB = "glib-2.0";
|
||||
public const string LIBRARY_FILENAME_GOBJECT = "gobject-2.0";
|
||||
public const string LIBRARY_FILENAME_GIO = "gio-2.0";
|
||||
|
||||
internal GObject(IntPtr handle)
|
||||
{
|
||||
Handle = handle;
|
||||
}
|
||||
protected GObject()
|
||||
{
|
||||
}
|
||||
|
||||
public IntPtr Handle { get; protected set; }
|
||||
|
||||
// private static extern void g_object_set_property (IntPtr obj, string property_name, ref GValue value);
|
||||
[DllImport(LIBRARY_FILENAME_GOBJECT)]
|
||||
private static extern void g_object_get_property (IntPtr obj, string property_name, IntPtr value);
|
||||
[DllImport(LIBRARY_FILENAME_GOBJECT)]
|
||||
private static extern void g_object_set_property (IntPtr obj, string property_name, IntPtr value);
|
||||
|
||||
public T GetProperty<T>(string property_name)
|
||||
{
|
||||
if (typeof(T) == typeof(bool))
|
||||
{
|
||||
GValue value = new GValue(GValueType.Boolean);
|
||||
g_object_get_property(Handle, property_name, value.Handle);
|
||||
|
||||
bool val = value.GetBoolean();
|
||||
return (T)((object)val);
|
||||
}
|
||||
else if (typeof(T) == typeof(IntPtr))
|
||||
{
|
||||
GValue value = new GValue(GValueType.Pointer);
|
||||
g_object_get_property(Handle, property_name, value.Handle);
|
||||
IntPtr val = value.GetPointer();
|
||||
return (T)((object)val);
|
||||
}
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public void SetProperty(string property_name, object value)
|
||||
{
|
||||
if (value is bool)
|
||||
{
|
||||
GValue gvalue = new GValue(GValueType.Boolean);
|
||||
gvalue.SetBoolean((bool)value);
|
||||
g_object_set_property(Handle, property_name, gvalue.Handle);
|
||||
}
|
||||
else if (value is IntPtr)
|
||||
{
|
||||
GValue gvalue = new GValue(GValueType.Pointer);
|
||||
gvalue.SetPointer((IntPtr)value);
|
||||
g_object_set_property(Handle, property_name, gvalue.Handle);
|
||||
}
|
||||
else if (value is GObject)
|
||||
{
|
||||
GValue gvalue = new GValue(GValueType.Object);
|
||||
gvalue.SetObject((GObject)value);
|
||||
g_object_set_property(Handle, property_name, gvalue.Handle);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport(LIBRARY_FILENAME_GOBJECT)]
|
||||
private static extern IntPtr g_type_from_name (string name);
|
||||
|
||||
|
||||
[DllImport(LIBRARY_FILENAME_GOBJECT)]
|
||||
private static extern void g_signal_connect_data(IntPtr instance, string detailed_signal, Action c_handler, IntPtr data, IntPtr destroy_data, GConnectFlags connect_flags);
|
||||
[DllImport(LIBRARY_FILENAME_GOBJECT)]
|
||||
private static extern void g_signal_connect_data(IntPtr instance, string detailed_signal, Action1P c_handler, IntPtr data, IntPtr destroy_data, GConnectFlags connect_flags);
|
||||
[DllImport(LIBRARY_FILENAME_GOBJECT)]
|
||||
private static extern void g_signal_connect_data(IntPtr instance, string detailed_signal, Action2P c_handler, IntPtr data, IntPtr destroy_data, GConnectFlags connect_flags);
|
||||
[DllImport(LIBRARY_FILENAME_GOBJECT)]
|
||||
private static extern void g_signal_connect_data(IntPtr instance, string detailed_signal, Action3P c_handler, IntPtr data, IntPtr destroy_data, GConnectFlags connect_flags);
|
||||
|
||||
public void Connect(string detailed_signal, Action1P c_handler, IntPtr data = default(IntPtr))
|
||||
{
|
||||
g_signal_connect_data(Handle, detailed_signal, c_handler, data, IntPtr.Zero, GConnectFlags.Default);
|
||||
}
|
||||
public void Connect(string detailed_signal, Action2P c_handler, IntPtr data = default(IntPtr))
|
||||
{
|
||||
g_signal_connect_data(Handle, detailed_signal, c_handler, data, IntPtr.Zero, GConnectFlags.Default);
|
||||
}
|
||||
public void Connect(string detailed_signal, Action3P c_handler, IntPtr data = default(IntPtr))
|
||||
{
|
||||
g_signal_connect_data(Handle, detailed_signal, c_handler, data, IntPtr.Zero, GConnectFlags.Default);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,80 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GObject.Classes;
|
||||
|
||||
public class GValue
|
||||
{
|
||||
[DllImport(GObject.LIBRARY_FILENAME_GOBJECT)]
|
||||
private static extern IntPtr g_value_init(IntPtr gvalue, IntPtr gtype);
|
||||
[DllImport(GObject.LIBRARY_FILENAME_GOBJECT)]
|
||||
private static extern IntPtr g_value_get_object(IntPtr gvalue);
|
||||
|
||||
[DllImport(GObject.LIBRARY_FILENAME_GOBJECT)]
|
||||
private static extern void g_value_set_object(IntPtr gvalue, IntPtr ptr);
|
||||
|
||||
[DllImport(GObject.LIBRARY_FILENAME_GOBJECT)]
|
||||
private static extern IntPtr g_value_get_pointer(IntPtr gvalue);
|
||||
|
||||
[DllImport(GObject.LIBRARY_FILENAME_GOBJECT)]
|
||||
private static extern void g_value_set_pointer(IntPtr gvalue, IntPtr ptr);
|
||||
|
||||
[DllImport(GObject.LIBRARY_FILENAME_GOBJECT)]
|
||||
private static extern long g_value_get_int64(IntPtr gvalue);
|
||||
[DllImport(GObject.LIBRARY_FILENAME_GOBJECT)]
|
||||
private static extern void g_value_set_int64(IntPtr gvalue, long value);
|
||||
|
||||
[DllImport(GObject.LIBRARY_FILENAME_GOBJECT)]
|
||||
private static extern bool g_value_get_boolean(IntPtr gvalue);
|
||||
[DllImport(GObject.LIBRARY_FILENAME_GOBJECT)]
|
||||
private static extern void g_value_set_boolean(IntPtr gvalue, bool value);
|
||||
|
||||
private const int G_VALUE_SIZE = 24; // found by calling sizeof(G_VALUE_INIT) in C
|
||||
private IntPtr g_value_new(IntPtr gtype)
|
||||
{
|
||||
IntPtr gvalue = Marshal.AllocHGlobal(G_VALUE_SIZE);
|
||||
for (int i = 0; i < G_VALUE_SIZE; i++)
|
||||
{
|
||||
Marshal.WriteByte(gvalue, i, 0);
|
||||
}
|
||||
|
||||
Console.WriteLine("g_value_new: initializing new GValue of type {0}", gtype);
|
||||
IntPtr gvalue2 = g_value_init(gvalue, gtype);
|
||||
return gvalue2;
|
||||
}
|
||||
|
||||
public IntPtr Handle { get; }
|
||||
|
||||
public GValue(GValueType type)
|
||||
{
|
||||
Handle = g_value_new(type.Handle);
|
||||
}
|
||||
|
||||
public bool GetBoolean()
|
||||
{
|
||||
return g_value_get_boolean(Handle);
|
||||
}
|
||||
public void SetBoolean(bool value)
|
||||
{
|
||||
g_value_set_boolean(Handle, value);
|
||||
}
|
||||
|
||||
public IntPtr GetPointer()
|
||||
{
|
||||
return g_value_get_pointer(Handle);
|
||||
}
|
||||
public void SetPointer(IntPtr value)
|
||||
{
|
||||
g_value_set_pointer(Handle, value);
|
||||
}
|
||||
|
||||
public GObject GetObject()
|
||||
{
|
||||
IntPtr h = g_value_get_object(Handle);
|
||||
// !FIXME: look up in our table to see if we have a .NET object for this
|
||||
return new GObject(h);
|
||||
}
|
||||
public void SetObject(GObject value)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GObject.Classes;
|
||||
|
||||
public class GValueType
|
||||
{
|
||||
private const int G_TYPE_FUNDAMENTAL_SHIFT = 2;
|
||||
|
||||
private static IntPtr G_TYPE_MAKE_FUNDAMENTAL(int x)
|
||||
{
|
||||
return new IntPtr(x << G_TYPE_FUNDAMENTAL_SHIFT);
|
||||
}
|
||||
|
||||
public IntPtr Handle { get; }
|
||||
public GValueType(IntPtr handle)
|
||||
{
|
||||
Handle = handle;
|
||||
}
|
||||
|
||||
private static readonly IntPtr G_TYPE_BOOLEAN = G_TYPE_MAKE_FUNDAMENTAL(5);
|
||||
public static GValueType Boolean { get; } = new GValueType(G_TYPE_BOOLEAN);
|
||||
|
||||
private static readonly IntPtr G_TYPE_INT64 = G_TYPE_MAKE_FUNDAMENTAL(10);
|
||||
public static GValueType Int64 { get; } = new GValueType(G_TYPE_INT64);
|
||||
|
||||
private static readonly IntPtr G_TYPE_POINTER = G_TYPE_MAKE_FUNDAMENTAL(17);
|
||||
public static GValueType Pointer { get; } = new GValueType(G_TYPE_POINTER);
|
||||
|
||||
private static readonly IntPtr G_TYPE_OBJECT = G_TYPE_MAKE_FUNDAMENTAL(20);
|
||||
public static GValueType Object { get; } = new GValueType(G_TYPE_OBJECT);
|
||||
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GObject.Constants;
|
||||
|
||||
public enum GConnectFlags
|
||||
{
|
||||
Default,
|
||||
After,
|
||||
Swapped
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GObject.Constants;
|
||||
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GObject;
|
||||
|
||||
public static class Delegates
|
||||
{
|
||||
|
||||
public delegate void Action1P(IntPtr parm1);
|
||||
public delegate void Action2P(IntPtr parm1, IntPtr parm2);
|
||||
public delegate void Action3P(IntPtr parm1, IntPtr parm2, IntPtr parm3);
|
||||
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GTK.Classes;
|
||||
|
||||
public static class Gtk
|
||||
{
|
||||
[DllImport("gtk-3")]
|
||||
private static extern void gtk_init(ref int argc, ref string[] argv);
|
||||
[DllImport("gtk-3")]
|
||||
private static extern bool gtk_init_check(ref int argc, ref string[] argv);
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
string[] argv = System.Environment.GetCommandLineArgs();
|
||||
int argc = argv.Length;
|
||||
gtk_init(ref argc, ref argv);
|
||||
}
|
||||
/// <summary>
|
||||
/// This function does the same work as <see cref="Init" /> with only a single
|
||||
/// change: It does not terminate the program if the commandline arguments
|
||||
/// couldn’t be parsed or the windowing system can’t be initialized.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// <see cref="string[]" /> of command-line arguments after the call to gtk_init_check,
|
||||
/// or <see cref="null" /> if gtk_init_check returned FALSE.
|
||||
/// </returns>
|
||||
public static string[] InitCheck()
|
||||
{
|
||||
string[] argv = System.Environment.GetCommandLineArgs();
|
||||
int argc = argv.Length;
|
||||
bool value = gtk_init_check(ref argc, ref argv);
|
||||
if (value)
|
||||
{
|
||||
return argv;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GIO.Classes;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GIO.Constants;
|
||||
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GTK.Classes;
|
||||
|
||||
public class GtkApplication : GApplication
|
||||
{
|
||||
public string Id { get; }
|
||||
public GApplicationFlags Flags { get; }
|
||||
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern IntPtr gtk_application_new(string application_id, GApplicationFlags flags);
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern IntPtr gtk_application_add_window(IntPtr application, IntPtr window);
|
||||
|
||||
public void AddWindow(GtkWindow window)
|
||||
{
|
||||
gtk_application_add_window(Handle, window.Handle);
|
||||
}
|
||||
|
||||
public GtkApplication(string id, GApplicationFlags flags)
|
||||
{
|
||||
Console.WriteLine("creating new GtkApplication with id {0}", id);
|
||||
Handle = gtk_application_new(id, flags);
|
||||
|
||||
Id = id;
|
||||
Flags = flags;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GTK.Classes;
|
||||
|
||||
public class GtkBin : GtkContainer
|
||||
{
|
||||
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GTK.Constants;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GTK.Interfaces;
|
||||
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GTK.Classes;
|
||||
|
||||
public class GtkBox : GtkContainer, GtkOrientable
|
||||
{
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern IntPtr /*GtkBox*/ gtk_box_new(GtkOrientation orientation, int spacing);
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern void gtk_box_pack_start(IntPtr /*GtkBox*/ handle, IntPtr /*GtkWidget*/ child, bool expand, bool fill, uint padding);
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern void gtk_box_pack_end(IntPtr /*GtkBox*/ handle, IntPtr /*GtkWidget*/ child, bool expand, bool fill, uint padding);
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern bool gtk_box_get_homogenous(IntPtr /*GtkBox*/ handle);
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern void gtk_box_set_homogenous(IntPtr /*GtkBox*/ handle, bool value);
|
||||
|
||||
public GtkBox(GtkOrientation orientation, int spacing)
|
||||
{
|
||||
Handle = gtk_box_new(orientation, spacing);
|
||||
}
|
||||
|
||||
public void PackStart(GtkWidget child, bool expand, bool fill, uint padding)
|
||||
{
|
||||
gtk_box_pack_start(Handle, child.Handle, expand, fill, padding);
|
||||
}
|
||||
public void PackEnd(GtkWidget child, bool expand, bool fill, uint padding)
|
||||
{
|
||||
gtk_box_pack_end(Handle, child.Handle, expand, fill, padding);
|
||||
}
|
||||
|
||||
public bool Homogenous
|
||||
{
|
||||
get { return gtk_box_get_homogenous(Handle); }
|
||||
set { gtk_box_set_homogenous(Handle, value); }
|
||||
}
|
||||
|
||||
public GtkOrientation Orientation
|
||||
{
|
||||
get { return GtkOrientable.gtk_orientable_get_orientation(Handle); }
|
||||
set { GtkOrientable.gtk_orientable_set_orientation(Handle, value); }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,22 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GTK.Classes;
|
||||
|
||||
public class GtkContainer : GtkWidget
|
||||
{
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern void gtk_container_add(IntPtr /*GtkContainer*/ container, IntPtr /*GtkWidget*/ widget);
|
||||
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern void gtk_container_remove(IntPtr /*GtkContainer*/ container, IntPtr /*GtkWidget*/ widget);
|
||||
|
||||
public void Add(GtkWidget widget)
|
||||
{
|
||||
gtk_container_add(Handle, widget.Handle);
|
||||
}
|
||||
public void Remove(GtkWidget widget)
|
||||
{
|
||||
gtk_container_remove(Handle, widget.Handle);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GTK.Classes;
|
||||
|
||||
public class GtkLabel : GtkWidget
|
||||
{
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern IntPtr gtk_label_new (string str);
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern IntPtr gtk_label_set_label (IntPtr /*GtkLabel*/ label, string str);
|
||||
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern string gtk_label_get_label (IntPtr /*GtkLabel*/ label);
|
||||
|
||||
public GtkLabel()
|
||||
{
|
||||
Handle = gtk_label_new("Hello World!");
|
||||
}
|
||||
|
||||
public string Text
|
||||
{
|
||||
get { return gtk_label_get_label(Handle); }
|
||||
set { gtk_label_set_label(Handle, value); }
|
||||
}
|
||||
public bool UseMarkup
|
||||
{
|
||||
get { return GetProperty<bool>("use-markup"); }
|
||||
set { SetProperty("use-markup", value); }
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GTK.Classes;
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GObject.Classes;
|
||||
|
||||
public class GtkWidget : GObject
|
||||
{
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern void gtk_widget_show(IntPtr widget);
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern void gtk_widget_show_all(IntPtr widget);
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern void gtk_widget_hide(IntPtr widget);
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern void gtk_widget_destroy(IntPtr widget);
|
||||
|
||||
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern bool gtk_widget_is_visible(IntPtr widget);
|
||||
|
||||
public bool IsVisible
|
||||
{
|
||||
get
|
||||
{
|
||||
return gtk_widget_is_visible(Handle);
|
||||
}
|
||||
}
|
||||
|
||||
public void Show()
|
||||
{
|
||||
gtk_widget_show(Handle);
|
||||
}
|
||||
public void ShowAll()
|
||||
{
|
||||
gtk_widget_show_all(Handle);
|
||||
}
|
||||
public void Hide()
|
||||
{
|
||||
gtk_widget_hide(Handle);
|
||||
}
|
||||
public void Destroy()
|
||||
{
|
||||
gtk_widget_destroy(Handle);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GTK.Constants;
|
||||
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GTK.Classes;
|
||||
|
||||
public class GtkWindow : GtkBin
|
||||
{
|
||||
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern IntPtr gtk_window_new(GtkWindowType type);
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern IntPtr gtk_application_window_new(IntPtr application);
|
||||
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern void gtk_window_get_default_size(IntPtr window, ref int width, ref int height);
|
||||
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern void gtk_window_set_default_size(IntPtr window, int width, int height);
|
||||
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern void gtk_window_set_title(IntPtr window, string title);
|
||||
|
||||
[DllImport(LIBRARY_FILENAME_GTK)]
|
||||
private static extern string gtk_window_get_title(IntPtr window);
|
||||
|
||||
public string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
return gtk_window_get_title(Handle);
|
||||
}
|
||||
set
|
||||
{
|
||||
gtk_window_set_title(Handle, value);
|
||||
}
|
||||
}
|
||||
|
||||
public GtkWindow(GtkWindowType type)
|
||||
{
|
||||
Handle = gtk_window_new(type);
|
||||
}
|
||||
public GtkWindow(GtkApplication application)
|
||||
{
|
||||
Handle = gtk_application_window_new(application.Handle);
|
||||
}
|
||||
|
||||
public void GetDefaultSize(out int width, out int height)
|
||||
{
|
||||
int w = 0, h = 0;
|
||||
gtk_window_get_default_size(Handle, ref w, ref h);
|
||||
|
||||
width = w;
|
||||
height = h;
|
||||
}
|
||||
public void SetDefaultSize(int width, int height)
|
||||
{
|
||||
gtk_window_set_default_size(Handle, width, height);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GTK.Constants;
|
||||
|
||||
public enum GtkOrientation
|
||||
{
|
||||
Horizontal,
|
||||
Vertical
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GTK.Constants;
|
||||
|
||||
public enum GtkWindowType
|
||||
{
|
||||
Toplevel,
|
||||
Popup
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GTK.Constants;
|
||||
|
||||
namespace MBS.Desktop.Engines.GTK3.Internal.GTK.Interfaces;
|
||||
|
||||
public interface GtkOrientable
|
||||
{
|
||||
GtkOrientation Orientation { get; set; }
|
||||
|
||||
[DllImport(GObject.Classes.GObject.LIBRARY_FILENAME_GTK)]
|
||||
public static extern GtkOrientation gtk_orientable_get_orientation(IntPtr /*GtkOrientable*/ orientable);
|
||||
[DllImport(GObject.Classes.GObject.LIBRARY_FILENAME_GTK)]
|
||||
public static extern void gtk_orientable_set_orientation(IntPtr /*GtkOrientable*/ orientable, GtkOrientation value);
|
||||
}
|
||||
@ -0,0 +1,47 @@
|
||||
using MBS.Core;
|
||||
using MBS.Core.Drawing;
|
||||
using MBS.Desktop.Controls;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GTK.Classes;
|
||||
using MBS.Desktop.Engines.GTK3.Internal.GTK.Constants;
|
||||
using MBS.Desktop.Layouts;
|
||||
|
||||
namespace MBS.Desktop.Engines.GTK3.LayoutImplementations;
|
||||
|
||||
[ImplementsFor(typeof(BoxLayout))]
|
||||
public class BoxLayoutImplementation : GTK3NativeImplementation, BoxLayout.IImplementation
|
||||
{
|
||||
protected override NativeHandle CreateNativeHandle()
|
||||
{
|
||||
return new GTK3NativeHandle(new GtkBox(GtkOrientation.Horizontal, 0));
|
||||
}
|
||||
|
||||
public Orientation GetOrientation()
|
||||
{
|
||||
GtkBox box = (GtkBox) ((GTK3NativeHandle)Handle).Handle;
|
||||
switch (box.Orientation)
|
||||
{
|
||||
case GtkOrientation.Horizontal: return Orientation.Horizontal;
|
||||
case GtkOrientation.Vertical: return Orientation.Vertical;
|
||||
}
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
public void SetOrientation(Orientation value)
|
||||
{
|
||||
GtkBox box = (GtkBox) ((GTK3NativeHandle)Handle).Handle;
|
||||
switch (value)
|
||||
{
|
||||
case Orientation.Horizontal:
|
||||
{
|
||||
box.Orientation = GtkOrientation.Horizontal;
|
||||
return;
|
||||
}
|
||||
case Orientation.Vertical:
|
||||
{
|
||||
box.Orientation = GtkOrientation.Vertical;
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\lib\MBS.Desktop\MBS.Desktop.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="MBS.Desktop.Engines.GTK3.dll.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<configuration>
|
||||
<dllmap dll="appindicator" target="libappindicator3.so.1" />
|
||||
<dllmap dll="gtk-x11-2.0" target="libgtk-x11-2.0.so.0" />
|
||||
<dllmap dll="gtk-3" target="libgtk-3.so.0" />
|
||||
<dllmap dll="gtk-4" target="libgtk-4.so.1" />
|
||||
<dllmap dll="gdk-3" target="libgdk-3.so.0" />
|
||||
<dllmap dll="notify" target="libnotify.so.4" />
|
||||
<dllmap dll="gio-2.0" target="libgio-2.0.so.0" />
|
||||
<dllmap dll="glib-2.0" target="libglib-2.0.so.0" />
|
||||
<dllmap dll="gobject-2.0" target="libgobject-2.0.so.0" />
|
||||
<dllmap dll="pango-1.0" target="libpango-1.0.so.0" />
|
||||
<dllmap dll="cairo" target="libcairo.so.2" />
|
||||
<dllmap dll="libgdl-3" target="libgdl-3.so.5" />
|
||||
<dllmap dll="libgtksourceview-3.0" target="libgtksourceview-3.0.so.1" />
|
||||
</configuration>
|
||||
@ -0,0 +1,50 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace MBS.Desktop.Controls;
|
||||
|
||||
public abstract class Container : Control
|
||||
{
|
||||
public interface IImplementation
|
||||
{
|
||||
void InsertControl(Control control, int index);
|
||||
void RemoveControl(Control control);
|
||||
void RemoveAllControls();
|
||||
}
|
||||
|
||||
private Layout _Layout = null;
|
||||
public Layout Layout
|
||||
{
|
||||
get { return _Layout; }
|
||||
set
|
||||
{
|
||||
_Layout = value;
|
||||
}
|
||||
}
|
||||
public Control.ControlCollection Controls { get; }
|
||||
|
||||
protected override void OnNativeHandleCreating(CancelEventArgs e)
|
||||
{
|
||||
base.OnNativeHandleCreating(e);
|
||||
|
||||
// ensure the layout is created first
|
||||
if (Layout != null)
|
||||
{
|
||||
Layout.CreateImplementation();
|
||||
}
|
||||
}
|
||||
|
||||
public Container()
|
||||
{
|
||||
Controls = new Control.ControlCollection(this);
|
||||
}
|
||||
|
||||
protected override void InitializeImplementedProperties()
|
||||
{
|
||||
base.InitializeImplementedProperties();
|
||||
|
||||
foreach (Control ctl in Controls)
|
||||
{
|
||||
(Implementation as Container.IImplementation).InsertControl(ctl, Controls.IndexOf(ctl));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
namespace MBS.Desktop.Controls;
|
||||
|
||||
public class Control : Implementable
|
||||
{
|
||||
public class ControlCollection : System.Collections.ObjectModel.Collection<Control>
|
||||
{
|
||||
private Container _parent;
|
||||
public ControlCollection(Container parent)
|
||||
{
|
||||
_parent = parent;
|
||||
}
|
||||
|
||||
protected override void ClearItems()
|
||||
{
|
||||
((Container.IImplementation?)_parent.Implementation)?.RemoveAllControls();
|
||||
base.ClearItems();
|
||||
}
|
||||
protected override void InsertItem(int index, Control item)
|
||||
{
|
||||
base.InsertItem(index, item);
|
||||
((Container.IImplementation?)_parent.Implementation)?.InsertControl(item, index);
|
||||
}
|
||||
protected override void RemoveItem(int index)
|
||||
{
|
||||
((Container.IImplementation?)_parent.Implementation)?.RemoveControl(this[index]);
|
||||
base.RemoveItem(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,65 @@
|
||||
namespace MBS.Desktop.Controls;
|
||||
|
||||
public class Label : Control
|
||||
{
|
||||
public interface IImplementation
|
||||
{
|
||||
string GetText();
|
||||
void SetText(string value);
|
||||
|
||||
bool GetUseMarkup();
|
||||
void SetUseMarkup(bool value);
|
||||
}
|
||||
|
||||
public Label()
|
||||
{
|
||||
}
|
||||
public Label(string text)
|
||||
{
|
||||
this.Text = text;
|
||||
}
|
||||
|
||||
protected override void InitializeImplementedProperties()
|
||||
{
|
||||
base.InitializeImplementedProperties();
|
||||
|
||||
Text = _Text;
|
||||
UseMarkup = _UseMarkup;
|
||||
}
|
||||
|
||||
private string _Text = null;
|
||||
public string Text
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Implementation is IImplementation impl)
|
||||
{
|
||||
_Text = impl.GetText();
|
||||
}
|
||||
return _Text;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Text = value;
|
||||
(Implementation as IImplementation)?.SetText(value);
|
||||
}
|
||||
}
|
||||
|
||||
private bool _UseMarkup = false;
|
||||
public bool UseMarkup
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Implementation is IImplementation impl)
|
||||
{
|
||||
_UseMarkup = impl.GetUseMarkup();
|
||||
}
|
||||
return _UseMarkup;
|
||||
}
|
||||
set
|
||||
{
|
||||
_UseMarkup = value;
|
||||
(Implementation as IImplementation)?.SetUseMarkup(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
using MBS.Core;
|
||||
using MBS.Desktop.Layouts;
|
||||
|
||||
namespace MBS.Desktop.Controls;
|
||||
|
||||
public class MainWindow : Window
|
||||
{
|
||||
public MainWindow()
|
||||
{
|
||||
Layout = new BoxLayout(Orientation.Vertical);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
using MBS.Core.Drawing;
|
||||
|
||||
namespace MBS.Desktop.Controls;
|
||||
|
||||
public class Window : Container
|
||||
{
|
||||
public new interface IImplementation : Container.IImplementation
|
||||
{
|
||||
bool GetVisible();
|
||||
void SetVisible(bool value);
|
||||
|
||||
string GetTitle();
|
||||
void SetTitle(string title);
|
||||
|
||||
Dimension2D GetDefaultSize();
|
||||
void SetDefaultSize(Dimension2D size);
|
||||
|
||||
void Show();
|
||||
}
|
||||
|
||||
public void Show()
|
||||
{
|
||||
CreateImplementation();
|
||||
((Window.IImplementation)Implementation).Show();
|
||||
}
|
||||
|
||||
protected override void InitializeImplementedProperties()
|
||||
{
|
||||
base.InitializeImplementedProperties();
|
||||
|
||||
Title = _Title;
|
||||
DefaultSize = _DefaultSize;
|
||||
}
|
||||
|
||||
private string? _Title;
|
||||
public string? Title
|
||||
{
|
||||
get
|
||||
{
|
||||
string? title = (Implementation as Window.IImplementation)?.GetTitle();
|
||||
if (title is null)
|
||||
return _Title;
|
||||
|
||||
return title;
|
||||
}
|
||||
set
|
||||
{
|
||||
_Title = value;
|
||||
(Implementation as Window.IImplementation)?.SetTitle(value);
|
||||
}
|
||||
}
|
||||
|
||||
private Dimension2D _DefaultSize = new Dimension2D(-1, -1);
|
||||
public Dimension2D DefaultSize
|
||||
{
|
||||
get
|
||||
{
|
||||
Dimension2D? value = (Implementation as Window.IImplementation)?.GetDefaultSize();
|
||||
if (value is null)
|
||||
return _DefaultSize;
|
||||
|
||||
return value;
|
||||
}
|
||||
set
|
||||
{
|
||||
_DefaultSize = value;
|
||||
(Implementation as Window.IImplementation)?.SetDefaultSize(value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,14 +1,34 @@
|
||||
namespace MBS.Desktop;
|
||||
using MBS.Desktop.Controls;
|
||||
|
||||
namespace MBS.Desktop;
|
||||
|
||||
public class DesktopApplication : MBS.Core.Application
|
||||
{
|
||||
public DesktopApplicationEngine Engine { get; }
|
||||
public DesktopApplicationEngine Engine { get; private set; }
|
||||
|
||||
protected override int StartInternal()
|
||||
{
|
||||
// find the appropriate DesktopApplicationEngine for this platform
|
||||
Console.WriteLine("DesktopApplication::StartInternal");
|
||||
|
||||
return base.StartInternal();
|
||||
// find the appropriate DesktopApplicationEngine for this platform
|
||||
DesktopApplicationEngine[] engines = MBS.Core.Reflection.TypeLoader.GetAvailableTypes<DesktopApplicationEngine>();
|
||||
Console.WriteLine("DesktopApplicationEngine loader: found {0} engines", engines.Length);
|
||||
if (engines.Length > 0)
|
||||
{
|
||||
DesktopApplicationEngine engine = engines[0];
|
||||
if (engine != null)
|
||||
{
|
||||
Engine = engine;
|
||||
|
||||
Console.WriteLine("Using engine '{0}'", engine.GetType().FullName);
|
||||
return engine.Start();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error.WriteLine("no engines were found or could be loaded");
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
||||
protected override void StopInternal(int exitCode = 0)
|
||||
|
||||
@ -0,0 +1,28 @@
|
||||
namespace MBS.Desktop;
|
||||
|
||||
public abstract class DesktopApplicationEngine
|
||||
{
|
||||
protected abstract void InitializeInternal();
|
||||
|
||||
private bool _Initialized = false;
|
||||
public bool Initialize()
|
||||
{
|
||||
if (_Initialized)
|
||||
return false;
|
||||
|
||||
InitializeInternal();
|
||||
return true;
|
||||
}
|
||||
|
||||
public int Start()
|
||||
{
|
||||
Initialize();
|
||||
return StartInternal();
|
||||
}
|
||||
|
||||
protected virtual int StartInternal()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
namespace MBS.Desktop;
|
||||
|
||||
public interface IImplementable
|
||||
{
|
||||
Implementation? Implementation { get; }
|
||||
bool IsCreated { get; }
|
||||
void CreateImplementation();
|
||||
}
|
||||
@ -0,0 +1,62 @@
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace MBS.Desktop;
|
||||
|
||||
public abstract class Implementable : IImplementable
|
||||
{
|
||||
public Implementation? Implementation { get; protected set; }
|
||||
|
||||
public bool IsCreated { get; private set; }
|
||||
|
||||
protected virtual void InitializeImplementedProperties()
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnNativeHandleCreating(CancelEventArgs e)
|
||||
{
|
||||
}
|
||||
protected virtual void OnNativeHandleCreated(EventArgs e)
|
||||
{
|
||||
}
|
||||
protected virtual void OnCreated(EventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
public void CreateImplementation()
|
||||
{
|
||||
if (Implementation == null)
|
||||
{
|
||||
// determine which Implementation to use to create this Control
|
||||
Implementation[] impls = Core.Reflection.TypeLoader.GetAvailableTypes<Implementation>();
|
||||
foreach (Implementation impl in impls)
|
||||
{
|
||||
if (impl.Supports(GetType()))
|
||||
{
|
||||
Implementation = impl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!IsCreated)
|
||||
{
|
||||
if (Implementation == null)
|
||||
{
|
||||
throw new ImplementationNotFoundException();
|
||||
}
|
||||
|
||||
CancelEventArgs ce = new CancelEventArgs();
|
||||
OnNativeHandleCreating(ce);
|
||||
if (ce.Cancel)
|
||||
return;
|
||||
|
||||
Implementation.Create(this);
|
||||
IsCreated = true;
|
||||
|
||||
InitializeImplementedProperties();
|
||||
OnNativeHandleCreated(EventArgs.Empty);
|
||||
|
||||
OnCreated(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
using MBS.Desktop.Controls;
|
||||
|
||||
namespace MBS.Desktop;
|
||||
|
||||
public abstract class Implementation
|
||||
{
|
||||
public object Control { get; private set; }
|
||||
public NativeHandle Handle { get; private set; }
|
||||
|
||||
protected abstract NativeHandle CreateNativeHandle();
|
||||
|
||||
public void Create(IImplementable control)
|
||||
{
|
||||
Control = control;
|
||||
Handle = CreateNativeHandle();
|
||||
|
||||
OnNativeHandleCreated(EventArgs.Empty);
|
||||
OnCreated(EventArgs.Empty);
|
||||
}
|
||||
|
||||
protected virtual void OnNativeHandleCreated(EventArgs e)
|
||||
{
|
||||
}
|
||||
protected virtual void OnCreated(EventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
public bool Supports(Type typ)
|
||||
{
|
||||
Type typImpl = this.GetType();
|
||||
object[] attrs = typImpl.GetCustomAttributes(false);
|
||||
foreach (object attr in attrs)
|
||||
{
|
||||
if (attr is ImplementsForAttribute ifa)
|
||||
{
|
||||
if (ifa.Type == typ || typ.IsSubclassOf(ifa.Type))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
namespace MBS.Desktop;
|
||||
|
||||
public class ImplementationNotFoundException : Exception
|
||||
{
|
||||
|
||||
public ImplementationNotFoundException() : base("No implementation for the specified IImplementable could be found") { }
|
||||
public ImplementationNotFoundException(string message) : base(message) { }
|
||||
public ImplementationNotFoundException(string message, Exception innerException) : base(message, innerException) { }
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
namespace MBS.Desktop;
|
||||
|
||||
public class ImplementsForAttribute : Attribute
|
||||
{
|
||||
public Type Type { get; }
|
||||
|
||||
public ImplementsForAttribute(Type type)
|
||||
{
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
40
desktop-framework-dotnet/src/lib/MBS.Desktop/Layout.cs
Normal file
40
desktop-framework-dotnet/src/lib/MBS.Desktop/Layout.cs
Normal file
@ -0,0 +1,40 @@
|
||||
namespace MBS.Desktop;
|
||||
|
||||
public abstract class Layout : IImplementable
|
||||
{
|
||||
public interface IImplementation
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Implementation? Implementation { get; private set; }
|
||||
public bool IsCreated { get; private set; }
|
||||
public virtual void CreateImplementation()
|
||||
{
|
||||
if (Implementation == null)
|
||||
{
|
||||
// determine which Implementation to use to create this Control
|
||||
Implementation[] impls = Core.Reflection.TypeLoader.GetAvailableTypes<Implementation>();
|
||||
foreach (Implementation impl in impls)
|
||||
{
|
||||
if (impl.Supports(GetType()))
|
||||
{
|
||||
Implementation = impl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!IsCreated)
|
||||
{
|
||||
if (Implementation == null)
|
||||
{
|
||||
throw new ImplementationNotFoundException();
|
||||
}
|
||||
Implementation.Create(this);
|
||||
IsCreated = true;
|
||||
|
||||
// InitializeControlProperties();
|
||||
// OnCreated(EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
namespace MBS.Desktop.Layouts;
|
||||
|
||||
using MBS.Core;
|
||||
|
||||
public class BoxLayout : Layout
|
||||
{
|
||||
public new interface IImplementation : Layout.IImplementation
|
||||
{
|
||||
Orientation GetOrientation();
|
||||
void SetOrientation(Orientation value);
|
||||
}
|
||||
|
||||
private Orientation _Orientation = Orientation.Horizontal;
|
||||
public Orientation Orientation
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Implementation is BoxLayout.IImplementation impl)
|
||||
{
|
||||
return impl.GetOrientation();
|
||||
}
|
||||
return _Orientation;
|
||||
}
|
||||
set
|
||||
{
|
||||
(Implementation as BoxLayout.IImplementation)?.SetOrientation(value);
|
||||
_Orientation = value;
|
||||
}
|
||||
}
|
||||
|
||||
public BoxLayout(Orientation orientation = Orientation.Horizontal)
|
||||
{
|
||||
Orientation = orientation;
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MBS.Core\MBS.Core.csproj" />
|
||||
<ProjectReference Include="..\..\..\..\..\framework-dotnet\framework-dotnet\src\lib\MBS.Core\MBS.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
|
||||
@ -0,0 +1,5 @@
|
||||
namespace MBS.Desktop;
|
||||
|
||||
public abstract class NativeHandle
|
||||
{
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
namespace MBS.Desktop;
|
||||
|
||||
public abstract class NativeImplementation : Implementation
|
||||
{
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user