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 class DesktopApplication : MBS.Core.Application
|
||||||
{
|
{
|
||||||
public DesktopApplicationEngine Engine { get; }
|
public DesktopApplicationEngine Engine { get; private set; }
|
||||||
|
|
||||||
protected override int StartInternal()
|
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)
|
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">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\MBS.Core\MBS.Core.csproj" />
|
<ProjectReference Include="..\..\..\..\..\framework-dotnet\framework-dotnet\src\lib\MBS.Core\MBS.Core.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<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