namespace Eto.Forms; /// /// Base for all visual UI elements /// /// /// All visual user interface elements should inherit from this class to provide common functionality like binding, /// load/unload, and common events. /// [sc.TypeConverter(typeof(ControlConverter))] public partial class Control : BindableWidget, IMouseInputSource, IKeyboardInputSource, ICallbackSource { /// /// Gets or sets a value indicating the UI is being shown in a designer preview, e.g. to supply sample data. /// /// /// Set by the designer when it starts; applications should not need to set this. /// public static bool IsDesignMode { get; set; } // shared by the xaml and json readers so a user control in either format inherits its parent's design data [ThreadStatic] static int designLoadDepth; internal static void BeginDesignLoad() => designLoadDepth++; internal static void EndDesignLoad() => designLoadDepth--; /// True while loading the outermost file in design mode, where d:DataContext applies. internal static bool IsDesignRootLoad => IsDesignMode && designLoadDepth == 1; /// /// Gets the handler for the widget, ensuring the current thread is the UI thread /// /// The handler object for this control protected new IHandler Handler { get { Application.Instance?.EnsureUIThread(); return (IHandler)base.Handler; } } static readonly object GesturesKey = new object(); /// /// Gets the gestures attached to this control. /// public Collection Gestures => Properties.Create(GesturesKey, () => new GestureCollection(this)); class GestureCollection : Collection { public GestureCollection(Control control) { this.control = control; } private readonly Control control; protected override void InsertItem(int index, Gesture item) { control.Handler.AddGesture(item); item.Control = control; base.InsertItem(index, item); } protected override void ClearItems() { foreach (var item in this) { item.Control = null; } control.Handler.ClearGestures(); base.ClearItems(); } protected override void RemoveItem(int index) { var item = this[index]; control.Handler.RemoveGesture(item); item.Control = null; base.RemoveItem(index); } protected override void SetItem(int index, Gesture item) { var oldItem = this[index]; control.Handler.AddGesture(item); control.Handler.RemoveGesture(oldItem); oldItem.Control = null; item.Control = control; base.SetItem(index, item); } } /// /// Gets a value indicating that the control is loaded onto a form, that is it has been created, added to a parent, and shown /// /// /// The method sets this value to true after cascading to all children (for a ) /// and calling the platform handler's implementation. It is called after adding to a loaded form, or when showing a new form. /// /// The method will set this value to false when the control is removed from its parent /// public bool Loaded { get => GetState(StateFlag.Loaded); private set => SetState(StateFlag.Loaded, value); } /// /// Gets a value indicating that has been raised since the control was last loaded. /// /// /// A control is before it gets its LoadComplete, so this is used to ensure LoadComplete is /// only raised once, e.g. when a child is added to a container that is loaded but hasn't had LoadComplete yet. /// internal bool IsLoadComplete { get => GetState(StateFlag.LoadComplete); private set => SetState(StateFlag.LoadComplete, value); } /// /// Gets an enumeration of controls that are in the visual tree. /// /// /// This is used to specify which controls are contained by this instance that are part of the visual tree. /// This should include all controls including non-logical Eto controls used for layout. /// /// The visual controls. public virtual IEnumerable VisualControls => Handler.VisualControls; /// /// Gets or sets a user-defined object that contains data about the control /// /// /// A common use of the tag property is to store data that is associated with the control that you can later /// retrieve. /// public object Tag { get { return Properties.Get(TagKey); } set { Properties[TagKey] = value; } } /// /// Gets the logical parent control. /// /// /// When the control is part of the visual tree ( is true), this returns the logical parent that contains this control. /// Otherwise this is the same as . /// /// The logical parent. public Container LogicalParent { get { if (IsVisualControl) { var foundVisual = false; foreach (var parent in Parents.OfType()) { if (!foundVisual && parent.GetState(StateFlag.IsVisualControl)) foundVisual = true; else return parent; } } return Parent; } } /// /// Gets a value indicating this is part of the visual tree. /// /// true if is visual control; otherwise, false. public bool IsVisualControl { get => GetState(StateFlag.IsVisualControl, StateFlag.IsVisualControlHasValue) ?? Parent?.IsVisualControl ?? false; // traverse up logical tree internal set => SetState(StateFlag.IsVisualControl, StateFlag.IsVisualControlHasValue, value); } static readonly object TagKey = new object(); #region Events /// /// Event identifier for handlers when attaching the event /// public const string SizeChangedEvent = "Control.SizeChanged"; /// /// Occurs when the size of the control is changed. /// public event EventHandler SizeChanged { add { Properties.AddHandlerEvent(SizeChangedEvent, value); } remove { Properties.RemoveEvent(SizeChangedEvent, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnSizeChanged(EventArgs e) { Properties.TriggerEvent(SizeChangedEvent, this, e); } /// /// Event identifier for handlers when attaching the event. /// public const string KeyDownEvent = "Control.KeyDown"; /// /// Occurs when a key has been pressed and is down /// /// public event EventHandler KeyDown { add { Properties.AddHandlerEvent(KeyDownEvent, value); } remove { Properties.RemoveEvent(KeyDownEvent, value); } } /// /// Raises the event. /// /// Key event arguments protected virtual void OnKeyDown(KeyEventArgs e) { Properties.TriggerEvent(KeyDownEvent, this, e); } /// /// Event identifier for handlers when attaching the event /// public const string KeyUpEvent = "Control.KeyUp"; /// /// Occurs when a key was released /// /// public event EventHandler KeyUp { add { Properties.AddHandlerEvent(KeyUpEvent, value); } remove { Properties.RemoveEvent(KeyUpEvent, value); } } /// /// Raises the event. /// /// Key event arguments protected virtual void OnKeyUp(KeyEventArgs e) { Properties.TriggerEvent(KeyUpEvent, this, e); } /// /// Event identifier for handlers when attaching the event /// public const string TextInputEvent = "Control.TextInput"; /// /// Occurs when text is input for the control. Currently only partially supported on iOS. /// public event EventHandler TextInput { add { Properties.AddHandlerEvent(TextInputEvent, value); } remove { Properties.RemoveEvent(TextInputEvent, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnTextInput(TextInputEventArgs e) { Properties.TriggerEvent(TextInputEvent, this, e); } /// /// Event identifier for handlers when attaching the event /// public const string MouseDownEvent = "Control.MouseDown"; /// /// Occurs when a mouse button has been pressed /// /// /// Controls will typically capture the mouse after a mouse button is pressed and will be released /// only after the event. /// /// public event EventHandler MouseDown { add { Properties.AddHandlerEvent(MouseDownEvent, value); } remove { Properties.RemoveEvent(MouseDownEvent, value); } } /// /// Raises the event. /// /// /// To override default behaviour of the control, set property to true. /// /// Event arguments protected virtual void OnMouseDown(MouseEventArgs e) { Properties.TriggerEvent(MouseDownEvent, this, e); } /// /// Event identifier for handlers when attaching the event /// public const string MouseUpEvent = "Control.MouseUp"; /// /// Occurs when a mouse button is released /// /// public event EventHandler MouseUp { add { Properties.AddHandlerEvent(MouseUpEvent, value); } remove { Properties.RemoveEvent(MouseUpEvent, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnMouseUp(MouseEventArgs e) { Properties.TriggerEvent(MouseUpEvent, this, e); } /// /// Event identifier for handlers when attaching the event /// public const string MouseMoveEvent = "Control.MouseMove"; /// /// Occurs when mouse moves within the bounds of the control, or when the mouse is captured /// /// /// The mouse is captured after a event within the control, /// and is released when the mouse button is released /// /// /// public event EventHandler MouseMove { add { Properties.AddHandlerEvent(MouseMoveEvent, value); } remove { Properties.RemoveEvent(MouseMoveEvent, value); } } /// /// Raises the event. /// /// Mouse event args protected virtual void OnMouseMove(MouseEventArgs e) { Properties.TriggerEvent(MouseMoveEvent, this, e); } /// /// Event identifier for handlers when attaching the event /// public const string MouseLeaveEvent = "Control.MouseLeave"; /// /// Occurs when mouse leaves the bounds of the control /// public event EventHandler MouseLeave { add { Properties.AddHandlerEvent(MouseLeaveEvent, value); } remove { Properties.RemoveEvent(MouseLeaveEvent, value); } } /// /// Raises the event. /// /// Mouse event arguments /// protected virtual void OnMouseLeave(MouseEventArgs e) { Properties.TriggerEvent(MouseLeaveEvent, this, e); } /// /// Event identifier for handlers when attaching the event /// public const string MouseEnterEvent = "Control.MouseEnter"; /// /// Occurs when the mouse enters the bounds of the control /// /// public event EventHandler MouseEnter { add { Properties.AddHandlerEvent(MouseEnterEvent, value); } remove { Properties.RemoveEvent(MouseEnterEvent, value); } } /// /// Raises the event. /// /// Mouse event arguments protected virtual void OnMouseEnter(MouseEventArgs e) { Properties.TriggerEvent(MouseEnterEvent, this, e); } /// /// Event identifier for handlers when attaching the event /// public const string MouseDoubleClickEvent = "Control.MouseDoubleClick"; /// /// Occurs when a mouse button is double clicked within the bounds of the control /// /// /// If you do not set the property to true, and the default behaviour of /// the control does not accept double clicks, the event will be called for each click of /// the mouse button. /// /// For example, if the user clicks twice in succession, the following will be called: /// 1. MouseDown for the first click /// 2. MouseDoubleClick for the second click /// 3. If Handled has not been set in #2, MouseDown will be called a 2nd time /// /// public event EventHandler MouseDoubleClick { add { Properties.AddHandlerEvent(MouseDoubleClickEvent, value); } remove { Properties.RemoveEvent(MouseDoubleClickEvent, value); } } /// /// Raises the mouse event. /// /// Mouse event arguments protected virtual void OnMouseDoubleClick(MouseEventArgs e) { Properties.TriggerEvent(MouseDoubleClickEvent, this, e); } /// /// Event identifier for handlers when attaching the event /// public const string MouseWheelEvent = "Control.MouseWheel"; /// /// Occurs when mouse wheel has been changed /// public event EventHandler MouseWheel { add { Properties.AddHandlerEvent(MouseWheelEvent, value); } remove { Properties.RemoveEvent(MouseWheelEvent, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnMouseWheel(MouseEventArgs e) { Properties.TriggerEvent(MouseWheelEvent, this, e); } /// /// Event identifier for handlers when attaching the event /// public const string GotFocusEvent = "Control.GotFocus"; /// /// Occurs when the control receives keyboard focus. /// /// /// Note that not all controls can recieve keyboard focus. /// /// public event EventHandler GotFocus { add { Properties.AddHandlerEvent(GotFocusEvent, value); } remove { Properties.RemoveEvent(GotFocusEvent, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnGotFocus(EventArgs e) { Properties.TriggerEvent(GotFocusEvent, this, e); } /// /// Event identifier for handlers when attaching the event /// public const string LostFocusEvent = "Control.LostFocus"; /// /// Occurs when control loses keyboard focus /// /// /// Note that not all controls can recieve keyboard focus /// /// public event EventHandler LostFocus { add { Properties.AddHandlerEvent(LostFocusEvent, value); } remove { Properties.RemoveEvent(LostFocusEvent, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnLostFocus(EventArgs e) { Properties.TriggerEvent(LostFocusEvent, this, e); } /// /// Event identifier for handlers when attaching the event /// public const string ShownEvent = "Control.Shown"; /// /// Occurs when the control is shown on the screen /// /// /// This event fires when the property changes, or when initially showing a control /// on a form. /// public event EventHandler Shown { add { Properties.AddHandlerEvent(ShownEvent, value); } remove { Properties.RemoveEvent(ShownEvent, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnShown(EventArgs e) { Properties.TriggerEvent(ShownEvent, this, e); } /// /// Event identifier for handlers when attaching the event /// public const string ThemeChangedEvent = "Control.ThemeChanged"; /// /// Occurs when the control's theme changes either due to a system theme change /// or when Application.Instance.CurrentTheme is set. /// public event EventHandler ThemeChanged { add { Properties.AddHandlerEvent(ThemeChangedEvent, value); } remove { Properties.RemoveEvent(ThemeChangedEvent, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnThemeChanged(EventArgs e) { Properties.TriggerEvent(ThemeChangedEvent, this, e); } static readonly object PreLoadKey = new object(); /// /// Occurs before the control is loaded. See the event for more detail. /// /// /// /// public event EventHandler PreLoad { add { Properties.AddEvent(PreLoadKey, value); } remove { Properties.RemoveEvent(PreLoadKey, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnPreLoad(EventArgs e) { Properties.TriggerEvent(PreLoadKey, this, e); Handler.OnPreLoad(e); OnApplyCascadingStyles(); } static readonly object LoadKey = new object(); /// /// Occurs when the control is displayed on a visible window /// /// /// A control is loaded when it is part of the control hierarchy and is shown on a window. /// When the control is removed from the hierarchy, or the window is closed, the event /// will be called. /// /// /// /// public event EventHandler Load { add { Properties.AddEvent(LoadKey, value); } remove { Properties.RemoveEvent(LoadKey, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnLoad(EventArgs e) { #if DEBUG if (Loaded) throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Control was loaded more than once")); #endif Properties.TriggerEvent(LoadKey, this, e); Handler.OnLoad(e); Loaded = true; } static readonly object LoadCompleteKey = new object(); /// /// Occurs when the load is complete, which happens after the event and before the window/control is shown. /// /// /// This is a good place to reposition a Window before it is shown. /// /// /// /// public event EventHandler LoadComplete { add { Properties.AddEvent(LoadCompleteKey, value); } remove { Properties.RemoveEvent(LoadCompleteKey, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnLoadComplete(EventArgs e) { Properties.TriggerEvent(LoadCompleteKey, this, e); Handler.OnLoadComplete(e); } static readonly object UnLoadKey = new object(); /// /// Occurs when the control is unloaded, which happens when removed from the control hierarchy or the window is closed. /// /// /// /// public event EventHandler UnLoad { add { Properties.AddEvent(UnLoadKey, value); } remove { Properties.RemoveEvent(UnLoadKey, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnUnLoad(EventArgs e) { #if DEBUG if (!Loaded) throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Control was unloaded more than once")); #endif Loaded = false; IsLoadComplete = false; Properties.TriggerEvent(UnLoadKey, this, e); Handler.OnUnLoad(e); } /// /// Event identifier for handlers when attaching the event /// public const string DragDropEvent = "Control.DragDrop"; /// /// Occurs when a drag operation is dropped onto the control. /// /// /// This should perform any of the actual drop logic and update the control state to reflect the dropped data. /// Any cleanup should be performed in the event, which is called immediately before this event. /// public event EventHandler DragDrop { add { Properties.AddHandlerEvent(DragDropEvent, value); } remove { Properties.RemoveEvent(DragDropEvent, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnDragDrop(DragEventArgs e) { Properties.TriggerEvent(DragDropEvent, this, e); } /// /// Event identifier for handlers when attaching the event /// public const string DragOverEvent = "Control.DragOver"; /// /// Occurs when a drag operation is over the control and needs updating based on position or keyboard state changes. /// public event EventHandler DragOver { add { Properties.AddHandlerEvent(DragOverEvent, value); } remove { Properties.RemoveEvent(DragOverEvent, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnDragOver(DragEventArgs e) => Properties.TriggerEvent(DragOverEvent, this, e); /// /// Event identifier for handlers when attaching the event /// public const string DragEnterEvent = "Control.DragEnter"; /// /// Occurs when a drag operation enters the bounds of the control. /// public event EventHandler DragEnter { add { Properties.AddHandlerEvent(DragEnterEvent, value); } remove { Properties.RemoveEvent(DragEnterEvent, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnDragEnter(DragEventArgs e) => Properties.TriggerEvent(DragEnterEvent, this, e); /// /// Event identifier for handlers when attaching the event /// public const string DragLeaveEvent = "Control.DragLeave"; /// /// Occurs when a drag operation leaves the bounds of the control or the drag operation was completed inside the control. /// /// /// Use this event to 'clean up' any state of the control for the current drag operation. /// This will be called before the event. /// public event EventHandler DragLeave { add { Properties.AddHandlerEvent(DragLeaveEvent, value); } remove { Properties.RemoveEvent(DragLeaveEvent, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnDragLeave(DragEventArgs e) => Properties.TriggerEvent(DragLeaveEvent, this, e); /// /// Event identifier for handlers when attaching the event /// public const string DragEndEvent = "Control.DragEnd"; /// /// Occurs for a source control after a call to when the drag operation has ended. /// The is the final used at the drop destination. /// /// /// For controls that you are dragging from this event is useful to know what to do with the dragged content after it is dropped in a different control or application. /// public event EventHandler DragEnd { add { Properties.AddHandlerEvent(DragEndEvent, value); } remove { Properties.RemoveEvent(DragEndEvent, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnDragEnd(DragEventArgs e) => Properties.TriggerEvent(DragEndEvent, this, e); /// /// Event identifier for handlers when attaching the event /// public const string EnabledChangedEvent = "Control.EnabledChanged"; /// /// Occurs when the value is changed. /// public event EventHandler EnabledChanged { add { Properties.AddHandlerEvent(EnabledChangedEvent, value); } remove { Properties.RemoveEvent(EnabledChangedEvent, value); } } /// /// Raises the event. /// /// Event arguments protected virtual void OnEnabledChanged(EventArgs e) => Properties.TriggerEvent(EnabledChangedEvent, this, e); #endregion static Control() { EventLookup.Register(c => c.OnGotFocus(null), Control.GotFocusEvent); EventLookup.Register(c => c.OnKeyDown(null), Control.KeyDownEvent); EventLookup.Register(c => c.OnKeyUp(null), Control.KeyUpEvent); EventLookup.Register(c => c.OnLostFocus(null), Control.LostFocusEvent); EventLookup.Register(c => c.OnMouseDoubleClick(null), Control.MouseDoubleClickEvent); EventLookup.Register(c => c.OnMouseDown(null), Control.MouseDownEvent); EventLookup.Register(c => c.OnMouseEnter(null), Control.MouseEnterEvent); EventLookup.Register(c => c.OnMouseLeave(null), Control.MouseLeaveEvent); EventLookup.Register(c => c.OnMouseMove(null), Control.MouseMoveEvent); EventLookup.Register(c => c.OnMouseUp(null), Control.MouseUpEvent); EventLookup.Register(c => c.OnMouseWheel(null), Control.MouseWheelEvent); EventLookup.Register(c => c.OnShown(null), Control.ShownEvent); EventLookup.Register(c => c.OnSizeChanged(null), Control.SizeChangedEvent); EventLookup.Register(c => c.OnTextInput(null), Control.TextInputEvent); EventLookup.Register(c => c.OnDragDrop(null), Control.DragDropEvent); EventLookup.Register(c => c.OnDragOver(null), Control.DragOverEvent); EventLookup.Register(c => c.OnDragEnter(null), Control.DragEnterEvent); EventLookup.Register(c => c.OnDragLeave(null), Control.DragLeaveEvent); EventLookup.Register(c => c.OnDragEnd(null), Control.DragEndEvent); EventLookup.Register(c => c.OnEnabledChanged(null), Control.EnabledChangedEvent); EventLookup.Register(c => c.OnThemeChanged(null), Control.ThemeChangedEvent); } /// /// Initializes a new instance of the class. /// protected Control() { } /// /// Initializes a new instance of the Container with the specified handler /// /// Pre-created handler to attach to this instance public Control(IHandler handler) : base(handler) { } /// /// Queues a repaint of the entire control on the screen and any of its children. /// /// /// This is only useful when the control is visible. /// public void Invalidate() { Handler.Invalidate(true); } /// /// Queues a repaint of the entire control on the screen /// /// /// This is only useful when the control is visible. /// /// True to invalidate all children, false to only invalidate the container public void Invalidate(bool invalidateChildren) { Handler.Invalidate(invalidateChildren); } /// /// Queues a repaint of the specified of the control and any children. /// /// /// This is only useful when the control is visible. /// /// Rectangle to repaint public void Invalidate(Rectangle rect) { Handler.Invalidate(rect, true); } /// /// Queues a repaint of the specified of the control /// /// /// This is only useful when the control is visible. /// /// Rectangle to repaint /// True to invalidate all children, false to only invalidate the container public void Invalidate(Rectangle rect, bool invalidateChildren) { Handler.Invalidate(rect, invalidateChildren); } /// /// Updates the layout of this control if necessary. /// /// /// This will ensure the control has had all of its layout applied so you can use its position and size right after this call. /// Most platforms (except WinForms) use a deferred layout system so that after adding your control to the form dynamically it won't /// get laid out until the next idle loop. /// This is useful when you need to know the dimensions of the control immediately. /// Note that this can be an expensive operation, so it is recommended to only call this method when necessary and after all of the /// controls have been added/updated. /// public void UpdateLayout() => Handler.UpdateLayout(); /// /// Gets or sets the size of the control. Use -1 to specify auto sizing for either the width and/or height. /// /// /// Setting the size of controls is entirely optional as most controls will size themselves appropriately. /// When specifying a size, it will be used as the desired size of the control. The container will reposition /// and resize the control depending on the available size. /// /// For a , it is preferred to set the instead, as various /// platforms have different sizes of window decorations, toolbars, etc. /// /// The current size of the control public virtual Size Size { get { return Handler.Size; } set { Handler.Size = value; } } /// /// Gets the preferred size of this control given infinite space available. /// /// The size this control would prefer to be public SizeF GetPreferredSize() => GetPreferredSize(SizeF.PositiveInfinity); /// /// Gets the preferred size of this control given the specified . /// /// The available size to determine the preferred size /// The preferred size this control would like to be, which can be larger than the specified . public SizeF GetPreferredSize(SizeF availableSize) { // hack for now for dynamic layouts.. this should be moved to the Measure infrastructure when implemented.. InternalEnsureLayout(); return Handler.GetPreferredSize(availableSize); } internal virtual void InternalEnsureLayout() { } /// /// Gets a value indicating this control currently has mouse capture /// /// /// Mouse capture can happen during a handled MouseDown event until MouseUp, /// or it can be captured explicitly via . /// public bool IsMouseCaptured => Handler.IsMouseCaptured; /// /// Captures all mouse events to this control. /// /// /// This captures all mouse events until is called. /// /// Note that not all platforms will allow a mouse capture unless the mouse is currently down. /// /// true if the mouse was captured, false otherwise. public bool CaptureMouse() => Handler.CaptureMouse(); /// /// Releases the mouse capture after a call to . /// public void ReleaseMouseCapture() => Handler.ReleaseMouseCapture(); /// /// Gets or sets the width of the control size. /// public virtual int Width { get => Handler.Width; set => Handler.Width = value; } /// /// Gets or sets the height of the control size. /// public virtual int Height { get => Handler.Height; set => Handler.Height = value; } /// /// Gets or sets a value indicating whether this (or its children) are enabled and accept user input. /// /// /// Typically when a control is disabled, the user cannot do anything with the control or any of its children. /// Including for example, selecting text in a text control. /// Certain controls can have a 'Read Only' mode, such as which allow the user to /// select text, but not change its contents. /// /// true if enabled; otherwise, false. [sc.DefaultValue(true)] public virtual bool Enabled { get => Handler.Enabled; set => Handler.Enabled = value; } /// /// Gets or sets a value indicating whether this is visible to the user. /// /// /// When the visibility of a control is set to false, it will not occupy space in the layout. /// /// true if visible; otherwise, false. [sc.DefaultValue(true)] public virtual bool Visible { get { return Handler.Visible; } set { Handler.Visible = value; } } /// /// Gets the container which this control has been added to, if any /// /// The parent control, or null if there is no parent public new Container Parent { get { return base.Parent as Container; } } /// /// Gets or sets the logical parent, which excludes any visual structure of custom containers. /// /// The logical parent. internal Container InternalLogicalParent { get { return base.Parent as Container; } set { base.Parent = value; } } static readonly object VisualParent_Key = new object(); /// /// Gets the visual container of this control, if any. /// /// /// Some containers may use other Eto controls to layout its children, such as the . /// This will return the parent control that visually contains this control as opposed to /// which will return the logical parent. /// /// The visual parent of this control. public Container VisualParent { get { return Properties.Get(VisualParent_Key); } internal set { var old = VisualParent; if (Properties.TrySet(VisualParent_Key, value)) { Handler.SetParent(old, value); } } } /// /// Finds a control in the parent hierarchy with the specified type and if specified /// /// The parent if found, or null if not found. /// The type of control to find. /// Identifier of the parent control to find, or null to find by type only. public new Container FindParent(Type type, string id = null) { var control = Parent; while (control != null) { if ((type == null || type.IsInstanceOfType(control)) && (string.IsNullOrEmpty(id) || control.ID == id)) { return control; } control = control.Parent; } return null; } /// /// Finds a control in the parent hierarchy with the specified /// /// The parent if found, or null if not found. /// Identifier of the parent control to find. public new Container FindParent(string id) => FindParent(null, id); /// /// Detaches the control by removing it from its parent /// /// /// This is essentially a shortcut to myControl.Parent.Remove(myControl); /// public void Detach() { VisualParent?.Remove(this); Parent?.Remove(this); } static readonly object IsAttached_Key = new object(); /// /// Gets a value indicating this control has been attached to a native container /// /// public bool IsAttached { get => Properties.Get(IsAttached_Key); private set => Properties.Set(IsAttached_Key, value); } /// /// Attaches the control for direct use in a native application /// /// /// Use this to use a control directly in a native application. Note that the native application must be running /// the same framework as the current platform. E.g. a WinForms application can use an Eto.Forms control /// when using the Eto.WinForms platform. /// /// This prepares the control by firing the , , etc. events. /// public void AttachNative() { if (VisualParent != null) throw new InvalidOperationException("You can only attach a parentless control"); if (IsAttached) return; IsAttached = true; using (Platform.Context) { OnPreLoad(EventArgs.Empty); OnLoad(EventArgs.Empty); Application.Instance.AsyncInvoke(PostAttach); } } void PostAttach() { // if the control is disposed before we get here Handler will be null, so omit calling OnLoadComplete if (!IsDisposed && Handler != null && Loaded) RaiseLoadComplete(EventArgs.Empty); } /// /// Raises LoadComplete unless it has already been raised since the control was loaded. /// /// Event arguments /// Raise it even if it has already been raised, e.g. when a loaded window is shown again. internal void RaiseLoadComplete(EventArgs e, bool always = false) { if (IsLoadComplete && !always) return; IsLoadComplete = true; OnLoadComplete(e); } /// /// Detaches the control when it is used in a native application, when you want to reuse the control. /// /// /// This should only be called after has been called, which is usually done by calling /// to ToNative(true). /// public void DetachNative() { if (!IsAttached) return; IsAttached = false; using (Platform.Context) { OnUnLoad(EventArgs.Empty); } } internal void TriggerPreLoad(EventArgs e) { using (Platform.Context) OnPreLoad(e); } internal void TriggerLoad(EventArgs e) { using (Platform.Context) OnLoad(e); } internal void TriggerLoadComplete(EventArgs e) { using (Platform.Context) RaiseLoadComplete(e); } internal void TriggerUnLoad(EventArgs e) { using (Platform.Context) OnUnLoad(e); } internal void TriggerStyleChanged(EventArgs e) { using (Platform.Context) OnStyleChanged(e); } /// /// Gets or sets the color for the background of the control /// /// /// Note that on some platforms (e.g. Mac), setting the background color of a control can change the performance /// characteristics of the control and its children, since it must enable layers to do so. /// /// The color of the background. public virtual Color BackgroundColor { get { return Handler.BackgroundColor; } set { Handler.BackgroundColor = value; } } /// /// Gets a value indicating whether this instance has the keyboard input focus. /// /// true if this instance has focus; otherwise, false. public virtual bool HasFocus => Handler.HasFocus; /// /// Attempts to set the keyboard input focus to this control, or the first child that accepts focus. /// For Windows, this will bring it to front and activate it. /// public virtual void Focus() => Handler.Focus(); static readonly object SuspendCount_Key = new object(); int SuspendCount { get { return Properties.Get(SuspendCount_Key); } set { Properties.Set(SuspendCount_Key, value); } } /// /// Gets a value indicating whether the layout of child controls is suspended. /// /// /// /// true if this instance is suspended; otherwise, false. public bool IsSuspended => SuspendCount > 0; /// /// Suspends the layout of child controls /// /// /// This can be used to optimize some platforms while adding, removing, or changing many child controls at once. /// It disables the calculation of control positioning until is called. /// Each call to SuspendLayout() must be balanced with a call to . /// public virtual void SuspendLayout() { SuspendCount++; Handler.SuspendLayout(); } /// /// Resumes the layout after it has been suspended, and performs a layout /// /// /// This can be used to optimize some platforms while adding, removing, or changing many child controls at once. /// Each call to ResumeLayout() must be balanced with a call to before it. /// public virtual void ResumeLayout() { var count = SuspendCount; if (count == 0) throw new InvalidOperationException("Control is not suspended. You must balance calls to Resume() with Suspend()"); SuspendCount = --count; Handler.ResumeLayout(); } /// /// Gets the window this control is contained in /// /// The parent window, or null if it is not currently on a window public Window ParentWindow { get { Control c = this; while (c != null) { var window = c as Window; if (window != null) return window; c = c.VisualParent; } return Handler.GetNativeParentWindow(); } } /// /// Gets the supported platform commands that can be used to hook up system functions to user defined logic /// /// /// This lists all available commands that can be mapped using the method /// of the control. /// /// The supported platform commands. /// public IEnumerable SupportedPlatformCommands => Handler.SupportedPlatformCommands; /// /// Specifies a command to execute for a platform-specific command /// /// /// Some platforms have specific system-defined commands that can be associated with a control. /// For example, the Mac platform's cut/copy/paste functionality is defined by the system, and if you want to /// hook into it, you can use this to map it to your own defined logic. /// The valid values of the parameter are defined by each platform, and a list can be /// retrieved using /// /// /// This example shows how to extend a control with cut/copy/paste for the mac platform: /// /// var drawable = new Drawable(); /// if (drawable.Generator.IsMac) /// { /// drawable.MapPlatformCommand("cut", new MyCutCommand()); /// drawable.MapPlatformCommand("copy", new MyCopyCommand()); /// drawable.MapPlatformCommand("paste", new MyPasteCommand()); /// } /// /// /// System command /// Command to execute, or null to restore to the default behavior /// public void MapPlatformCommand(string systemCommand, Command command) => Handler.MapPlatformCommand(systemCommand, command); /// /// Converts a point from screen space to control space. /// /// The point in control space /// Point in screen space public PointF PointFromScreen(PointF point) => Handler.PointFromScreen(point); /// /// Converts a point from control space to screen space /// /// The point in screen space /// Point in control space public PointF PointToScreen(PointF point) => Handler.PointToScreen(point); /// /// Converts a rectangle from control space to screen space /// /// The rectangle in screen space /// Rectangle in control space public RectangleF RectangleToScreen(RectangleF rect) => new RectangleF(PointToScreen(rect.Location), PointToScreen(rect.EndLocation)); /// /// Converts a rectangle from screen space to control space. /// /// The rectangle in control space /// Rectangle in screen space public RectangleF RectangleFromScreen(RectangleF rect) => new RectangleF(PointFromScreen(rect.Location), PointFromScreen(rect.EndLocation)); /// /// Gets the bounding rectangle of this control relative to its container /// /// The bounding rectangle of the control public Rectangle Bounds => new Rectangle(Location, Size); /// /// Gets the location of the control as positioned by the container /// /// /// A control's location is set by the container. /// This can be used to determine where the control is for overlaying floating windows, menus, etc. /// /// The current location of the control public Point Location => Handler.Location; /// /// Gets or sets the type of cursor to use when the mouse is hovering over the control /// /// The mouse cursor public virtual Cursor Cursor { get { return Handler.Cursor; } set { Handler.Cursor = value; } } /// /// Gets or sets the tool tip to show when the mouse is hovered over the control /// /// The tool tip. public virtual string ToolTip { get { return Handler.ToolTip; } set { Handler.ToolTip = value; } } /// /// Gets or sets the tab index order for this control within its container. /// /// /// This sets the order when using the tab key to cycle through controls /// /// Note that some platforms (Gtk and WinForms) may not support setting the context of the tab order to StackLayout /// or DynamicLayout containers and may not behave exactly as expected. Use the /// flag to determine if it is supported. /// /// The index of the control in the tab order. [sc.DefaultValue(int.MaxValue)] public virtual int TabIndex { get { return Handler.TabIndex; } set { Handler.TabIndex = value; } } /// /// Gets or sets a value indicating whether the user can get to this control using the tab key. /// /// /// When false, the control is skipped when cycling through controls with the tab key, but can still be /// focused by clicking on it or by calling . /// This is useful for composite controls where only part of the control should be in the tab order, such as /// the spinner of a or . /// /// The tab key only cycles through the controls within a window, so this has no effect for a . /// /// Note that on Gtk this maps directly to whether the underlying widget can be focused, so it also prevents the /// control from being focused by clicking on it, and controls that never accept focus (such as a ) /// will report false. On iOS and Android this has no effect. /// /// true to include the control in the tab order (the default); false to skip it. [sc.DefaultValue(true)] public virtual bool TabStop { get { return Handler.TabStop; } set { Handler.TabStop = value; } } /// /// Gets or sets a value indicating whether this control can serve as drop target. /// public virtual bool AllowDrop { get { return Handler.AllowDrop; } set { Handler.AllowDrop = value; } } /// /// Starts drag operation using this control as drag source. /// /// /// This method can be blocking on some platforms (Wpf, WinForms), and non-blocking on others (Mac, Gtk). /// Use the event to determine when the drag operation is completed and get its resulting DragEffects. /// /// Drag data. /// Allowed action. public virtual void DoDragDrop(DataObject data, DragEffects allowedEffects) { Handler.DoDragDrop(data, allowedEffects, null, PointF.Empty); } /// /// Starts drag operation using this control as drag source. /// /// /// This method can be blocking on some platforms (Wpf, WinForms), and non-blocking on others (Mac, Gtk). /// Use the event to determine when the drag operation is completed and get its resulting DragEffects. /// /// Drag data. /// Allowed effects. /// Custom drag image /// Offset of the cursor to the drag image public virtual void DoDragDrop(DataObject data, DragEffects allowedEffects, Image image, PointF cursorOffset) { Handler.DoDragDrop(data, allowedEffects, image, cursorOffset); } /// /// Handles when the is changed. /// /// /// This applies the cascading styles to the control and any of its children. /// protected override void OnStyleChanged(EventArgs e) { base.OnStyleChanged(e); // already loaded, re-apply styles as they have changed if (Loaded) OnApplyCascadingStyles(); } /// /// Triggers the StyleChanged event and re-applies the styles to this control and its children. /// public void TriggerStyleChanged() => OnStyleChanged(EventArgs.Empty); /// /// Called when cascading styles should be applied to this control. /// /// /// You don't typically have to call this directly, but override it to apply styles to any child item(s) /// that may need styling at the same time. /// /// This is automatically done for any Container based control and its child controls. /// protected virtual void OnApplyCascadingStyles() => ApplyStyles(this, Style); /// /// Applies the styles to the specified up the parent chain. /// /// /// This traverses up the parent chain to apply any cascading styles defined in parent container objects. /// /// Call this method on any child widget of a control. /// /// Widget to style. /// Style of the widget to apply. protected virtual void ApplyStyles(object widget, string style) => Parent?.ApplyStyles(widget, Style); /// /// Shows a print dialog to print the specified control /// public void Print() { using (var doc = new PrintDocument(this)) { var dlg = new PrintDialog(); dlg.ShowDialog(this, doc); } } /// /// Gets or sets the context menu that appears when the user right-clicks on the control. /// /// /// On some platforms and controls, such as macOS, the context menu can have additional items added by the system. /// /// Also the menu may appear when pressing different keys, such as a control-click on macOS, or when /// pressing the menu key on Windows keyboards. /// /// There is also some other semantic differences of using this vs. showing a context menu manually, such as on Windows, /// right clicking on a TextBox or TextArea will keep the selection visible, whereas this would not be the case if you showed /// the context menu manually. /// public ContextMenu ContextMenu { get { return Handler.ContextMenu; } set { Handler.ContextMenu = value; } } /// /// Handles the disposal of this control /// /// True if the caller called manually, false if being called from a finalizer protected override void Dispose(bool disposing) { if (disposing) { Unbind(); Detach(); DetachNative(); } base.Dispose(disposing); } /// /// Converts a string to a label control implicitly. /// /// /// This provides an easy way to add labels to your layout through code, without having to create instances. /// /// Text to convert to a Label control. public static implicit operator Control(string labelText) { return new Label { Text = labelText }; } /// /// Converts an to a control implicitly. /// /// /// This provides an easy way to add images to your layout through code, without having to create instances manually. /// /// Image to convert to an ImageView control. public static implicit operator Control(Image image) { return new ImageView { Image = image }; } #region Callback static readonly object callback = new Callback(); /// /// Gets an instance of an object used to perform callbacks to the widget from handler implementations. /// /// The callback instance to use for this widget protected override object GetCallback() { return callback; } /// /// Callback interface for instances of /// public new interface ICallback : Widget.ICallback { /// /// Raises the key down event. /// void OnKeyDown(Control widget, KeyEventArgs e); /// /// Raises the key up event. /// void OnKeyUp(Control widget, KeyEventArgs e); /// /// Raises the mouse down event. /// void OnMouseDown(Control widget, MouseEventArgs e); /// /// Raises the mouse up event. /// void OnMouseUp(Control widget, MouseEventArgs e); /// /// Raises the mouse move event. /// void OnMouseMove(Control widget, MouseEventArgs e); /// /// Raises the mouse leave event. /// void OnMouseLeave(Control widget, MouseEventArgs e); /// /// Raises the mouse enter event. /// void OnMouseEnter(Control widget, MouseEventArgs e); /// /// Raises the text input event. /// void OnTextInput(Control widget, TextInputEventArgs e); /// /// Raises the size changed event. /// void OnSizeChanged(Control widget, EventArgs e); /// /// Raises the mouse double click event. /// void OnMouseDoubleClick(Control widget, MouseEventArgs e); /// /// Raises the mouse wheel event. /// void OnMouseWheel(Control widget, MouseEventArgs e); /// /// Raises the got focus event. /// void OnGotFocus(Control widget, EventArgs e); /// /// Raises the lost focus event. /// void OnLostFocus(Control widget, EventArgs e); /// /// Raises the shown event. /// void OnShown(Control widget, EventArgs e); /// /// Raises the DragDrop event. /// void OnDragDrop(Control widget, DragEventArgs e); /// /// Raises the DragOver event. /// void OnDragOver(Control widget, DragEventArgs e); /// /// Raises the DragEnter event. /// void OnDragEnter(Control widget, DragEventArgs e); /// /// Raises the DragLeave event. /// void OnDragLeave(Control widget, DragEventArgs e); /// /// Raises the DragEnd event. /// void OnDragEnd(Control widget, DragEventArgs e); /// /// Raises the EnabledChanged event. /// void OnEnabledChanged(Control widget, EventArgs e); /// /// Raises the ThemeChanged event. /// void OnThemeChanged(Control widget, EventArgs e); } /// /// Callback methods for handlers of /// protected class Callback : ICallback { /// /// Raises the key down event. /// public void OnKeyDown(Control widget, KeyEventArgs e) { using (widget.Platform.Context) widget.OnKeyDown(e); } /// /// Raises the key up event. /// public void OnKeyUp(Control widget, KeyEventArgs e) { using (widget.Platform.Context) widget.OnKeyUp(e); } /// /// Raises the mouse down event. /// public void OnMouseDown(Control widget, MouseEventArgs e) { using (widget.Platform.Context) widget.OnMouseDown(e); } /// /// Raises the mouse up event. /// public void OnMouseUp(Control widget, MouseEventArgs e) { using (widget.Platform.Context) widget.OnMouseUp(e); } /// /// Raises the mouse move event. /// public void OnMouseMove(Control widget, MouseEventArgs e) { using (widget.Platform.Context) widget.OnMouseMove(e); } /// /// Raises the mouse leave event. /// public void OnMouseLeave(Control widget, MouseEventArgs e) { using (widget.Platform.Context) widget.OnMouseLeave(e); } /// /// Raises the mouse enter event. /// public void OnMouseEnter(Control widget, MouseEventArgs e) { using (widget.Platform.Context) widget.OnMouseEnter(e); } /// /// Raises the text input event. /// public void OnTextInput(Control widget, TextInputEventArgs e) { using (widget.Platform.Context) widget.OnTextInput(e); } /// /// Raises the size changed event. /// public void OnSizeChanged(Control widget, EventArgs e) { using (widget.Platform.Context) widget.OnSizeChanged(e); } /// /// Raises the mouse double click event. /// public void OnMouseDoubleClick(Control widget, MouseEventArgs e) { using (widget.Platform.Context) widget.OnMouseDoubleClick(e); } /// /// Raises the mouse wheel event. /// public void OnMouseWheel(Control widget, MouseEventArgs e) { using (widget.Platform.Context) widget.OnMouseWheel(e); } /// /// Raises the got focus event. /// public void OnGotFocus(Control widget, EventArgs e) { using (widget.Platform.Context) widget.OnGotFocus(e); } /// /// Raises the lost focus event. /// public void OnLostFocus(Control widget, EventArgs e) { using (widget.Platform.Context) widget.OnLostFocus(e); } /// /// Raises the shown event. /// public void OnShown(Control widget, EventArgs e) { using (widget.Platform.Context) widget.OnShown(e); } /// /// Raises the DragDrop event. /// public void OnDragDrop(Control widget, DragEventArgs e) { using (widget.Platform.Context) widget.OnDragDrop(e); } /// /// Raises the DragOver event. /// public void OnDragOver(Control widget, DragEventArgs e) { using (widget.Platform.Context) widget.OnDragOver(e); } /// /// Raises the DragEnter event. /// public void OnDragEnter(Control widget, DragEventArgs e) { using (widget.Platform.Context) widget.OnDragEnter(e); } /// /// Raises the DragLeave event. /// public void OnDragLeave(Control widget, DragEventArgs e) { using (widget.Platform.Context) widget.OnDragLeave(e); } /// /// Raises the DragEnd event. /// public void OnDragEnd(Control widget, DragEventArgs e) { using (widget.Platform.Context) widget.OnDragEnd(e); } /// /// Raises the EnabledChanged event. /// public void OnEnabledChanged(Control widget, EventArgs e) { using (widget.Platform.Context) widget.OnEnabledChanged(e); } /// /// Raises the ThemeChanged event. /// public void OnThemeChanged(Control widget, EventArgs e) { using (widget.Platform.Context) widget.OnThemeChanged(e); } } #endregion #region Handler /// /// Handler interface for /// /// (c) 2014 by Curtis Wensley /// See LICENSE for full terms public new interface IHandler : Widget.IHandler, IContextMenuHost { /// /// Gets or sets the color for the background of the control /// /// /// Note that on some platforms (e.g. Mac), setting the background color of a control can change the performance /// characteristics of the control and its children, since it must enable layers to do so. /// /// The color of the background. Color BackgroundColor { get; set; } /// /// Gets or sets the size of the control. Use -1 to specify auto sizing for either the width and/or height. /// /// /// Setting the size of controls is entirely optional as most controls will size themselves appropriately. /// When specifying a size, it will be used as the desired size of the control. The container will reposition /// and resize the control depending on the available size. /// /// For a , it is preferred to set the instead, as various /// platforms have different sizes of window decorations, toolbars, etc. /// /// The current size of the control Size Size { get; set; } /// /// Gets or sets the width of the control size. /// int Width { get; set; } /// /// Gets or sets the height of the control size. /// int Height { get; set; } /// /// Gets or sets a value indicating whether this is enabled and accepts user input. /// /// /// Typically when a control is disabled, the user cannot do anything with the control (including for example, selecting /// text in a text control). Certain controls can have a 'Read Only' mode, such as which /// allows the user to select text, but not change its contents. /// /// true if enabled; otherwise, false. bool Enabled { get; set; } /// /// Queues a repaint of the entire control on the screen /// /// /// This is only useful when the control is visible. /// /// True to invalidate all children, false to only invalidate the container void Invalidate(bool invalidateChildren); /// /// Queues a repaint of the specified of the control /// /// /// This is only useful when the control is visible. /// /// Rectangle to repaint /// True to invalidate all children, false to only invalidate the container void Invalidate(Rectangle rect, bool invalidateChildren); /// /// Suspends the layout of child controls /// /// /// This can be used to optimize some platforms while adding, removing, or changing many child controls at once. /// It disables the calculation of control positioning until is called. /// Each call to SuspendLayout() must be balanced with a call to . /// void SuspendLayout(); /// /// Resumes the layout after it has been suspended, and performs a layout /// /// /// This can be used to optimize some platforms while adding, removing, or changing many child controls at once. /// Each call to ResumeLayout() must be balanced with a call to before it. /// void ResumeLayout(); /// /// Attempts to set the keyboard input focus to this control, or the first child that accepts focus /// void Focus(); /// /// Gets a value indicating whether this instance has the keyboard input focus. /// /// true if this instance has focus; otherwise, false. bool HasFocus { get; } /// /// Gets or sets a value indicating whether this is visible to the user. /// /// /// When the visibility of a control is set to false, it will still occupy space in the layout, but not be shown. /// The only exception is for controls like the , which will hide a pane if the visibility /// of one of the panels is changed. /// /// true if visible; otherwise, false. bool Visible { get; set; } /// /// Called before the control is loaded on a form /// /// Event arguments /// /// /// void OnPreLoad(EventArgs e); /// /// Called when the control is loaded on a form /// /// Event arguments /// /// /// void OnLoad(EventArgs e); /// /// Called after all other controls have been loaded /// /// Event arguments /// /// /// void OnLoadComplete(EventArgs e); /// /// Called when the control is unloaded, which is when it is not currently on a displayed window /// /// Event arguments /// /// /// void OnUnLoad(EventArgs e); /// /// Called when the parent of the control has been set /// /// Old parent for the control, or null if the control is added /// New parent for the control, or null if the parent was removed void SetParent(Container oldParent, Container newParent); /// /// Gets the supported platform commands that can be used to hook up system functions to user defined logic /// /// /// This lists all available commands that can be mapped using the method /// of the control. /// /// The supported platform commands. /// IEnumerable SupportedPlatformCommands { get; } /// /// Specifies a command to execute for a platform-specific command /// /// /// Some platforms have specific system-defined commands that can be associated with a control. /// For example, the Mac platform's cut/copy/paste functionality is defined by the system, and if you want to /// hook into it, you can use this to map it to your own defined logic. /// The valid values of the parameter are defined by each platform, and a list can be /// retrieved using /// /// /// This example shows how to extend a control with cut/copy/paste for the mac platform: /// /// var drawable = new Drawable(); /// if (drawable.Generator.IsMac) /// { /// drawable.MapPlatformCommand("cut", new MyCutCommand()); /// drawable.MapPlatformCommand("copy", new MyCopyCommand()); /// drawable.MapPlatformCommand("paste", new MyPasteCommand()); /// } /// /// /// System command. /// Command to execute, or null to restore to the default behavior /// void MapPlatformCommand(string systemCommand, Command command); /// /// Converts a point from screen space to control space. /// /// The point in control space /// Point in screen space PointF PointFromScreen(PointF point); /// /// Converts a point from control space to screen space /// /// The point in screen space /// Point in control space PointF PointToScreen(PointF point); /// /// Gets the location of the control as positioned by the container /// /// /// A control's location is set by the container. /// This can be used to determine where the control is for overlaying floating windows, menus, etc. /// /// The current location of the control Point Location { get; } /// /// Gets or sets the tool tip to show when the mouse is hovered over the control /// /// The tool tip. string ToolTip { get; set; } /// /// Gets or sets the type of cursor to use when the mouse is hovering over the control /// /// The mouse cursor Cursor Cursor { get; set; } /// /// Gets or sets the tab index order for this control within its container. /// /// /// This sets the order when using the tab key to cycle through controls /// /// Note that some platforms (Gtk and WinForms) may not support setting the context of the tab order to StackLayout /// or DynamicLayout containers and may not behave exactly as expected. Use the /// flag to determine if it is supported. /// /// The index of the control in the tab order. int TabIndex { get; set; } /// /// Gets or sets a value indicating whether the user can get to this control using the tab key. /// /// /// When false, the control is skipped when cycling through controls with the tab key, but can still be /// focused by clicking on it or by calling . /// /// Note that on Gtk this also prevents the control from being focused by clicking on it, and on iOS and Android /// this has no effect. /// /// true to include the control in the tab order (the default); false to skip it. bool TabStop { get; set; } /// /// Gets an enumeration of controls that are in the visual tree. /// /// /// This is used to specify which controls are contained by this instance that are part of the visual tree. /// This should include all controls including non-logical Eto controls used for layout. /// /// The visual controls. IEnumerable VisualControls { get; } /// /// Gets or sets a value indicating whether this control can serve as drop target. /// bool AllowDrop { get; set; } /// /// Starts drag operation using this control as drag source. /// /// Drag data. /// Allowed effects. /// Custom drag image /// Offset of the cursor to the drag image void DoDragDrop(DataObject data, DragEffects allowedEffects, Image image, PointF cursorOffset); /// /// Gets a parent window wrapper around the native window /// /// The parent window. Window GetNativeParentWindow(); /// /// Gets the preferred size of this control given the specified . /// /// The available size to determine the preferred size /// The preferred size this control would like to be, which can be larger than the specified . SizeF GetPreferredSize(SizeF availableSize); /// /// Updates the layout of this control if necessary. /// /// /// This will ensure the control has had all of its layout applied so you can use its position and size right after this call. /// Most platforms (except WinForms) use a deferred layout system so that after adding your control to the form dynamically it won't /// get laid out until the next idle loop. /// This is useful when you need to know the dimensions of the control immediately. /// void UpdateLayout(); /// /// Gets a value indicating this control currently has mouse capture /// /// /// Mouse capture can happen during a handled MouseDown event until MouseUp, /// or it can be captured explicitly via . /// bool IsMouseCaptured { get; } /// /// Captures all mouse events to this control. /// /// /// This captures all mouse events until is called. /// /// Note that not all platforms will allow a mouse capture unless the mouse is currently down. /// /// true if the mouse was captured, false otherwise. bool CaptureMouse(); /// /// Releases the mouse capture after a call to . /// void ReleaseMouseCapture(); /// /// Adds a gesture to the control. /// /// Gesture to add. void AddGesture(Gesture item); /// /// Removes all gestures from the control. /// void ClearGestures(); /// /// Removes a gesture from the control. /// /// Gesture to remove. void RemoveGesture(Gesture item); } #endregion }