using System;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Forms.Integration;
using JetBrains.Annotations;
namespace JetBrains.UI.Avalon.Interop
{
///
/// Adapts the WinForms and Avalon controls to one another.
///
public class EitherControl : IDisposable
{
#region Data
///
/// Stores the WinForms control, if explicitly inited.
/// and are mutually exclusive.
///
private readonly Control myControl;
///
/// Stores the Avalon element, if explicitly inited.
/// and are mutually exclusive.
///
private readonly UIElement myElement;
///
/// Stores the element host that adapts an Avalon control to the WinForms host, in case we were created with an Avalon control. Lazy-created.
///
private ElementHost myElementHost;
private bool myIsDisposed;
///
/// Stores the winforms host that adapts a WinForms control to the Avalon host, in case we were created with a WinForms control. Lazy-created.
///
private WindowsFormsHost myWindowsFormsHost;
#endregion
#region Init
///
/// Initializes from a WinForms control.
///
public EitherControl([NotNull] Control control)
{
if(control == null)
throw new ArgumentNullException("control");
// Try unwrapping
var host = control as ElementHost;
if(host != null)
{
myElement = host.Child;
myElementHost = host;
}
else
myControl = control;
}
///
/// Initializes from an Avalon element.
///
public EitherControl([NotNull] UIElement element)
{
if(element == null)
throw new ArgumentNullException("element");
// Try unwrapping
var host = element as WindowsFormsHost;
if(host != null)
{
myControl = host.Child;
myWindowsFormsHost = host;
}
else
myElement = element;
}
#endregion
#region Attributes
///
/// Gets the contained either-control as a Windows Forms control, creating a wrapper as needed.
///
public Control Control
{
get
{
if(myControl != null)
return myControl;
if(myElementHost == null)
{
myElementHost = new ElementHost();
myElementHost.Child = myElement;
}
return myElementHost;
}
}
///
/// Gets the contained either-control as an Avalon UI element, creating a wrapper as needed.
///
public UIElement Element
{
get
{
if(myElement != null)
return myElement;
if(myWindowsFormsHost == null)
{
myWindowsFormsHost = new WindowsFormsHost();
myWindowsFormsHost.Child = myControl;
}
return myWindowsFormsHost;
}
}
///
/// Gets whether the WinForms controls have been disposed of.
///
public bool IsDisposed
{
get
{
return myIsDisposed;
}
}
#endregion
#region Operations
///
/// Detects the control type, throws if neither. Calls the appropriate ctor.
///
public static EitherControl FromObject([NotNull] object either)
{
if(either == null)
throw new ArgumentNullException("either");
var control = either as Control;
if(control != null)
return new EitherControl(control);
var element = either as UIElement;
if(element != null)
return new EitherControl(element);
throw new InvalidOperationException(string.Format("The control type “{0}” is not supported.", either.GetType().AssemblyQualifiedName));
}
#endregion
#region ERROR
public static implicit operator Control([NotNull] EitherControl either)
{
if(either == null)
throw new ArgumentNullException("either");
return either.Control;
}
public static implicit operator UIElement([NotNull] EitherControl either)
{
if(either == null)
throw new ArgumentNullException("either");
return either.Element;
}
public static implicit operator EitherControl([NotNull] Control control)
{
if(control == null)
throw new ArgumentNullException("control");
return new EitherControl(control);
}
public static implicit operator EitherControl([NotNull] UIElement element)
{
if(element == null)
throw new ArgumentNullException("element");
return new EitherControl(element);
}
#endregion
#region IDisposable Members
///
///Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
///
///2
public void Dispose()
{
myIsDisposed = true;
if(myControl != null)
myControl.Dispose();
if(myElementHost != null)
myElementHost.Dispose();
}
#endregion
}
}