// Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // Copyright (c) 2004 Novell, Inc. // // Authors: // Peter Bartok pbartok@novell.com // // Based on work by: // Aleksey Ryabchuk ryabchuk@yahoo.com // Alexandre Pigolkine pigolkine@gmx.de // Dennis Hayes dennish@raytek.com // Jaak Simm jaaksimm@firm.ee // John Sohn jsohn@columbus.rr.com // // $Revision: 1.1 $ // $Modtime: $ // $Log: Control.cs,v $ // Revision 1.1 2004/07/09 05:21:25 pbartok // - Initial check-in // // // NOT COMPLETE using System; using System.Drawing; using System.ComponentModel; using System.Collections; using System.Diagnostics; using System.Threading; using System.Runtime.InteropServices; namespace System.Windows.Forms { public class Control : Component, ISynchronizeInvoke, IWin32Window { #region Local Variables // Basic internal Rectangle bounds; // bounding rectangle for control internal object creator_thread; // thread that created the control internal ControlNativeWindow window; // object for native window handle internal string name; // for object naming // State internal bool has_focus; // true if control has focus internal bool is_visible; // true if control is visible internal bool is_enabled; // true if control is enabled (usable/not grayed out) internal int tab_index; // position in tab order of siblings internal bool is_disposed; // has the window already been disposed? internal Size window_size; // size of the window (including decorations) internal Size client_size; // size of the client area (window excluding decorations) internal ControlStyles control_style; // win32-specific, style bits for control // Visuals internal Color foreground_color; // foreground color for control internal Color background_color; // background color for control internal Image background_image; // background image for control internal Font font; // font for control internal string text; // window/title text for control // to be categorized... static internal Hashtable controls; // All of the applications controls, in a flat list internal ControlCollection child_controls; // our children internal Control parent; // our parent control internal int num_of_children; // number of children the control has internal Control[] children; // our children internal AccessibleObject accessibility_object; // object that contains accessibility information about our control internal AnchorStyles anchor_style; // TODO internal BindingContext binding_context; // TODO internal RightToLeft right_to_left; // drawing direction for control #endregion // Local Variables #region Private Classes // This helper class allows us to dispatch messages to Control.WndProc internal class ControlNativeWindow : NativeWindow { private Control control; public ControlNativeWindow(Control control) : base() { this.control=control; } protected override void WndProc(ref Message m) { control.WndProc(ref m); } } #endregion #region Public Classes public class ControlCollection : IList, ICollection, ICloneable, IEnumerable { private class Enumerator : IEnumerator { private Control owner; private int current; public Enumerator(Control owner) { this.owner=owner; this.current=-1; } public bool MoveNext() { current++; if (current>=owner.num_of_children) { return false; } return true; } public void Reset() { current=-1; } public object Current { get { if (current>=0 && current=owner.num_of_children) { throw new ArgumentOutOfRangeException(); } return owner.children[index]; } } #endregion // ControlCollection Public Instance Properties #region ControlCollection Public Instance Methods public virtual void Add(Control value) { // Don't add it if we already have it for (int i=0; i0) { Array.Copy(owner.children, 0, dest, index, owner.num_of_children); } } public override bool Equals(object other) { if (other is ControlCollection && (((ControlCollection)other).owner==this.owner)) { return(true); } else { return(false); } } public int GetChildIndex(Control child) { return GetChildIndex(child, false); } public int GetChildIndex(Control child, bool throwException) { int index; index=IndexOf(child); if (index==-1 && throwException) { throw new ArgumentException("Not a child control", "child"); } return index; } public IEnumerator GetEnumerator() { return new ControlCollection.Enumerator(this.owner); } public override int GetHashCode() { return base.GetHashCode(); } public int IndexOf(Control control) { int index; for (index=0; indexowner.num_of_children) { Add(child); } else { for (int i=owner.num_of_children-1;i>new_index; i--) { owner.children[i+1]=owner.children[i]; } owner.children[new_index]=(Control)child; } } #endregion // ControlCollection Public Instance Methods #region ControlCollection Interface Methods #if nodef int IList.Add(Control value) { Add(value); } #endif int IList.Add(object value) { if (!(value is Control)) { throw new ArgumentException("Not of type Control", "value"); } Add((Control)value); // Assumes the element was added to the end of the list return owner.num_of_children; } void IList.Clear() { this.Clear(); } bool IList.Contains(object value) { if (!(value is Control)) { throw new ArgumentException("Not of type Control", "value"); } return this.Contains((Control)value); } int IList.IndexOf(object value) { if (!(value is Control)) { throw new ArgumentException("Not of type Control", "value"); } for (int i=0; iowner.num_of_children) { throw new ArgumentOutOfRangeException("index"); } for (int i=owner.num_of_children-1;i>index; i--) { owner.children[i+1]=owner.children[i]; } owner.children[index]=(Control)value; } void IList.Remove(object value) { if (!(value is Control)) { throw new ArgumentException("Not of type Control", "value"); } this.Remove((Control)value); } object IList.this [int index] { get { return owner.children[index]; } set { } } bool IList.IsFixedSize { get { return false; } } object ICollection.SyncRoot { get { return this; } } bool ICollection.IsSynchronized { get { return false; } } Object ICloneable.Clone() { ControlCollection clone = new ControlCollection(this.owner); return clone; } #endregion // ControlCollection Interface Methods class ControlComparer : IComparer { int IComparer.Compare(object x, object y) { int tab_index_x; int tab_index_y; tab_index_x=((Control)x).tab_index; tab_index_y=((Control)y).tab_index; if (tab_index_xtab_index_y) { return 1; } return 0; } } } #endregion // ControlCollection Class #region Public Constructors public Control() { creator_thread = Thread.CurrentThread; controls = new Hashtable(); child_controls = CreateControlsInstance(); bounds = new Rectangle(0, 0, DefaultSize.Width, DefaultSize.Height); window_size = new Size(DefaultSize.Width, DefaultSize.Height); client_size = new Size(DefaultSize.Width, DefaultSize.Height); is_visible = true; is_disposed = false; is_enabled = true; has_focus = false; parent = null; background_image = null; } public Control(Control parent, string text) : this() { Text=text; Parent=parent; } public Control(Control parent, string text, int left, int top, int width, int height) : this() { Parent=parent; Left=left; Top=top; Width=width; Height=height; Text=text; } public Control(string text) : this() { Text=text; } public Control(string text, int left, int top, int width, int height) : this() { Left=left; Top=top; Width=width; Height=height; Text=text; } #endregion // Public Constructors #region Public Static Properties public static Color DefaultBackColor { get { return XplatUI.Defaults.BackColor; } } public static Font DefaultFont { get { return XplatUI.Defaults.Font; } } public static Color DefaultForeColor { get { return XplatUI.Defaults.ForeColor; } } public static Keys ModifierKeys { get { return XplatUI.State.ModifierKeys; } } public static MouseButtons MouseButtons { get { return XplatUI.State.MouseButtons; } } public static Point MousePosition { get { return XplatUI.State.MousePosition; } } #endregion // Public Static Properties #region Public Instance Properties public AccessibleObject AccessibilityObject { get { if (accessibility_object==null) { accessibility_object=CreateAccessibilityInstance(); } return accessibility_object; } } public string AccessibleDefaultActionDescription { get { return AccessibilityObject.default_action; } set { AccessibilityObject.default_action=value; } } public string AccessibleDescription { get { return AccessibilityObject.description; } set { AccessibilityObject.description=value; } } public string AccessibleName { get { return AccessibilityObject.Name; } set { AccessibilityObject.Name=value; } } public AccessibleRole AccessibleRole { get { return AccessibilityObject.role; } set { AccessibilityObject.role=value; } } public virtual bool AllowDrop { get { return XplatUI.State.DropTarget; } set { XplatUI.State.DropTarget=value; } } public virtual AnchorStyles Anchor { get { return anchor_style; } set { anchor_style=value; } } public virtual Color BackColor { get { if (background_color.IsEmpty) { if (parent!=null) { return parent.BackColor; } return DefaultBackColor; } return background_color; } set { background_color=value; Refresh(); } } public virtual Image BackgroundImage { get { return background_image; } set { if (background_image!=value) { background_image=value; OnBackgroundImageChanged(EventArgs.Empty); } } } public virtual BindingContext BindingContext { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public int Bottom { get { return bounds.Y+bounds.Height; } } public Rectangle Bounds { get { return this.bounds; } set { SetBounds(value.Left, value.Top, value.Width, value.Height, BoundsSpecified.All); } } public bool CanFocus { get { throw new NotImplementedException(); } } public bool CanSelect { get { throw new NotImplementedException(); } } public bool Capture { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public bool CausesValidation { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public Rectangle ClientRectangle { get { return new Rectangle(0, 0, client_size.Width, client_size.Height); } } public Size ClientSize { get { return client_size; } set { throw new NotImplementedException(); } } public String CompanyName { get { return "Mono Project, Novell, Inc."; } } public bool ContainsFocus { get { throw new NotImplementedException(); } } #if notdef public virtual ContextMenu ContextMenu { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } #endif public ControlCollection Controls { get { return CreateControlsInstance(); } } public bool Created { get { throw new NotImplementedException(); } } #if notdef public virtual Cursor Cursor { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public ControlBidingsCollection DataBindings { get { throw new NotImplementedException(); } } #endif public virtual Rectangle DisplayRectangle { get { return ClientRectangle; } } public bool Disposing { get { throw new NotImplementedException(); } } public virtual DockStyle Dock { get { throw new NotImplementedException(); } set { throw new NotImplementedException(); } } public bool Enabled { get { return is_enabled; } set { throw new NotImplementedException(); } } public virtual bool Focused { get { return this.has_focus; } set { throw new NotImplementedException(); } } public virtual Font Font { get { if (font != null) { return font; } if (Parent != null && Parent.Font != null) { return Parent.Font; } return DefaultFont; } set { font=value; Refresh(); } } public virtual Color ForeColor { get { if (foreground_color.IsEmpty) { if (parent!=null) { return parent.ForeColor; } return DefaultForeColor; } return foreground_color; } set { foreground_color=value; Refresh(); } } public bool IsDisposed { get { return this.is_disposed; } } public bool IsHandleCreated { get { if ((window!=null) && (window.Handle!=IntPtr.Zero)) { return true; } return false; } } public string Name { get { return this.name; } set { this.name=value; } } public Control Parent { get { return this.parent; } set { if (parent!=value) { if (parent!=null) { parent.Controls.Remove(this); } parent=value; if (!parent.Controls.Contains(this)) { parent.Controls.Add(this); } XplatUI.SetParent(Handle, value.Handle); } } } public IntPtr Handle { // IWin32Window get { if (!IsHandleCreated) { CreateHandle(); } return window.Handle; } } public bool InvokeRequired { // ISynchronizeInvoke get { if (creator_thread!=Thread.CurrentThread) { return true; } return false; } } public bool Visible { get { return this.is_visible; } set { if (value!=is_visible) { is_visible=value; XplatUI.SetVisible(Handle, value); } } } public virtual string Text { get { return this.text; } set { if (text!=value) { text=value; XplatUI.Text(Handle, text); } } } public int Left { get { return this.bounds.X; } set { SetBounds(value, bounds.Y, bounds.Width, bounds.Height, BoundsSpecified.X); } } public int Top { get { return this.bounds.Y; } set { SetBounds(bounds.X, value, bounds.Width, bounds.Height, BoundsSpecified.Y); } } public int Width { get { return this.bounds.Width; } set { SetBounds(bounds.X, bounds.Y, value, bounds.Height, BoundsSpecified.Width); } } public int Height { get { return this.bounds.Height; } set { SetBounds(bounds.X, bounds.Y, bounds.Width, value, BoundsSpecified.Height); } } public Point Location { get { return new Point(bounds.X, bounds.Y); } set { SetBounds(value.X, value.Y, bounds.Width, bounds.Height, BoundsSpecified.Location); } } public Size Size { get { return new Size(Width, Height); } set { SetBounds(bounds.X, bounds.Y, value.Width, value.Height, BoundsSpecified.Size); } } #endregion // Public Instance Properties #region Protected Instance Properties protected virtual CreateParams CreateParams { get { CreateParams create_params = new CreateParams(); create_params.Caption = Text; create_params.X = Left; create_params.Y = Top; create_params.Width = Width; create_params.Height = Height; create_params.ClassName = XplatUI.DefaultClassName; create_params.ClassStyle = 0; create_params.ExStyle = 0; create_params.Param = 0; if (parent!=null) { create_params.Parent = parent.Handle; } create_params.Style = (int)WindowStyles.WS_OVERLAPPED; if (is_visible) { create_params.Style |= (int)WindowStyles.WS_VISIBLE; } return create_params; } } protected virtual ImeMode DefaultImeMode { get { return ImeMode.Inherit; } } protected virtual Size DefaultSize { get { return new Size(100, 23); } } #endregion // Protected Instance Properties #region Public Instance Methods public bool Contains(Control ctl) { Control current; current=ctl; while (current!=null) { if (current==ctl) { return true; } current=current.parent; } return false; } public void CreateControl() { Control child; CreateHandle(); for (int i=0; i