From d40fed5ce2bc806a91245adb18039634eac13ed0 Mon Sep 17 00:00:00 2001 From: MichaelTheShifter Date: Wed, 20 Jul 2016 09:40:36 -0400 Subject: Move ShiftUI source code to ShiftOS This'll be a lot easier to work on. --- source/ShiftUI/Internal/ButtonBase.cs | 747 ++++++++++++++++++++++++++++++++++ 1 file changed, 747 insertions(+) create mode 100644 source/ShiftUI/Internal/ButtonBase.cs (limited to 'source/ShiftUI/Internal/ButtonBase.cs') diff --git a/source/ShiftUI/Internal/ButtonBase.cs b/source/ShiftUI/Internal/ButtonBase.cs new file mode 100644 index 0000000..7f8c894 --- /dev/null +++ b/source/ShiftUI/Internal/ButtonBase.cs @@ -0,0 +1,747 @@ +// 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-2006 Novell, Inc. +// +// Authors: +// Peter Bartok pbartok@novell.com +// + +using System.ComponentModel; +using System.ComponentModel.Design; +using System.Drawing; +using System.Drawing.Text; +using System.Runtime.InteropServices; +using System; + +namespace ShiftUI { + [ClassInterface (ClassInterfaceType.AutoDispatch)] + [ComVisible (true)] + //[Designer ("ShiftUI.Design.ButtonBaseDesigner, " + Consts.AssemblySystem_Design, + //"System.ComponentModel.Design.IDesigner")] + public abstract class ButtonBase : Widget + { + #region Local Variables + private FlatStyle flat_style; + private int image_index; + internal Image image; + internal ImageList image_list; + private ContentAlignment image_alignment; + internal ContentAlignment text_alignment; + private bool is_default; + internal bool is_pressed; +// private bool enter_state; + internal StringFormat text_format; + internal bool paint_as_acceptbutton; + + // Properties are 2.0, but variables used in 1.1 for common drawing code + private bool auto_ellipsis; + private FlatButtonAppearance flat_button_appearance; + private string image_key; + private TextImageRelation text_image_relation; + private TextFormatFlags text_format_flags; + private bool use_mnemonic; + private bool use_visual_style_back_color; + #endregion // Local Variables + + #region Public Constructors + protected ButtonBase() : base() + { + flat_style = FlatStyle.Standard; + flat_button_appearance = new FlatButtonAppearance (this); + this.image_key = string.Empty; + this.text_image_relation = TextImageRelation.Overlay; + this.use_mnemonic = true; + use_visual_style_back_color = true; + image_index = -1; + image = null; + image_list = null; + image_alignment = ContentAlignment.MiddleCenter; + ImeMode = ImeMode.Disable; + text_alignment = ContentAlignment.MiddleCenter; + is_default = false; + is_pressed = false; + text_format = new StringFormat(); + text_format.Alignment = StringAlignment.Center; + text_format.LineAlignment = StringAlignment.Center; + text_format.HotkeyPrefix = HotkeyPrefix.Show; + text_format.FormatFlags |= StringFormatFlags.LineLimit; + + text_format_flags = TextFormatFlags.HorizontalCenter; + text_format_flags |= TextFormatFlags.VerticalCenter; + text_format_flags |= TextFormatFlags.TextBoxControl; + + SetStyle (Widgetstyles.ResizeRedraw | + Widgetstyles.Opaque | + Widgetstyles.UserMouse | + Widgetstyles.SupportsTransparentBackColor | + Widgetstyles.CacheText | + Widgetstyles.OptimizedDoubleBuffer, true); + SetStyle (Widgetstyles.StandardClick, false); + } + #endregion // Public Constructors + + #region Public Properties + [Browsable (true)] + [DefaultValue (false)] + //[EditorBrowsable (EditorBrowsableState.Always)] + [MWFCategory("Behavior")] + public bool AutoEllipsis { + get { return this.auto_ellipsis; } + set + { + if (this.auto_ellipsis != value) { + this.auto_ellipsis = value; + + if (this.auto_ellipsis) { + text_format_flags |= TextFormatFlags.EndEllipsis; + text_format_flags &= ~TextFormatFlags.WordBreak; + } else { + text_format_flags &= ~TextFormatFlags.EndEllipsis; + text_format_flags |= TextFormatFlags.WordBreak; + } + + if (Parent != null) + Parent.PerformLayout (this, "AutoEllipsis"); + this.Invalidate (); + } + } + } + + [Browsable (true)] + //[EditorBrowsable (EditorBrowsableState.Always)] + //[DesignerSerializationVisibility (DesignerSerializationVisibility.Visible)] + [MWFCategory("Layout")] + public override bool AutoSize { + get { return base.AutoSize; } + set { base.AutoSize = value; } + } + + public override Color BackColor { + get { return base.BackColor; } + set { base.BackColor = value; } + } + + //[DesignerSerializationVisibility (DesignerSerializationVisibility.Content)] + [Browsable (true)] + [MWFCategory("Appearance")] + public FlatButtonAppearance FlatAppearance { + get { return flat_button_appearance; } + } + + [Localizable(true)] + [DefaultValue(FlatStyle.Standard)] + [MWFDescription("Determines look of button"), MWFCategory("Appearance")] + public FlatStyle FlatStyle { + get { return flat_style; } + set { + if (flat_style != value) { + flat_style = value; + + if (Parent != null) + Parent.PerformLayout (this, "FlatStyle"); + Invalidate(); + } + } + } + + [Localizable(true)] + [MWFDescription("Sets image to be displayed on button face"), MWFCategory("Appearance")] + public Image Image { + get { + if (this.image != null) + return this.image; + + if (this.image_index >= 0) + if (this.image_list != null) + return this.image_list.Images[this.image_index]; + + if (!string.IsNullOrEmpty (this.image_key)) + if (this.image_list != null) + return this.image_list.Images[this.image_key]; + return null; + } + set { + if (this.image != value) { + this.image = value; + this.image_index = -1; + this.image_key = string.Empty; + this.image_list = null; + + if (this.AutoSize && this.Parent != null) + this.Parent.PerformLayout (this, "Image"); + + Invalidate (); + } + } + } + + internal bool ShouldSerializeImage () + { + return this.Image != null; + } + + [Localizable(true)] + [DefaultValue(ContentAlignment.MiddleCenter)] + [MWFDescription("Sets the alignment of the image to be displayed on button face"), MWFCategory("Appearance")] + public ContentAlignment ImageAlign { + get { return image_alignment; } + set { + if (image_alignment != value) { + image_alignment = value; + Invalidate (); + } + } + } + + [Localizable(true)] + [DefaultValue(-1)] + //[Editor("ShiftUI.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design, typeof(System.Drawing.Design.UITypeEditor))] + [TypeConverter(typeof(ImageIndexConverter))] + [MWFDescription("Index of image to display, if ImageList is used for button face images"), MWFCategory("Appearance")] + [RefreshProperties (RefreshProperties.Repaint)] + public int ImageIndex { + get { + if (image_list == null) + return -1; + + return image_index; + } + set { + if (this.image_index != value) { + this.image_index = value; + this.image = null; + this.image_key = string.Empty; + Invalidate (); + } + } + } + + [Localizable (true)] + [DefaultValue ("")] + //[Editor ("ShiftUI.Design.ImageIndexEditor, " + Consts.AssemblySystem_Design, typeof (System.Drawing.Design.UITypeEditor))] + [RefreshProperties (RefreshProperties.Repaint)] + [TypeConverter (typeof (ImageKeyConverter))] + [MWFCategory("Appearance")] + public string ImageKey { + get { return this.image_key; } + set { + if (this.image_key != value) { + this.image = null; + this.image_index = -1; + this.image_key = value; + this.Invalidate (); + } + } + } + + [DefaultValue(null)] + [MWFDescription("ImageList used for ImageIndex"), MWFCategory("Appearance")] + [RefreshProperties (RefreshProperties.Repaint)] + public ImageList ImageList { + get { return image_list; } + set { + if (image_list != value) { + image_list = value; + + if (value != null && image != null) + image = null; + + Invalidate (); + } + } + } + + [Browsable(false)] + //[EditorBrowsable (EditorBrowsableState.Never)] + public new ImeMode ImeMode { + get { return base.ImeMode; } + set { base.ImeMode = value; } + } + + [SettingsBindable (true)] + //[Editor ("System.ComponentModel.Design.MultilineStringEditor, " + Consts.AssemblySystem_Design, + //"System.Drawing.Design.UITypeEditor, " + Consts.AssemblySystem_Drawing)] + public override string Text { + get { return base.Text; } + set { base.Text = value; } + } + + [Localizable(true)] + [DefaultValue(ContentAlignment.MiddleCenter)] + [MWFDescription("Alignment for button text"), MWFCategory("Appearance")] + public virtual ContentAlignment TextAlign { + get { return text_alignment; } + set { + if (text_alignment != value) { + text_alignment = value; + + text_format_flags &= ~TextFormatFlags.Bottom; + text_format_flags &= ~TextFormatFlags.Top; + text_format_flags &= ~TextFormatFlags.Left; + text_format_flags &= ~TextFormatFlags.Right; + text_format_flags &= ~TextFormatFlags.HorizontalCenter; + text_format_flags &= ~TextFormatFlags.VerticalCenter; + + switch (text_alignment) { + case ContentAlignment.TopLeft: + text_format.Alignment=StringAlignment.Near; + text_format.LineAlignment=StringAlignment.Near; + break; + + case ContentAlignment.TopCenter: + text_format.Alignment=StringAlignment.Center; + text_format.LineAlignment=StringAlignment.Near; + text_format_flags |= TextFormatFlags.HorizontalCenter; + break; + + case ContentAlignment.TopRight: + text_format.Alignment=StringAlignment.Far; + text_format.LineAlignment=StringAlignment.Near; + text_format_flags |= TextFormatFlags.Right; + break; + + case ContentAlignment.MiddleLeft: + text_format.Alignment=StringAlignment.Near; + text_format.LineAlignment=StringAlignment.Center; + text_format_flags |= TextFormatFlags.VerticalCenter; + break; + + case ContentAlignment.MiddleCenter: + text_format.Alignment=StringAlignment.Center; + text_format.LineAlignment=StringAlignment.Center; + text_format_flags |= TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter; + break; + + case ContentAlignment.MiddleRight: + text_format.Alignment=StringAlignment.Far; + text_format.LineAlignment=StringAlignment.Center; + text_format_flags |= TextFormatFlags.VerticalCenter | TextFormatFlags.Right; + break; + + case ContentAlignment.BottomLeft: + text_format.Alignment=StringAlignment.Near; + text_format.LineAlignment=StringAlignment.Far; + text_format_flags |= TextFormatFlags.Bottom; + break; + + case ContentAlignment.BottomCenter: + text_format.Alignment=StringAlignment.Center; + text_format.LineAlignment=StringAlignment.Far; + text_format_flags |= TextFormatFlags.HorizontalCenter | TextFormatFlags.Bottom; + break; + + case ContentAlignment.BottomRight: + text_format.Alignment=StringAlignment.Far; + text_format.LineAlignment=StringAlignment.Far; + text_format_flags |= TextFormatFlags.Bottom | TextFormatFlags.Right; + break; + } + + Invalidate(); + } + } + } + + [Localizable (true)] + [DefaultValue (TextImageRelation.Overlay)] + [MWFCategory("Appearance")] + public TextImageRelation TextImageRelation { + get { return this.text_image_relation; } + set { + if (!Enum.IsDefined (typeof (TextImageRelation), value)) + throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for TextImageRelation", value)); + + if (this.text_image_relation != value) { + this.text_image_relation = value; + + if (this.AutoSize && this.Parent != null) + this.Parent.PerformLayout (this, "TextImageRelation"); + + this.Invalidate (); + } + } + } + + [DefaultValue (false)] + [MWFCategory("Behavior")] + public bool UseCompatibleTextRendering { + get { return use_compatible_text_rendering; } + set { + if (use_compatible_text_rendering != value) { + use_compatible_text_rendering = value; + if (Parent != null) + Parent.PerformLayout (this, "UseCompatibleTextRendering"); + Invalidate (); + } + } + } + + [DefaultValue (true)] + [MWFCategory("Appearance")] + public bool UseMnemonic { + get { return this.use_mnemonic; } + set { + if (this.use_mnemonic != value) { + this.use_mnemonic = value; + + if (this.use_mnemonic) + text_format_flags &= ~TextFormatFlags.NoPrefix; + else + text_format_flags |= TextFormatFlags.NoPrefix; + + this.Invalidate (); + } + } + } + + [MWFCategory("Appearance")] + public bool UseVisualStyleBackColor { + get { return use_visual_style_back_color; } + set { + if (use_visual_style_back_color != value) { + use_visual_style_back_color = value; + Invalidate (); + } + } + } + #endregion // Public Instance Properties + + #region Protected Properties + protected override CreateParams CreateParams { + get { return base.CreateParams; } + } + + protected override ImeMode DefaultImeMode { + get { return ImeMode.Disable; } + } + + protected override Size DefaultSize { + get { return ThemeEngine.Current.ButtonBaseDefaultSize; } + } + + protected internal bool IsDefault { + get { return is_default; } + set { + if (is_default != value) { + is_default = value; + Invalidate (); + } + } + } + #endregion // Public Instance Properties + + #region Public Methods + // The base calls into GetPreferredSizeCore, which we will override in our subclasses + public override Size GetPreferredSize (Size proposedSize) + { + return base.GetPreferredSize (proposedSize); + } + #endregion + + #region Protected Methods + protected override AccessibleObject CreateAccessibilityInstance () + { + return new ButtonBaseAccessibleObject (this); + } + + protected override void Dispose (bool disposing) + { + base.Dispose (disposing); + } + + protected override void OnEnabledChanged (EventArgs e) + { + base.OnEnabledChanged (e); + } + + protected override void OnGotFocus (EventArgs e) + { + Invalidate (); + base.OnGotFocus (e); + } + + protected override void OnKeyDown (KeyEventArgs kevent) + { + if (kevent.KeyData == Keys.Space) { + is_pressed = true; + Invalidate (); + kevent.Handled = true; + } + + base.OnKeyDown (kevent); + } + + protected override void OnKeyUp (KeyEventArgs kevent) + { + if (kevent.KeyData == Keys.Space) { + is_pressed = false; + Invalidate (); + OnClick (EventArgs.Empty); + kevent.Handled = true; + } + + base.OnKeyUp (kevent); + } + + protected override void OnLostFocus (EventArgs e) + { + Invalidate (); + base.OnLostFocus (e); + } + + protected override void OnMouseDown (MouseEventArgs mevent) + { + if ((mevent.Button & MouseButtons.Left) != 0) { + is_pressed = true; + Invalidate (); + } + + base.OnMouseDown (mevent); + } + + protected override void OnMouseEnter (EventArgs eventargs) + { + is_entered = true; + Invalidate (); + base.OnMouseEnter (eventargs); + } + + protected override void OnMouseLeave (EventArgs eventargs) + { + is_entered = false; + Invalidate (); + base.OnMouseLeave (eventargs); + } + + protected override void OnMouseMove (MouseEventArgs mevent) { + bool inside = false; + bool redraw = false; + + if (ClientRectangle.Contains (mevent.Location)) + inside = true; + + // If the button was pressed and we leave, release the button press and vice versa + if ((mevent.Button & MouseButtons.Left) != 0) { + if (this.Capture && (inside != is_pressed)) { + is_pressed = inside; + redraw = true; + } + } + + if (is_entered != inside) { + is_entered = inside; + redraw = true; + } + + if (redraw) + Invalidate (); + + base.OnMouseMove (mevent); + } + + protected override void OnMouseUp (MouseEventArgs mevent) + { + if (this.Capture && ((mevent.Button & MouseButtons.Left) != 0)) { + this.Capture = false; + + if (is_pressed) { + is_pressed = false; + Invalidate (); + } else if ((this.flat_style == FlatStyle.Flat) || (this.flat_style == FlatStyle.Popup)) { + Invalidate (); + } + + if (ClientRectangle.Contains (mevent.Location)) + if (!ValidationFailed) { + OnClick (EventArgs.Empty); + OnMouseClick (mevent); + } + } + + base.OnMouseUp (mevent); + } + + protected override void OnPaint (PaintEventArgs pevent) + { + Draw (pevent); + base.OnPaint (pevent); + } + + protected override void OnParentChanged (EventArgs e) + { + base.OnParentChanged (e); + } + + protected override void OnTextChanged (EventArgs e) + { + Invalidate (); + base.OnTextChanged (e); + } + + protected override void OnVisibleChanged (EventArgs e) + { + if (!Visible) { + is_pressed = false; + is_entered = false; + } + + base.OnVisibleChanged (e); + } + + protected void ResetFlagsandPaint () + { + // Nothing to do; MS internal + // Should we do Invalidate (); ? + } + + protected override void WndProc (ref Message m) + { + switch ((Msg)m.Msg) { + case Msg.WM_LBUTTONDBLCLK: { + HaveDoubleClick (); + break; + } + + case Msg.WM_MBUTTONDBLCLK: { + HaveDoubleClick (); + break; + } + + case Msg.WM_RBUTTONDBLCLK: { + HaveDoubleClick (); + break; + } + } + + base.WndProc (ref m); + } + #endregion // Public Instance Properties + + #region Public Events + [Browsable (true)] + //[EditorBrowsable (EditorBrowsableState.Always)] + public new event EventHandler AutoSizeChanged { + add { base.AutoSizeChanged += value; } + remove { base.AutoSizeChanged -= value; } + } + + [Browsable (false)] + //[EditorBrowsable (EditorBrowsableState.Never)] + public new event EventHandler ImeModeChanged { + add { base.ImeModeChanged += value; } + remove { base.ImeModeChanged -= value; } + } + #endregion // Events + + #region Internal Properties + internal ButtonState ButtonState { + get { + ButtonState ret = ButtonState.Normal; + + if (Enabled) { + // Popup style is only followed as long as the mouse isn't "in" the control + if (is_entered) { + if (flat_style == FlatStyle.Flat) { + ret |= ButtonState.Flat; + } + } else { + if (flat_style == FlatStyle.Flat || flat_style == FlatStyle.Popup) { + ret |= ButtonState.Flat; + } + } + + if (is_entered && is_pressed) { + ret |= ButtonState.Pushed; + } + } else { + ret |= ButtonState.Inactive; + if ((flat_style == FlatStyle.Flat) || (flat_style == FlatStyle.Popup)) { + ret |= ButtonState.Flat; + } + } + return ret; + } + } + + internal bool Pressed { + get { return this.is_pressed; } + } + + // The flags to be used for MeasureText and DrawText + internal TextFormatFlags TextFormatFlags { + get { return this.text_format_flags; } + } + #endregion + + #region Internal Methods + // Derived classes should override Draw method and we dont want + // to break the control signature, hence this approach. + internal virtual void Draw (PaintEventArgs pevent) + { + ThemeEngine.Current.DrawButtonBase (pevent.Graphics, pevent.ClipRectangle, this); + } + + internal virtual void HaveDoubleClick () + { + // override me + } + + internal override void OnPaintBackgroundInternal (PaintEventArgs e) + { + base.OnPaintBackground (e); + } + #endregion // Internal Methods + + #region ButtonBaseAccessibleObject sub-class + [ComVisible (true)] + public class ButtonBaseAccessibleObject : WidgetAccessibleObject + { + #region ButtonBaseAccessibleObject Local Variables + private new Widget owner; + #endregion // ButtonBaseAccessibleObject Local Variables + + #region ButtonBaseAccessibleObject Constructors + public ButtonBaseAccessibleObject (Widget owner) : base (owner) + { + if (owner == null) + throw new ArgumentNullException ("owner"); + + this.owner = owner; + default_action = "Press"; + role = AccessibleRole.PushButton; + } + #endregion // ButtonBaseAccessibleObject Constructors + + #region Public Properties + public override AccessibleStates State { + get { return base.State; } + } + #endregion + + #region ButtonBaseAccessibleObject Methods + public override void DoDefaultAction () + { + ((ButtonBase)owner).OnClick (EventArgs.Empty); + } + #endregion // ButtonBaseAccessibleObject Methods + } + #endregion // ButtonBaseAccessibleObject sub-class + } +} -- cgit v1.2.3