Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to set up native control when subclassing NativeControlHost #2590

Merged
merged 1 commit into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 27 additions & 8 deletions src/Eto.Gtk/Forms/Controls/NativeControlHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,46 @@ public NativeControlHandler()
{
}

public void Create(object controlObject)
protected override void Initialize()
{
if (controlObject == null)
// don't call any initialize routines as we are hosting a native control
// base.Initialize();
}

protected override Gtk.Widget CreateControl()
{
if (Widget is NativeControlHost host && Callback is NativeControlHost.ICallback callback)
{
var args = new CreateNativeControlArgs();
callback.OnCreateNativeControl(host, args);
return CreateHost(args.NativeControl);
}
return base.CreateControl();
}

public void Create(object nativeControl) => CreateHost(nativeControl);

Gtk.Widget CreateHost(object nativeControl)
{
if (nativeControl == null)
{
Control = _eventBox;
return _eventBox;
}
else if (controlObject is Gtk.Widget widget)
else if (nativeControl is Gtk.Widget widget)
{
Control = widget;
_eventBox.Child = widget;
return _eventBox;
}
else if (controlObject is IntPtr handle)
else if (nativeControl is IntPtr handle)
{
widget = GLib.Object.GetObject(handle) as Gtk.Widget;
if (widget == null)
throw new InvalidOperationException("Could not convert handle to Gtk.Widget");
Control = widget;
_eventBox.Child = widget;
return _eventBox;
}
else
throw new NotSupportedException($"controlObject of type {controlObject.GetType()} is not supported by this platform");
throw new NotSupportedException($"Native control of type {nativeControl.GetType()} is not supported by this platform");
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Eto.Gtk/GtkHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public static Control ToEto(this Gtk.Widget nativeWidget)
{
if (nativeWidget == null)
return null;
return new Control(new NativeControlHandler(nativeWidget));
return new NativeControlHost(nativeWidget);
}

/// <summary>
Expand Down
47 changes: 37 additions & 10 deletions src/Eto.Mac/Forms/Controls/NativeControlHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,26 @@ public NativeControlHandler()
{
}

protected override void Initialize()
{
// don't call any initialize routines as we are hosting a native control
base.Initialize();
}

protected override NSView CreateControl()
{
if (Widget is NativeControlHost host && Callback is NativeControlHost.ICallback callback)
{
var args = new CreateNativeControlArgs();
callback.OnCreateNativeControl(host, args);
return CreateHost(args.NativeControl);
}
return base.CreateControl();
}

public override SizeF GetPreferredSize(SizeF availableSize)
{
return Control.FittingSize.ToEto();
return Control?.FittingSize.ToEto() ?? SizeF.Empty;
}

public NativeControlHandler(NSViewController nativeControl)
Expand All @@ -24,27 +41,37 @@ public NativeControlHandler(NSViewController nativeControl)
Control = controller.View;
}

public override NSView ContainerControl { get { return Control; } }
public override NSView ContainerControl => Control;

public void Create(object controlObject)
public void Create(object nativeControl)
{
Control = CreateHost(nativeControl);
}

NSView CreateHost(object nativeControl)
{
if (controlObject == null)
if (nativeControl == null)
{
return new NSView();
}
else if (nativeControl is NSView view)
{
Control = new NSView();
return view;
}
else if (controlObject is NSView view)
else if (nativeControl is NSViewController viewController)
{
Control = view;
controller = viewController;
return controller.View;
}
else if (controlObject is IntPtr handle)
else if (nativeControl is IntPtr handle)
{
view = Runtime.GetNSObject(handle) as NSView;
if (view == null)
throw new InvalidOperationException("supplied handle is invalid or does not refer to an object derived from NSView");
Control = view;
return view;
}
else
throw new NotSupportedException($"controlObject of type {controlObject.GetType()} is not supported by this platform");
throw new NotSupportedException($"Native control of type {nativeControl.GetType()} is not supported by this platform");
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/Eto.Mac/MacHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ public static Control ToEto(this NSView view)
{
if (view == null)
return null;
return new Control(new NativeControlHandler(view));
return new NativeControlHost(view);
}

/// <summary>
Expand All @@ -78,7 +78,7 @@ public static Control ToEto(this NSViewController viewController)
{
if (viewController == null)
return null;
return new Control(new NativeControlHandler(viewController));
return new NativeControlHost(viewController);
}

/// <summary>
Expand Down
52 changes: 37 additions & 15 deletions src/Eto.WinForms/Forms/Controls/NativeControlHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,42 +14,64 @@ public NativeControlHandler()
{
}

protected override void Initialize()
{
// don't call any initialize routines as we are hosting a native control
//base.Initialize();
}

protected override swf.Control CreateControl()
{
if (Widget is NativeControlHost host && Callback is NativeControlHost.ICallback callback)
{
var args = new CreateNativeControlArgs();
callback.OnCreateNativeControl(host, args);
return CreateHost(args.NativeControl);
}
return base.CreateControl();
}


public void Create(object controlObject)
public void Create(object nativeControl)
{
Control = CreateHost(nativeControl);
}
swf.Control CreateHost(object nativeControl)
{
if (controlObject == null)
if (nativeControl == null)
{
Control = new swf.UserControl();
return new swf.UserControl();
}
else if (controlObject is swf.Control control)
else if (nativeControl is swf.Control control)
{
Control = control;
return control;
}
else if (controlObject is IntPtr handle)
else if (nativeControl is IntPtr handle)
{
CreateWithHandle(handle);
return CreateWithHandle(handle);
}
else if (controlObject is swf.IWin32Window win32Window)
else if (nativeControl is swf.IWin32Window win32Window)
{
// keep a reference so it doesn't get GC'd
_win32Window = win32Window;
CreateWithHandle(win32Window.Handle);
return CreateWithHandle(win32Window.Handle);
}
else
throw new NotSupportedException($"controlObject of type {controlObject.GetType()} is not supported by this platform");
throw new NotSupportedException($"Native control of type {nativeControl.GetType()} is not supported by this platform");
}

private void CreateWithHandle(IntPtr handle)
private swf.Control CreateWithHandle(IntPtr handle)
{
Control = new swf.Control();
var control = new swf.Control();
Win32.GetWindowRect(handle, out var rect);
Win32.SetParent(handle, Control.Handle);
Control.Size = rect.ToSD().Size;
Win32.SetParent(handle, control.Handle);
control.Size = rect.ToSD().Size;
Widget.SizeChanged += (sender, e) =>
{
var size = Control.Size;
var size = control.Size;
Win32.SetWindowPos(handle, IntPtr.Zero, 0, 0, size.Width, size.Height, Win32.SWP.NOZORDER);
};
return control;
}
}
}
Expand Down
6 changes: 2 additions & 4 deletions src/Eto.WinForms/Forms/WindowsControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -184,9 +184,9 @@ protected override void OnParentBackColorChanged(EventArgs e)

