aboutsummaryrefslogtreecommitdiff
path: root/source/ShiftUI/Widgets/ContainerControl.cs
diff options
context:
space:
mode:
Diffstat (limited to 'source/ShiftUI/Widgets/ContainerControl.cs')
-rw-r--r--source/ShiftUI/Widgets/ContainerControl.cs850
1 files changed, 850 insertions, 0 deletions
diff --git a/source/ShiftUI/Widgets/ContainerControl.cs b/source/ShiftUI/Widgets/ContainerControl.cs
new file mode 100644
index 0000000..5d02f46
--- /dev/null
+++ b/source/ShiftUI/Widgets/ContainerControl.cs
@@ -0,0 +1,850 @@
+// 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 [email protected]
+//
+//
+
+
+using System.Collections;
+using System.ComponentModel;
+using System.ComponentModel.Design;
+using System.Drawing;
+using System.Runtime.InteropServices;
+using System;
+
+namespace ShiftUI {
+ [ClassInterface (ClassInterfaceType.AutoDispatch)]
+ [ComVisible (true)]
+ public class ContainerWidget : ScrollableWidget, IContainerWidget {
+ private Widget active_Widget;
+ private Widget unvalidated_Widget;
+ private ArrayList pending_validation_chain;
+
+ // This is an internal hack that allows some container Widgets
+ // to not auto select their child when they are activated
+ internal bool auto_select_child = true;
+ private SizeF auto_scale_dimensions;
+ private AutoScaleMode auto_scale_mode;
+ private bool auto_scale_mode_set;
+ private bool auto_scale_pending;
+ private bool is_auto_scaling;
+
+ internal bool validation_failed; //track whether validation was cancelled by a validating Widget
+
+ #region Public Constructors
+ public ContainerWidget() {
+ active_Widget = null;
+ unvalidated_Widget = null;
+ WidgetRemoved += new WidgetEventHandler(OnWidgetRemoved);
+ auto_scale_dimensions = SizeF.Empty;
+ auto_scale_mode = AutoScaleMode.Inherit;
+ }
+ #endregion // Public Constructors
+
+ #region Public Instance Properties
+ [Browsable (false)]
+ //[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public Widget ActiveWidget {
+ get {
+ return active_Widget;
+ }
+
+ set {
+ if (value==null || (active_Widget == value && active_Widget.Focused)) {
+ return;
+ }
+
+ if (!Contains(value)) {
+ throw new ArgumentException("Cannot activate invisible or disabled Widget.");
+ }
+
+ // Fire the enter and leave events if possible
+ Form form = FindForm ();
+ Widget active = GetMostDeeplyNestedActiveWidget (form == null ? this : form);
+ Widget common_ancestor = GetCommonContainer (active, value);
+ ArrayList chain = new ArrayList ();
+ ArrayList validation_chain = new ArrayList ();
+ Widget walk = active;
+
+ // we split this up into three steps:
+ // 1. walk up the tree (if we need to) to our root, firing leave events.
+ // 2. validate.
+ // 3. walk down the tree (if we need to), firing enter events.
+
+ // "our root" is either the common ancestor of the current active
+ // Widget and the new active Widget, or the current active Widget,
+ // or the new active Widget. That is, it's either one of these three
+ // configurations:
+
+ // (1) root (2) new (3) current
+ // / \ / \ / \
+ // ... ... ... ... ... ...
+ // / \ / \
+ // current new current new
+
+
+ // note (3) doesn't require any upward walking, and no leave events are generated.
+ // (2) doesn't require any downward walking, and no enter events are generated.
+
+ // as we walk up the tree, we generate a list of all Widgets which cause
+ // validation. After firing the leave events, we invoke (in order starting from
+ // the most deeply nested) their Validating event. If one sets CancelEventArgs.Cancel
+ // to true, we ignore the Widget the user wanted to set ActiveWidget to, and use
+ // the Validating Widget instead.
+
+ bool fire_enter = true;
+ Widget root = common_ancestor;
+
+ active_Widget = value;
+
+ // Generate the leave messages
+ while (walk != common_ancestor && walk != null) {
+ if (walk == value) {
+ root = value;
+ fire_enter = false;
+ break;
+ }
+ walk.FireLeave ();
+ /* clear our idea of the active Widget as we go back up */
+ if (walk is ContainerWidget)
+ ((ContainerWidget)walk).active_Widget = null;
+
+ if (walk.CausesValidation)
+ validation_chain.Add (walk);
+
+ walk = walk.Parent;
+ }
+
+ // Validation can be postponed due to all the Widgets
+ // in the enter chain not causing validation. If we don't have any
+ // enter chain, it means that the selected Widget is a child and then
+ // we need to validate the Widgets anyway
+ bool postpone_validation;
+ Widget topmost_under_root = null; // topmost under root, in the *enter* chain
+ if (value == root)
+ postpone_validation = false;
+ else {
+ postpone_validation = true;
+ walk = value;
+ while (walk != root && walk != null) {
+ if (walk.CausesValidation)
+ postpone_validation = false;
+
+ topmost_under_root = walk;
+ walk = walk.Parent;
+ }
+ }
+
+ Widget failed_validation_Widget = PerformValidation (form == null ? this : form, postpone_validation,
+ validation_chain, topmost_under_root);
+ if (failed_validation_Widget != null) {
+ active_Widget = value = failed_validation_Widget;
+ fire_enter = true;
+ }
+
+ if (fire_enter) {
+ walk = value;
+ while (walk != root && walk != null) {
+ chain.Add (walk);
+ walk = walk.Parent;
+ }
+
+ if (root != null && walk == root && !(root is ContainerWidget))
+ chain.Add (walk);
+
+ for (int i = chain.Count - 1; i >= 0; i--) {
+ walk = (Widget) chain [i];
+ walk.FireEnter ();
+ }
+ }
+
+ walk = this;
+ Widget ctl = this;
+ while (walk != null) {
+ if (walk.Parent is ContainerWidget) {
+ ((ContainerWidget) walk.Parent).active_Widget = ctl;
+ ctl = walk.Parent;
+ }
+ walk = walk.Parent;
+ }
+
+ if (this is Form)
+ CheckAcceptButton();
+
+ // Scroll Widget into view
+ ScrollWidgetIntoView(active_Widget);
+
+
+ walk = this;
+ ctl = this;
+ while (walk != null) {
+ if (walk.Parent is ContainerWidget) {
+ ctl = walk.Parent;
+ }
+ walk = walk.Parent;
+ }
+
+ // Let the Widget know it's selected
+ if (ctl.InternalContainsFocus)
+ SendWidgetFocus (active_Widget);
+ }
+ }
+
+ // Return the Widget where validation failed, and null otherwise
+ // @topmost_under_root is the Widget under the root in the enter chain, if any
+ //
+ // The process of validation happens as described:
+ //
+ // 1. Iterate over the nodes in the enter chain (walk down), looking for any node
+ // causing validation. If we can't find any, don't validate the current validation chain, but postpone it,
+ // saving it in the top_container.pending_validation_chain field, since we need to keep track of it later.
+ // If we have a previous pending_validation_chain, add the new nodes, making sure they are not repeated
+ // (this is computed in ActiveWidget and we receive if as the postpone_validation parameter).
+ //
+ // 2. If we found at least one node causing validation in the enter chain, try to validate the elements
+ // in pending_validation_chain, if any. Then continue with the ones receives as parameters.
+ //
+ // 3. Return null if all the validation performed successfully, and return the Widget where the validation
+ // failed otherwise.
+ //
+ private Widget PerformValidation (ContainerWidget top_container, bool postpone_validation, ArrayList validation_chain,
+ Widget topmost_under_root)
+ {
+ validation_failed = false;
+
+ if (postpone_validation) {
+ AddValidationChain (top_container, validation_chain);
+ return null;
+ }
+
+ // if not null, pending chain has always one element or more
+ if (top_container.pending_validation_chain != null) {
+ // if the topmost node in the enter chain is exactly the topmost
+ // int the validation chain, remove it, as .net does
+ int last_idx = top_container.pending_validation_chain.Count - 1;
+ if (topmost_under_root == top_container.pending_validation_chain [last_idx])
+ top_container.pending_validation_chain.RemoveAt (last_idx);
+
+ AddValidationChain (top_container, validation_chain);
+ validation_chain = top_container.pending_validation_chain;
+ top_container.pending_validation_chain = null;
+ }
+
+ for (int i = 0; i < validation_chain.Count; i ++) {
+ if (!ValidateWidget ((Widget)validation_chain[i])) {
+ validation_failed = true;
+ return (Widget)validation_chain[i];
+ }
+ }
+
+ return null;
+ }
+
+ // Add the elements in validation_chain to the pending validation chain stored in top_container
+ private void AddValidationChain (ContainerWidget top_container, ArrayList validation_chain)
+ {
+ if (validation_chain.Count == 0)
+ return;
+
+ if (top_container.pending_validation_chain == null || top_container.pending_validation_chain.Count == 0) {
+ top_container.pending_validation_chain = validation_chain;
+ return;
+ }
+
+ foreach (Widget c in validation_chain)
+ if (!top_container.pending_validation_chain.Contains (c))
+ top_container.pending_validation_chain.Add (c);
+ }
+
+ private bool ValidateWidget (Widget c)
+ {
+ CancelEventArgs e = new CancelEventArgs ();
+
+ c.FireValidating (e);
+
+ if (e.Cancel)
+ return false;
+
+ c.FireValidated ();
+ return true;
+ }
+
+ private Widget GetMostDeeplyNestedActiveWidget (ContainerWidget container)
+ {
+ Widget active = container.ActiveWidget;
+ while (active is ContainerWidget) {
+ if (((ContainerWidget)active).ActiveWidget == null)
+ break;
+ active = ((ContainerWidget)active).ActiveWidget;
+ }
+ return active;
+ }
+
+ // Just in a separate method to make debugging a little easier,
+ // should eventually be rolled into ActiveWidget setter
+ private Widget GetCommonContainer (Widget active_Widget, Widget value)
+ {
+ Widget new_container = null;
+ Widget prev_container = active_Widget;
+
+ while (prev_container != null) {
+ new_container = value.Parent;
+ while (new_container != null) {
+ if (new_container == prev_container)
+ return new_container;
+ new_container = new_container.Parent;
+ }
+
+ prev_container = prev_container.Parent;
+ }
+
+ return null;
+ }
+
+ internal void SendWidgetFocus (Widget c)
+ {
+ if (c != null && c.IsHandleCreated) {
+ XplatUI.SetFocus (c.window.Handle);
+ }
+ }
+
+ [Browsable (false)]
+ //[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+ //[EditorBrowsable (EditorBrowsableState.Advanced)]
+ [Localizable (true)]
+ public SizeF AutoScaleDimensions {
+ get {
+ return auto_scale_dimensions;
+ }
+
+ set {
+ if (auto_scale_dimensions != value) {
+ auto_scale_dimensions = value;
+
+ PerformAutoScale ();
+ }
+ }
+ }
+
+ protected SizeF AutoScaleFactor {
+ get {
+ if (auto_scale_dimensions.IsEmpty)
+ return new SizeF (1f, 1f);
+
+ return new SizeF(CurrentAutoScaleDimensions.Width / auto_scale_dimensions.Width,
+ CurrentAutoScaleDimensions.Height / auto_scale_dimensions.Height);
+ }
+ }
+
+
+ [Browsable (false)]
+ //[EditorBrowsable (EditorBrowsableState.Advanced)]
+ //[DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
+ public AutoScaleMode AutoScaleMode {
+ get {
+ return auto_scale_mode;
+ }
+ set {
+ if (this is Form)
+ (this as Form).AutoScale = false;
+
+ if (auto_scale_mode != value) {
+ auto_scale_mode = value;
+
+ if (auto_scale_mode_set)
+ auto_scale_dimensions = SizeF.Empty;
+
+ auto_scale_mode_set = true;
+
+ PerformAutoScale ();
+ }
+ }
+ }
+
+ [Browsable (false)]
+ public override BindingContext BindingContext {
+ get {
+ if (base.BindingContext == null) {
+ base.BindingContext = new BindingContext();
+ }
+ return base.BindingContext;
+ }
+
+ set {
+ base.BindingContext = value;
+ }
+ }
+
+ [Browsable (false)]
+ //[EditorBrowsable (EditorBrowsableState.Advanced)]
+ public SizeF CurrentAutoScaleDimensions {
+ get {
+ switch(auto_scale_mode) {
+ case AutoScaleMode.Dpi:
+ return TextRenderer.GetDpi ();
+
+ case AutoScaleMode.Font:
+ Size s = TextRenderer.MeasureText ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890", Font);
+ int width = (int)Math.Round ((float)s.Width / 62f);
+
+ return new SizeF (width, s.Height);
+ }
+
+ return auto_scale_dimensions;
+ }
+ }
+
+ [Browsable (false)]
+ //[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public Form ParentForm {
+ get {
+ Widget parent;
+
+ parent = this.Parent;
+
+ while (parent != null) {
+ if (parent is Form) {
+ return (Form)parent;
+ }
+ parent = parent.Parent;
+ }
+
+ return null;
+ }
+ }
+ #endregion // Public Instance Properties
+
+ #region Protected Instance Methods
+ protected override bool CanEnableIme {
+ get { return false; }
+ }
+ protected override CreateParams CreateParams {
+ get {
+ return base.CreateParams;
+ }
+ }
+ #endregion // Public Instance Methods
+
+ #region Public Instance Methods
+ internal void PerformAutoScale (bool called_by_scale)
+ {
+ if ((AutoScaleMode == AutoScaleMode.Inherit) && !called_by_scale)
+ return;
+
+ if ((layout_suspended > 0) && !called_by_scale) {
+ auto_scale_pending = true;
+ return;
+ }
+ // Set this first so we don't get called again from
+ // PerformDelayedAutoScale after ResumeLayout
+ auto_scale_pending = false;
+
+ SizeF factor = AutoScaleFactor;
+ if (AutoScaleMode == AutoScaleMode.Inherit) {
+ ContainerWidget cc = FindContainer (this.Parent);
+ if (cc != null)
+ factor = cc.AutoScaleFactor;
+ }
+ if (factor != new SizeF (1F, 1F)) {
+ is_auto_scaling = true;
+ SuspendLayout ();
+ Scale (factor);
+ ResumeLayout (false);
+ is_auto_scaling = false;
+ }
+
+ auto_scale_dimensions = CurrentAutoScaleDimensions;
+ }
+
+ public void PerformAutoScale ()
+ {
+ PerformAutoScale (false);
+ }
+
+ internal void PerformDelayedAutoScale ()
+ {
+ if (auto_scale_pending)
+ PerformAutoScale ();
+ }
+
+ internal bool IsAutoScaling {
+ get { return is_auto_scaling; }
+ }
+
+ [MonoTODO ("Stub, not implemented")]
+ static bool ValidateWarned;
+ public bool Validate() {
+ //throw new NotImplementedException();
+ if (!ValidateWarned) {
+ Console.WriteLine("ContainerWidget.Validate is not yet implemented");
+ ValidateWarned = true;
+ }
+ return true;
+ }
+
+ public bool Validate (bool checkAutoValidate)
+ {
+ if ((checkAutoValidate && (AutoValidate != AutoValidate.Disable)) || !checkAutoValidate)
+ return Validate ();
+
+ return true;
+ }
+
+ [Browsable (false)]
+ //[EditorBrowsable (EditorBrowsableState.Never)]
+ public virtual bool ValidateChildren ()
+ {
+ return ValidateChildren (ValidationConstraints.Selectable);
+ }
+
+ [Browsable (false)]
+ //[EditorBrowsable (EditorBrowsableState.Never)]
+ public virtual bool ValidateChildren (ValidationConstraints validationConstraints)
+ {
+ bool recurse = !((validationConstraints & ValidationConstraints.ImmediateChildren) == ValidationConstraints.ImmediateChildren);
+
+ foreach (Widget Widget in Widgets)
+ if (!ValidateNestedWidgets (Widget, validationConstraints, recurse))
+ return false;
+
+ return true;
+ }
+
+ bool IContainerWidget.ActivateWidget(Widget Widget) {
+ return Select(Widget);
+ }
+ #endregion // Public Instance Methods
+
+ #region Protected Instance Methods
+ //[EditorBrowsable (EditorBrowsableState.Advanced)]
+ protected override void AdjustFormScrollbars(bool displayScrollbars) {
+ base.AdjustFormScrollbars(displayScrollbars);
+ }
+
+ protected override void Dispose(bool disposing) {
+ base.Dispose(disposing);
+ }
+
+ // LAMESPEC This used to be documented, but it's not in code
+ // and no longer listed in MSDN2
+ // //[EditorBrowsable (EditorBrowsableState.Advanced)]
+ // protected override void OnWidgetRemoved(WidgetEventArgs e) {
+ private void OnWidgetRemoved(object sender, WidgetEventArgs e) {
+ if (e.Widget == this.unvalidated_Widget) {
+ this.unvalidated_Widget = null;
+ }
+
+ if (e.Widget == this.active_Widget) {
+ this.unvalidated_Widget = null;
+ }
+
+ // base.OnWidgetRemoved(e);
+ }
+
+ protected override void OnCreateWidget() {
+ base.OnCreateWidget();
+ // MS seems to call this here, it gets the whole databinding process started
+ OnBindingContextChanged (EventArgs.Empty);
+ }
+
+ protected override bool ProcessCmdKey (ref Message msg, Keys keyData)
+ {
+ if (ToolStripManager.ProcessCmdKey (ref msg, keyData) == true)
+ return true;
+
+ return base.ProcessCmdKey (ref msg, keyData);
+ }
+
+ //[EditorBrowsable (EditorBrowsableState.Advanced)]
+ protected override bool ProcessDialogChar(char charCode) {
+ if (GetTopLevel()) {
+ if (ProcessMnemonic(charCode)) {
+ return true;
+ }
+ }
+ return base.ProcessDialogChar(charCode);
+ }
+
+ protected override bool ProcessDialogKey(Keys keyData) {
+ Keys key;
+ bool forward;
+
+ key = keyData & Keys.KeyCode;
+ forward = true;
+
+ switch (key) {
+ case Keys.Tab: {
+ if ((keyData & (Keys.Alt | Keys.Widget)) == Keys.None) {
+ if (ProcessTabKey ((Widget.ModifierKeys & Keys.Shift) == 0)) {
+ return true;
+ }
+ }
+ break;
+ }
+
+ case Keys.Left: {
+ forward = false;
+ goto case Keys.Down;
+ }
+
+ case Keys.Up: {
+ forward = false;
+ goto case Keys.Down;
+ }
+
+ case Keys.Right: {
+ goto case Keys.Down;
+ }
+ case Keys.Down: {
+ if (SelectNextWidget(active_Widget, forward, false, false, true)) {
+ return true;
+ }
+ break;
+ }
+
+
+ }
+ return base.ProcessDialogKey(keyData);
+ }
+
+ protected override bool ProcessMnemonic(char charCode) {
+ bool wrapped;
+ Widget c;
+
+ wrapped = false;
+ c = active_Widget;
+
+ do {
+ c = GetNextWidget(c, true);
+ if (c != null) {
+ // This is stupid. I want to be able to call c.ProcessMnemonic directly
+ if (c.ProcessWidgetMnemonic(charCode)) {
+ return(true);
+ }
+ continue;
+ } else {
+ if (wrapped) {
+ break;
+ }
+ wrapped = true;
+ }
+ } while (c != active_Widget);
+
+ return false;
+ }
+
+ protected virtual bool ProcessTabKey(bool forward) {
+ return SelectNextWidget(active_Widget, forward, true, true, false);
+ }
+
+ protected override void Select(bool directed, bool forward)
+ {
+ if (Parent != null) {
+ IContainerWidget parent = Parent.GetContainerWidget ();
+ if (parent != null) {
+ parent.ActiveWidget = this;
+ }
+ }
+
+ if (directed && auto_select_child) {
+ SelectNextWidget (null, forward, true, true, false);
+ }
+ }
+
+ protected virtual void UpdateDefaultButton() {
+ // MS Internal
+ }
+
+ //[EditorBrowsable (EditorBrowsableState.Advanced)]
+ protected override void WndProc(ref Message m) {
+ switch ((Msg) m.Msg) {
+
+ case Msg.WM_SETFOCUS:
+ if (active_Widget != null)
+ Select (active_Widget);
+ else
+ base.WndProc (ref m);
+ break;
+
+ default:
+ base.WndProc(ref m);
+ break;
+ }
+ }
+ #endregion // Protected Instance Methods
+
+ #region Internal Methods
+ internal void ChildWidgetRemoved (Widget Widget)
+ {
+ ContainerWidget top_container = FindForm ();
+ if (top_container == null)
+ top_container = this;
+
+ // Remove Widgets -as well as any sub Widget- that was in the pending validation chain
+ ArrayList pending_validation_chain = top_container.pending_validation_chain;
+ if (pending_validation_chain != null) {
+ RemoveChildrenFromValidation (pending_validation_chain, Widget);
+
+ if (pending_validation_chain.Count == 0)
+ top_container.pending_validation_chain = null;
+ }
+
+ if (Widget == active_Widget || Widget.Contains (active_Widget)) {
+ SelectNextWidget (this, true, true, true, true);
+ if (Widget == active_Widget || Widget.Contains (active_Widget)) {
+ active_Widget = null;
+ }
+ }
+ }
+
+ // Check that this Widget (or any child) is included in the pending validation chain
+ bool RemoveChildrenFromValidation (ArrayList validation_chain, Widget c)
+ {
+ if (RemoveFromValidationChain (validation_chain, c))
+ return true;
+
+ foreach (Widget child in c.Widgets)
+ if (RemoveChildrenFromValidation (validation_chain, child))
+ return true;
+
+ return false;
+ }
+
+ // Remove the top most Widget in the pending validation chain, as well as any children there,
+ // taking advantage of the fact that the chain is in reverse order of the Widget's hierarchy
+ bool RemoveFromValidationChain (ArrayList validation_chain, Widget c)
+ {
+ int idx = validation_chain.IndexOf (c);
+ if (idx > -1) {
+ pending_validation_chain.RemoveAt (idx--);
+ return true;
+ }
+
+ return false;
+ }
+
+ internal virtual void CheckAcceptButton()
+ {
+ // do nothing here, only called if it is a Form
+ }
+
+ private bool ValidateNestedWidgets (Widget c, ValidationConstraints constraints, bool recurse)
+ {
+ bool validate_result = true;
+
+ if (!c.CausesValidation)
+ validate_result = true;
+ else if (!ValidateThisWidget (c, constraints))
+ validate_result = true;
+ else if (!ValidateWidget (c))
+ validate_result = false;
+
+ if (recurse)
+ foreach (Widget Widget in c.Widgets)
+ if (!ValidateNestedWidgets (Widget, constraints, recurse))
+ return false;
+
+ return validate_result;
+ }
+
+ private bool ValidateThisWidget (Widget c, ValidationConstraints constraints)
+ {
+ if (constraints == ValidationConstraints.None)
+ return true;
+
+ if ((constraints & ValidationConstraints.Enabled) == ValidationConstraints.Enabled && !c.Enabled)
+ return false;
+
+ if ((constraints & ValidationConstraints.Selectable) == ValidationConstraints.Selectable && !c.GetStyle (Widgetstyles.Selectable))
+ return false;
+
+ if ((constraints & ValidationConstraints.TabStop) == ValidationConstraints.TabStop && !c.TabStop)
+ return false;
+
+ if ((constraints & ValidationConstraints.Visible) == ValidationConstraints.Visible && !c.Visible)
+ return false;
+
+ return true;
+ }
+ #endregion // Internal Methods
+
+ protected override void OnParentChanged (EventArgs e)
+ {
+ base.OnParentChanged (e);
+ }
+
+ //[EditorBrowsable (EditorBrowsableState.Advanced)]
+ protected override void OnFontChanged (EventArgs e)
+ {
+ base.OnFontChanged (e);
+
+ if (AutoScaleMode == AutoScaleMode.Font)
+ PerformAutoScale ();
+ }
+
+ protected override void OnLayout (LayoutEventArgs e)
+ {
+ base.OnLayout (e);
+ }
+
+ AutoValidate auto_validate = AutoValidate.Inherit;
+
+ [Browsable (false)]
+ [AmbientValue (AutoValidate.Inherit)]
+ //[EditorBrowsable (EditorBrowsableState.Never)]
+ public virtual AutoValidate AutoValidate {
+ get {
+ return auto_validate;
+ }
+
+ [MonoTODO("Currently does nothing with the setting")]
+ set {
+ if (auto_validate != value){
+ auto_validate = value;
+ OnAutoValidateChanged (new EventArgs ());
+ }
+ }
+ }
+
+ internal bool ShouldSerializeAutoValidate ()
+ {
+ return this.AutoValidate != AutoValidate.Inherit;
+ }
+
+ static object OnValidateChanged = new object ();
+
+ protected virtual void OnAutoValidateChanged (EventArgs e)
+ {
+ EventHandler eh = (EventHandler) (Events [OnValidateChanged]);
+ if (eh != null)
+ eh (this, e);
+ }
+
+ [Browsable (false)]
+ //[EditorBrowsable (EditorBrowsableState.Never)]
+ public event EventHandler AutoValidateChanged {
+ add { Events.AddHandler (OnValidateChanged, value); }
+ remove { Events.RemoveHandler (OnValidateChanged, value); }
+ }
+ }
+}