Control.ICallback IWindowsControl.Callback { get { return Callback; } }

public bool XScale { get; set; }
public bool XScale { get; set; } = true;

public bool YScale { get; set; }
public bool YScale { get; set; } = true;

public virtual Size? GetDefaultSize(Size availableSize) { return null; }// Control.GetPreferredSize(availableSize.ToSD()).ToEto(); }

Expand Down Expand Up @@ -276,8 +276,6 @@ public bool MouseCaptured
protected override void Initialize()
{
base.Initialize();
XScale = true;
YScale = true;
Control.Margin = swf.Padding.Empty;
Control.Tag = this;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Eto.WinForms/WinFormsHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public static Control ToEto(this swf.Control nativeControl)
{
if (nativeControl == null)
return null;
return new Control(new NativeControlHandler(nativeControl));
return new NativeControlHost(nativeControl);
}

/// <summary>
Expand Down
46 changes: 34 additions & 12 deletions src/Eto.Wpf/Forms/Controls/NativeControlHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,44 +25,66 @@ public NativeControlHandler(sw.FrameworkElement nativeControl)
Control = nativeControl;
}

protected override void Initialize()
{
// don't call any initialize routines as we are hosting a native control
// base.Initialize();
}

protected override sw.FrameworkElement CreateControl()
{
if (Widget is NativeControlHost host && Callback is NativeControlHost.ICallback callback)
{
var args = new CreateNativeControlArgs();
callback.OnCreateNativeControl(host, args);
return CreateHost(args.NativeControl);
}
return base.CreateControl();
}

public override Color BackgroundColor
{
get => throw new NotSupportedException("You cannot get this property for native controls");
set => throw new NotSupportedException("You cannot set this property for native controls");
}

public void Create(object controlObject)
public void Create(object nativeControl)
{
Control = CreateHost(nativeControl);
}

public sw.FrameworkElement CreateHost(object nativeControl)
{
if (controlObject == null)
if (nativeControl == null)
{
var host = new EtoHwndHost(null);
host.GetPreferredSize += () => Size.Round(UserPreferredSize.ToEto() * (Widget.ParentWindow?.Screen?.LogicalPixelSize ?? 1));
Control = host;
return host;
}
else if (controlObject is sw.FrameworkElement element)
else if (nativeControl is sw.FrameworkElement element)
{
Control = element;
return element;
}
else if (controlObject is IntPtr handle)
else if (nativeControl is IntPtr handle)
{
Control = new EtoHwndHost(new HandleRef(this, handle));
return new EtoHwndHost(new HandleRef(this, handle));
}
else if (controlObject is IWin32WindowWinForms win32Window)
else if (nativeControl is IWin32WindowWinForms win32Window)
{
// keep a reference to the win32window object
var host = new EtoHwndHost(new HandleRef(win32Window, win32Window.Handle));
host.GetPreferredSize += () => Size.Round(UserPreferredSize.ToEto() * (Widget.ParentWindow?.Screen?.LogicalPixelSize ?? 1));
Control = host;
return host;
}
else if (controlObject is IWin32WindowInterop win32WindowWpf)
else if (nativeControl is IWin32WindowInterop win32WindowWpf)
{
// keep a reference to the win32window object
var host = new EtoHwndHost(new HandleRef(win32WindowWpf, win32WindowWpf.Handle));
host.GetPreferredSize += () => Size.Round(UserPreferredSize.ToEto() * (Widget.ParentWindow?.Screen?.LogicalPixelSize ?? 1));
Control = host;
return host;
}
else
throw new NotSupportedException($"controlObject of type {controlObject.GetType()} is not supported by this platform");
throw new NotSupportedException($"Native control of type {nativeControl.GetType()} is not supported by this platform");
}
}

Expand Down
Loading
Loading