DesignerActionPanel.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / Designer / CompMod / System / ComponentModel / Design / DesignerActionPanel.cs / 5 / DesignerActionPanel.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//----------------------------------------------------------------------------- 

// IMPORTANT NOTE ([....]): 
// This file is published by the build system to public\internal\ndp\inc so that 
// its contents can be built into Microsoft.VisualStudio.Web.dll. As such, when
// making modifications to the file always make sure to build clean in the 
// venus\mvw folder to make sure you do not cause a build break.
// The original location of this file is:
// ndp\fx\src\Designer\CompMod\System\ComponentModel\Design\DesignerActionPanel.cs
// and that is where all changes should be made. 

#if MVWASSEMBLY 
namespace Microsoft.VisualStudio.Web { 
#else
namespace System.ComponentModel.Design { 
#endif
    using System;
    using System.Collections;
    using System.Collections.Generic; 
    using System.Collections.Specialized;
    using System.ComponentModel; 
    using System.ComponentModel.Design; 
    using System.Diagnostics;
    using System.Diagnostics.CodeAnalysis; 
    using System.Drawing;
    using System.Drawing.Design;
    using System.Drawing.Drawing2D;
    using System.Drawing.Imaging; 
    using System.Globalization;
    using System.Reflection; 
    using System.Runtime.InteropServices; 
    using System.Text;
    using System.Windows.Forms; 
    using System.Windows.Forms.Design;
    using System.Windows.Forms.VisualStyles;
#if !MVWASSEMBLY
    using System.Design; 
#endif
 
    using ContentAlignment = System.Drawing.ContentAlignment; 

    internal sealed class DesignerActionPanel : ContainerControl { 

        public const string ExternDllGdi32 = "gdi32.dll";
        public const string ExternDllUser32 = "user32.dll";
 
        private static readonly object EventFormActivated = new object();
        private static readonly object EventFormDeactivate = new object(); 
 
        private const int EditInputWidth = 150; // The static size of edit controls
        private const int ListBoxMaximumHeight = 200; // The maximum height of a dropdown listbox 
        private const int MinimumWidth = 150; // The minimum overall width of the panel
        private const int BottomPadding = 2; // Padding at the bottom of the panel
        private const int TopPadding = 2; // Padding at the top of the panel
 
        private const int LineLeftMargin = 5; // Left padding for all lines
        private const int LineRightMargin = 4; // Right padding for all lines 
 
        private const int LineVerticalPadding = 7; // Vertical padding between lines
 
        private const int TextBoxTopPadding = 4; // Additional padding for top of textbox lines
        private const int SeparatorHorizontalPadding = 3; // Left and right padding for separator lines

        private const int TextBoxLineCenterMargin = 5; // Padding between the label region and editor region of a textbox line 
        private const int TextBoxLineInnerPadding = 1; // Padding within the editor region of a textbox line
 
        private const int EditorLineSwatchPadding = 1; // Padding for the swatch of an editor line 
        private const int EditorLineButtonPadding = 1; // Padding for the button of an editor line
 
        private const int PanelHeaderVerticalPadding = 3; // Vertical padding within the header of the panel
        private const int PanelHeaderHorizontalPadding = 5; // Horizontal padding within the header of the panel

        private const int TextBoxHeightFixup = 2; // Countereffects the fix for VSWhidbey 359726 - we relied on the broken behavior before 

        private CommandID[] _filteredCommandIDs; 
 
        private ToolTip _toolTip;
 
        private List _lines;
        private List _lineYPositions;
        private List _lineHeights;
 
        private Color _gradientLightColor = SystemColors.Control;
        private Color _gradientDarkColor = SystemColors.Control; 
        private Color _titleBarColor = SystemColors.ActiveCaption; 
        private Color _titleBarUnselectedColor = SystemColors.InactiveCaption;
        private Color _titleBarTextColor = SystemColors.ActiveCaptionText; 
        private Color _separatorColor = SystemColors.ControlDark;
        private Color _borderColor = SystemColors.ActiveBorder;
        private Color _linkColor = SystemColors.HotTrack;
        private Color _activeLinkColor = SystemColors.HotTrack; 

        private IServiceProvider _serviceProvider; 
 
        private bool _inMethodInvoke;
#if MVWASSEMBLY 
        private bool _inPushingValue;
#endif
        private bool _updatingTasks;
        private bool _dropDownActive; 

        public DesignerActionPanel(IServiceProvider serviceProvider) { 
            SetStyle(ControlStyles.AllPaintingInWmPaint, true); 
            SetStyle(ControlStyles.Opaque, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true); 
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.UserPaint, true);

            _serviceProvider = serviceProvider; 

            _lines = new List(); 
            _lineHeights = new List(); 
            _lineYPositions = new List();
 
            _toolTip = new ToolTip();

            // Try to get the font from the IUIService, otherwise, use the default
            IUIService uiService = (IUIService)ServiceProvider.GetService(typeof(IUIService)); 
            if (uiService != null) {
                Font = (Font)uiService.Styles["DialogFont"]; 
 
                if (uiService.Styles["VsColorPanelGradientDark"] is Color) {
                    _gradientDarkColor = (Color)uiService.Styles["VsColorPanelGradientDark"]; 
                }
                if (uiService.Styles["VsColorPanelGradientLight"] is Color) {
                    _gradientLightColor = (Color)uiService.Styles["VsColorPanelGradientLight"];
                } 
                if (uiService.Styles["VsColorPanelHyperLink"] is Color) {
                    _linkColor = (Color)uiService.Styles["VsColorPanelHyperLink"]; 
                } 
                if (uiService.Styles["VsColorPanelHyperLinkPressed"] is Color) {
                    _activeLinkColor = (Color)uiService.Styles["VsColorPanelHyperLinkPressed"]; 
                }
                if (uiService.Styles["VsColorPanelTitleBar"] is Color) {
                    _titleBarColor = (Color)uiService.Styles["VsColorPanelTitleBar"];
                } 
                if (uiService.Styles["VsColorPanelTitleBarUnselected"] is Color) {
                    _titleBarUnselectedColor = (Color)uiService.Styles["VsColorPanelTitleBarUnselected"]; 
                } 
                if (uiService.Styles["VsColorPanelTitleBarText"] is Color) {
                    _titleBarTextColor = (Color)uiService.Styles["VsColorPanelTitleBarText"]; 
                }
                if (uiService.Styles["VsColorPanelBorder"] is Color) {
                    _borderColor = (Color)uiService.Styles["VsColorPanelBorder"];
                } 
                if (uiService.Styles["VsColorPanelSeparator"] is Color) {
                    _separatorColor = (Color)uiService.Styles["VsColorPanelSeparator"]; 
                } 
            }
 
            MinimumSize = new Size(150, 0);
        }

 
        public Color ActiveLinkColor {
            get { 
                return _activeLinkColor; 
            }
        } 

        public Color BorderColor {
            get {
                return _borderColor; 
            }
        } 
 
        private bool DropDownActive {
            get { 
                return _dropDownActive;
            }
        }
 
        /// 
        /// Returns the list of commands that should be filtered by the form 
        /// that hosts this panel. This is done so that these specific commands 
        /// will not get passed on to VS, and can instead be handled by the
        /// panel itself. 
        /// 
        public CommandID[] FilteredCommandIDs {
            get {
                if (_filteredCommandIDs == null) { 
                    _filteredCommandIDs = new CommandID[] {
                        StandardCommands.Copy, 
                        StandardCommands.Cut, 
                        StandardCommands.Delete,
                        StandardCommands.F1Help, 
                        StandardCommands.Paste,
                        StandardCommands.Redo,
                        StandardCommands.SelectAll,
                        StandardCommands.Undo, 
                        MenuCommands.KeyCancel,
                        MenuCommands.KeyReverseCancel, 
                        MenuCommands.KeyDefaultAction, 
                        MenuCommands.KeyEnd,
                        MenuCommands.KeyHome, 
                        MenuCommands.KeyMoveDown,
                        MenuCommands.KeyMoveLeft,
                        MenuCommands.KeyMoveRight,
                        MenuCommands.KeyMoveUp, 
                        MenuCommands.KeyNudgeDown,
                        MenuCommands.KeyNudgeHeightDecrease, 
                        MenuCommands.KeyNudgeHeightIncrease, 
                        MenuCommands.KeyNudgeLeft,
                        MenuCommands.KeyNudgeRight, 
                        MenuCommands.KeyNudgeUp,
                        MenuCommands.KeyNudgeWidthDecrease,
                        MenuCommands.KeyNudgeWidthIncrease,
                        MenuCommands.KeySizeHeightDecrease, 
                        MenuCommands.KeySizeHeightIncrease,
                        MenuCommands.KeySizeWidthDecrease, 
                        MenuCommands.KeySizeWidthIncrease, 
                        MenuCommands.KeySelectNext,
                        MenuCommands.KeySelectPrevious, 
                        MenuCommands.KeyShiftEnd,
                        MenuCommands.KeyShiftHome,
                    };
                } 
                return _filteredCommandIDs;
            } 
        } 

        ///  
        /// Gets the Line that currently has input focus.
        /// 
        private Line FocusedLine {
            get { 
                Control activeControl = ActiveControl;
                if (activeControl != null) { 
                    return activeControl.Tag as Line; 
                }
                return null; 
            }
        }

        public Color GradientDarkColor { 
            get {
                return _gradientDarkColor; 
            } 
        }
 
        public Color GradientLightColor {
            get {
                return _gradientLightColor;
            } 
        }
 
        public bool InMethodInvoke { 
            get {
                return _inMethodInvoke; 
            }
            internal set {
                _inMethodInvoke = value;
            } 
        }
 
#if MVWASSEMBLY 
        public bool InPushingValue {
            get { 
                return _inPushingValue;
            }
            internal set {
                _inPushingValue = value; 
            }
        } 
#endif 

        public Color LinkColor { 
            get {
                return _linkColor;
            }
        } 

        public Color SeparatorColor { 
            get { 
                return _separatorColor;
            } 
        }

        private IServiceProvider ServiceProvider {
            get { 
                return _serviceProvider;
            } 
        } 

        public Color TitleBarColor { 
            get {
                return _titleBarColor;
            }
        } 

        public Color TitleBarTextColor { 
            get { 
                return _titleBarTextColor;
            } 
        }

        public Color TitleBarUnselectedColor {
            get { 
                return _titleBarUnselectedColor;
            } 
        } 

        ///  
        /// Helper event so that Lines can be notified of this event.
        /// 
        private event EventHandler FormActivated {
            add { 
                Events.AddHandler(EventFormActivated, value);
            } 
            remove { 
                Events.RemoveHandler(EventFormActivated, value);
            } 
        }

        /// 
        /// Helper event so that Lines can be notified of this event. 
        /// 
        private event EventHandler FormDeactivate { 
            add { 
                Events.AddHandler(EventFormDeactivate, value);
            } 
            remove {
                Events.RemoveHandler(EventFormDeactivate, value);
            }
        } 

        private void AddToCategories(LineInfo lineInfo, ListDictionary categories) { 
            string categoryName = lineInfo.Item.Category; 
            if (categoryName == null) {
                categoryName = String.Empty; 
            }

            ListDictionary category = (ListDictionary)categories[categoryName];
            if (category == null) { 
                category = new ListDictionary();
                categories.Add(categoryName, category); 
            } 

            List categoryList = (List)category[lineInfo.List]; 
            if (categoryList == null) {
                categoryList = new List();
                category.Add(lineInfo.List, categoryList);
            } 
            categoryList.Add(lineInfo);
        } 
 
        /// 
        /// Computes the best possible location (in desktop coordinates) to display 
        /// the panel, given the size of the panel and the position of its anchor
        /// 
        public static Point ComputePreferredDesktopLocation(Rectangle rectangleAnchor, Size sizePanel, out DockStyle edgeToDock) {
            Rectangle rectScreen = Screen.FromPoint(rectangleAnchor.Location).WorkingArea; 

            // Determine where we can draw the panel to minimize clipping. 
            // Start with the most preferred position, i.e. bottom-right of anchor 
            // For the purposes of computing the flags below, assume the anchor to be
            // small enough to ignore its size. 
            bool fRightOfAnchor = true;
            bool fAlignToScreenLeft = false;

            // if the panel is too wide, try flipping to left or aligning to screen left 
            if (rectangleAnchor.Right + sizePanel.Width > rectScreen.Right) { // no room at right
                // try at left of anchor 
                fRightOfAnchor = false; 
                if (rectangleAnchor.Left - sizePanel.Width < rectScreen.Left) { // no room at left, either
                    fAlignToScreenLeft = true; 
                }
            }

            bool fBelowAnchor = (fRightOfAnchor ? true : false); 
            bool fAlignToScreenTop = false;
 
            if (fBelowAnchor) { 
                // if the panel is too tall, try flipping to top or aligning to screen top
                if (rectangleAnchor.Bottom + sizePanel.Height > rectScreen.Bottom) { // no room at bottom 
                    // try at top of anchor
                    fBelowAnchor = false;
                    if (rectangleAnchor.Top - sizePanel.Height < rectScreen.Top) { // no room at top, either
                        fAlignToScreenTop = true; 
                    }
                } 
            } 
            else {
                // if the panel is too tall, try flipping to bottom or aligning to screen top 
                if (rectangleAnchor.Top - sizePanel.Height < rectScreen.Top) { // no room at top
                    // try at bottom of anchor
                    fBelowAnchor = true;
                    if (rectangleAnchor.Bottom + sizePanel.Height > rectScreen.Bottom) { // no room at bottom, either 
                        fAlignToScreenTop = true;
                    } 
                } 
            }
 
            // The flags give us a total of nine possible positions -
            // {LeftOfAnchor, RightOfAnchor, AlignToScreenLeft} X {AboveAnchor, BelowAnchor, AlignToScreenTop}
            // Out of these, we rule out one combination (AlignToScreenLeft, AlignToScreenTop) because this
            // does not guarantee the alignment of an anchor edge with that of the panel edge 
            if (fAlignToScreenTop) {
                fAlignToScreenLeft = false; 
            } 

            int x = 0, y = 0; 
            const int EDGE_SPACE = 0;
            edgeToDock = DockStyle.None;

            // Compute the actual position now, based on the flags above, 
            // and taking the anchor size into account.
            if (fAlignToScreenLeft && fBelowAnchor) { 
                x = rectScreen.Left; 
                y = rectangleAnchor.Bottom + EDGE_SPACE;
                edgeToDock = DockStyle.Bottom; 
            }
            else if (fAlignToScreenLeft && !fBelowAnchor) {
                x = rectScreen.Left;
                y = rectangleAnchor.Top - sizePanel.Height - EDGE_SPACE; 
                edgeToDock = DockStyle.Top;
            } 
            else if (fRightOfAnchor && fAlignToScreenTop) { 
                x = rectangleAnchor.Right + EDGE_SPACE;
                y = rectScreen.Top; 
                edgeToDock = DockStyle.Right;
            }
            else if (fRightOfAnchor && fBelowAnchor) {
                x = rectangleAnchor.Right + EDGE_SPACE; 
                y = rectangleAnchor.Top;
                edgeToDock = DockStyle.Right; 
            } 
            else if (fRightOfAnchor && !fBelowAnchor) {
                x = rectangleAnchor.Right + EDGE_SPACE; 
                y = rectangleAnchor.Bottom - sizePanel.Height;
                edgeToDock = DockStyle.Right;
            }
            else if (!fRightOfAnchor && fAlignToScreenTop) { 
                x = rectangleAnchor.Left - sizePanel.Width - EDGE_SPACE;
                y = rectScreen.Top; 
                edgeToDock = DockStyle.Left; 
            }
            else if (!fRightOfAnchor && fBelowAnchor) { 
                x = rectangleAnchor.Left - sizePanel.Width - EDGE_SPACE;
                y = rectangleAnchor.Top;
                edgeToDock = DockStyle.Left;
            } 
            else if (!fRightOfAnchor && !fBelowAnchor) {
                x = rectangleAnchor.Right - sizePanel.Width; 
                y = rectangleAnchor.Top - sizePanel.Height - EDGE_SPACE; 
                edgeToDock = DockStyle.Top;
            } 
            else {
                Debug.Assert(false); // should never get here
            }
 
            return new Point(x, y);
        } 
 
        protected override void Dispose(bool disposing) {
            if (disposing) { 
                _toolTip.Dispose();
            }
            base.Dispose(disposing);
        } 

        private Size DoLayout(Size proposedSize, bool measureOnly) { 
            // 
            if (Disposing || IsDisposed) {
                return Size.Empty; 
            }

            int panelWidth = MinimumWidth;
            int yPos = 0; 

            SuspendLayout(); 
            try { 
                // Clear cached calculated information
                _lineYPositions.Clear(); 
                _lineHeights.Clear();

                // Layout each line
                for (int i = 0; i < _lines.Count; i++) { 
                    Line line = _lines[i];
 
                    _lineYPositions.Add(yPos); 
                    Size size = line.LayoutControls(yPos, proposedSize.Width, measureOnly);
                    panelWidth = Math.Max(panelWidth, size.Width); 
                    _lineHeights.Add(size.Height);

                    yPos += size.Height;
                } 
            }
            finally { 
                ResumeLayout(!measureOnly); 
            }
 
            return new Size(panelWidth, yPos + BottomPadding);
        }

        public override Size GetPreferredSize(Size proposedSize) { 
            //
 
 
            if (proposedSize.IsEmpty) {
                return proposedSize; 
            }

            return DoLayout(proposedSize, true);
        } 

        private static bool IsReadOnlyProperty(PropertyDescriptor pd) { 
            if (pd.IsReadOnly) { 
                return true;
            } 
            return (pd.ComponentType.GetProperty(pd.Name).GetSetMethod() == null);
        }

        protected override void OnFontChanged(EventArgs e) { 
            base.OnFontChanged(e);
 
            UpdateEditXPos(); 

            // 
        }

        private void OnFormActivated(object sender, EventArgs e) {
            EventHandler handler = (EventHandler)Events[EventFormActivated]; 
            if (handler != null) {
                handler(sender, e); 
            } 
        }
 
        private void OnFormClosing(object sender, CancelEventArgs e) {
            if (!e.Cancel && TopLevelControl != null) {
                Debug.Assert(TopLevelControl is Form, "DesignerActionPanel must be hosted on a Form.");
                Form form = (Form)TopLevelControl; 
                if (form != null) {
                    form.Activated -= new EventHandler(OnFormActivated); 
                    form.Deactivate -= new EventHandler(OnFormDeactivate); 
                    form.Closing -= new CancelEventHandler(OnFormClosing);
                } 
            }
        }

        private void OnFormDeactivate(object sender, EventArgs e) { 
            EventHandler handler = (EventHandler)Events[EventFormDeactivate];
            if (handler != null) { 
                handler(sender, e); 
            }
        } 

        protected override void OnHandleCreated(EventArgs e) {
            base.OnHandleCreated(e);
            Form form = TopLevelControl as Form; 
            if (form != null) {
                form.Activated += new EventHandler(OnFormActivated); 
                form.Deactivate += new EventHandler(OnFormDeactivate); 
                form.Closing += new CancelEventHandler(OnFormClosing);
            } 
        }

        protected override void OnLayout(LayoutEventArgs levent) {
            if (_updatingTasks) { 
                return;
            } 
 
            DoLayout(Size, false);
        } 

        protected override void OnPaint(PaintEventArgs e) {
            base.OnPaint(e);
 
            if (_updatingTasks) {
                return; 
            } 

            Rectangle rect = Bounds; 
            if (RightToLeft == RightToLeft.Yes) {
                using (LinearGradientBrush gradientBrush = new LinearGradientBrush(rect, GradientDarkColor, GradientLightColor, LinearGradientMode.Horizontal)) {
                    e.Graphics.FillRectangle(gradientBrush, ClientRectangle);
                } 
            }
            else { 
                using (LinearGradientBrush gradientBrush = new LinearGradientBrush(rect, GradientLightColor, GradientDarkColor, LinearGradientMode.Horizontal)) { 
                    e.Graphics.FillRectangle(gradientBrush, ClientRectangle);
                } 
            }

            using (Pen borderPen = new Pen(BorderColor)) {
                e.Graphics.DrawRectangle(borderPen, new Rectangle(0, 0, Width - 1, Height - 1)); 
            }
 
            Rectangle originalClip = e.ClipRectangle; 

            // Determine the first line index to paint 
            int index = 0;
            while ((index < (_lineYPositions.Count - 1)) && (_lineYPositions[index + 1] <= originalClip.Top)) {
                index++;
            } 

            Graphics g = e.Graphics; 
            for (int i = index; i < _lineYPositions.Count; i++) { 
                Line line = _lines[i];
 
                int yPos = _lineYPositions[i];
                int lineHeight = _lineHeights[i];
                int lineWidth = Width;
 
                // Set the clip rectangle so the lines can't mess with each other
                g.SetClip(new Rectangle(0, yPos, lineWidth, lineHeight)); 
 
                // Normalize the paint coordinates
                g.TranslateTransform(0, yPos); 
                line.PaintLine(g, lineWidth, lineHeight);
                g.ResetTransform();

                // Stop if we've painted all the lines in the clip rectangle 
                if (yPos + lineHeight > originalClip.Bottom) {
                    break; 
                } 
            }
        } 

        protected override void OnRightToLeftChanged(EventArgs e) {
            base.OnRightToLeftChanged(e);
 
            PerformLayout();
        } 
 
        protected override bool ProcessDialogKey(Keys keyData) {
            // 
            Line focusedLine = FocusedLine;
            if (focusedLine != null) {
                if (focusedLine.ProcessDialogKey(keyData)) {
                    return true; 
                }
            } 
 
            return base.ProcessDialogKey(keyData);
        } 

        // we want to loop
        protected override bool ProcessTabKey(bool forward) {
            return (SelectNextControl(ActiveControl, forward, true, true, true)); 
        }
 
        private void ProcessLists(DesignerActionListCollection lists, ListDictionary categories) { 
            if (lists == null) {
                return; 
            }
            foreach (DesignerActionList list in lists) {
                if (list != null) {
                    IEnumerable items = list.GetSortedActionItems(); 
                    if (items != null) {
                        foreach (DesignerActionItem item in items) { 
                            if (item == null) { 
                                continue;
                            } 

                            LineInfo lineInfo = ProcessTaskItem(list, item);
                            if (lineInfo == null) {
                                continue; 
                            }
 
                            AddToCategories(lineInfo, categories); 

                            // Process lists from related component 
                            IComponent relatedComponent = null;
                            DesignerActionPropertyItem propItem = item as DesignerActionPropertyItem;
                            if (propItem != null) {
                                relatedComponent = propItem.RelatedComponent; 
                            }
                            else { 
                                DesignerActionMethodItem methodItem = item as DesignerActionMethodItem; 
                                if (methodItem != null) {
                                    relatedComponent = methodItem.RelatedComponent; 
                                }
                            }

                            if (relatedComponent != null) { 
                                IEnumerable relatedLineInfos = ProcessRelatedTaskItems(relatedComponent);
                                if (relatedLineInfos != null) { 
                                    foreach (LineInfo relatedLineInfo in relatedLineInfos) { 
                                        AddToCategories(relatedLineInfo, categories);
                                    } 
                                }
                            }
                        }
                    } 
                }
            } 
        } 

        private IEnumerable ProcessRelatedTaskItems(IComponent relatedComponent) { 
            // Add the related tasks
            Debug.Assert(relatedComponent != null);

            DesignerActionListCollection relatedLists = null; 

            DesignerActionService actionService = (DesignerActionService)ServiceProvider.GetService(typeof(DesignerActionService)); 
            if (actionService != null) { 
                relatedLists = actionService.GetComponentActions(relatedComponent);
            } 
            else {
                // Try to use the component's service provider if it exists so that
                // we end up getting the right IDesignerHost.
                IServiceProvider serviceProvider = relatedComponent.Site; 
                if (serviceProvider == null) {
                    serviceProvider = ServiceProvider; 
                } 
                IDesignerHost host = (IDesignerHost)serviceProvider.GetService(typeof(IDesignerHost));
                if (host != null) { 
                    ComponentDesigner componentDesigner = host.GetDesigner(relatedComponent) as ComponentDesigner;
                    if (componentDesigner != null) {
                        relatedLists = componentDesigner.ActionLists;
                    } 
                }
            } 
 
            List lineInfos = new List();
 
            if (relatedLists != null) {
                foreach (DesignerActionList relatedList in relatedLists) {
                    if (relatedList != null) {
                        Type relatedListType = relatedList.GetType(); 
                        IEnumerable items = relatedList.GetSortedActionItems();
                        if (items!=null) { 
                            foreach (DesignerActionItem relatedItem in items) { 
                                if (relatedItem != null) {
                                    if (relatedItem.AllowAssociate) { 
                                        LineInfo lineInfo = ProcessTaskItem(relatedList, relatedItem);
                                        if (lineInfo != null) {
                                            lineInfos.Add(lineInfo);
                                        } 
                                    }
                                } 
                            } 
                        }
                    } 
                }
            }
            return lineInfos;
        } 

        private LineInfo ProcessTaskItem(DesignerActionList list, DesignerActionItem item) { 
            Line newLine = null; 
            if (item is DesignerActionMethodItem) {
                newLine = new MethodLine(_serviceProvider, this); 
            }
            else if (item is DesignerActionPropertyItem) {
                DesignerActionPropertyItem pti = (DesignerActionPropertyItem)item;
                PropertyDescriptor pd = TypeDescriptor.GetProperties(list)[pti.MemberName]; 
                if (pd == null) {
                    throw new InvalidOperationException(SR.GetString(SR.DesignerActionPanel_CouldNotFindProperty, pti.MemberName, list.GetType().FullName)); 
                } 

                TypeDescriptorContext context = new TypeDescriptorContext(_serviceProvider, pd, list); 

                UITypeEditor editor = (UITypeEditor)pd.GetEditor(typeof(UITypeEditor));
                bool standardValuesSupported = pd.Converter.GetStandardValuesSupported(context);
 
                if (editor == null) {
                    if (pd.PropertyType == typeof(bool)) { 
                        if (IsReadOnlyProperty(pd)) { 
                            newLine = new TextBoxPropertyLine(_serviceProvider, this);
                        } 
                        else {
                            newLine = new CheckBoxPropertyLine(_serviceProvider, this);
                        }
                    } 
                    else if (standardValuesSupported) {
                        newLine = new EditorPropertyLine(_serviceProvider, this); 
                    } 
                    else {
                        newLine = new TextBoxPropertyLine(_serviceProvider, this); 
                    }
                }
                else {
                    newLine = new EditorPropertyLine(_serviceProvider, this); 
                }
            } 
            else if (item is DesignerActionTextItem) { 
                if (item is DesignerActionHeaderItem) {
                    newLine = new HeaderLine(_serviceProvider, this); 
                }
                else {
                    newLine = new TextLine(_serviceProvider, this);
                } 
            }
            else { 
                // Ignore unknown items 
                return null;
            } 

            return new LineInfo(list, item, newLine);
        }
 
        private void SetDropDownActive(bool active) {
            _dropDownActive = active; 
        } 

        private void ShowError(string errorMessage) { 
            IUIService uiService = (IUIService)ServiceProvider.GetService(typeof(IUIService));
            if (uiService != null) {
                uiService.ShowError(errorMessage);
            } 
            else {
                MessageBoxOptions options = 0; 
                if (SR.GetString(SR.RTL) != "RTL_False") { 
                    options = (MessageBoxOptions.RightAlign | MessageBoxOptions.RtlReading);
                } 
                MessageBox.Show(this, errorMessage, SR.GetString(SR.UIServiceHelper_ErrorCaption), MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, options);
            }
        }
 
        /// 
        /// Strips out ampersands used for mnemonics so that they don't show up 
        /// in the rendering. 
        /// - Convert "&&" to "&"
        /// - Convert "&x" to "x" 
        /// - An ampersand by itself at the end of a string is displayed as-is
        /// 
        private static string StripAmpersands(string s) {
            if (String.IsNullOrEmpty(s)) { 
                return String.Empty;
            } 
            StringBuilder result = new StringBuilder(s.Length); 
            for (int i = 0; i < s.Length; i++) {
                if (s[i] == '&') { 
                    // Skip over the ampersand
                    i++;
                    if (i == s.Length) {
                        // If we're at the last character just add the ampersand and stop 
                        result.Append('&');
                        break; 
                    } 
                }
                result.Append(s[i]); 
            }
            return result.ToString();
        }
 
        private void UpdateEditXPos() {
            // Find the correct edit control position 
            int editXPos = 0; 
            for (int i = 0; i < _lines.Count; i++) {
                TextBoxPropertyLine line = _lines[i] as TextBoxPropertyLine; 
                if (line != null) {
                    editXPos = Math.Max(editXPos, ((TextBoxPropertyLine)line).GetEditRegionXPos());
                }
            } 

            // Make all the edit controls line up 
            for (int i = 0; i < _lines.Count; i++) { 
                TextBoxPropertyLine line = _lines[i] as TextBoxPropertyLine;
                if (line != null) { 
                    line.SetEditRegionXPos(editXPos);
                }
            }
        } 

        public void UpdateTasks(DesignerActionListCollection actionLists, DesignerActionListCollection serviceActionLists, string title, string subtitle) { 
            _updatingTasks = true; 

            SuspendLayout(); 
            try {
                AccessibleName = title;
                AccessibleDescription = subtitle;
 
                // Store the focus state
                string focusId = String.Empty; 
                Line focusedLine = FocusedLine; 
                if (focusedLine != null) {
                    focusId = focusedLine.FocusId; 
                }

                // Merge the categories from the lists and create controls for each of the items
                ListDictionary categories = new ListDictionary(); 

                ProcessLists(actionLists, categories); 
                ProcessLists(serviceActionLists, categories); 

 
                // Create a flat list of lines w/ separators
                List newLines = new List();

                // Always add a special line for the header 
                newLines.Add(new LineInfo(null, new DesignerActionPanelHeaderItem(title, subtitle), new PanelHeaderLine(_serviceProvider, this)));
 
                int categoriesIndex = 0; 
                foreach (ListDictionary category in categories.Values) {
                    int categoryIndex = 0; 
                    foreach (List categoryList in category.Values) {
                        for (int i = 0; i < categoryList.Count; i++) {
                            newLines.Add(categoryList[i]);
                        } 

                        categoryIndex++; 
 
                        // Add a sub-separator
                        if (categoryIndex < category.Count) { 
                            newLines.Add(new LineInfo(null, null, new SeparatorLine(_serviceProvider, this, true)));
                        }
                    }
 
                    categoriesIndex++;
                    // Add a separator 
                    if (categoriesIndex < categories.Count) { 
                        newLines.Add(new LineInfo(null, null, new SeparatorLine(_serviceProvider, this)));
                    } 
                }


                // Now try to update similar lines 
                int currentTabIndex = 0;
                for (int i = 0; i < newLines.Count; i++) { 
                    LineInfo newLineInfo = newLines[i]; 
                    Line newLine = newLineInfo.Line;
 
                    // See if we can update an old line
                    bool updated = false;
                    if (i < _lines.Count) {
                        Line oldLine = _lines[i]; 

                        if (oldLine.GetType() == newLine.GetType()) { 
                            oldLine.UpdateActionItem(newLineInfo.List, newLineInfo.Item, _toolTip, ref currentTabIndex); 
                            updated = true;
                        } 
                        else {
                            oldLine.RemoveControls(Controls);
                            _lines.RemoveAt(i);
                        } 
                    }
 
                    if (!updated) { 
                        // Add the new controls
                        List newControlList = newLine.GetControls(); 
                        Control[] controls = new Control[newControlList.Count];
                        newControlList.CopyTo(controls);
                        Controls.AddRange(controls);
 
                        newLine.UpdateActionItem(newLineInfo.List, newLineInfo.Item, _toolTip, ref currentTabIndex);
                        _lines.Insert(i, newLine); 
                    } 
                }
 
                // Remove any excess lines
                for (int i = _lines.Count - 1; i >= newLines.Count; i--) {
                    Line excessLine = _lines[i];
                    excessLine.RemoveControls(Controls); 
                    _lines.RemoveAt(i);
                } 
 
                // Restore focus
                if (!String.IsNullOrEmpty(focusId)) { 
                    foreach (Line line in _lines) {
                        if (String.Equals(line.FocusId, focusId, StringComparison.Ordinal)) {
                            line.Focus();
                        } 
                    }
                } 
            } 
            finally {
                UpdateEditXPos(); 

                _updatingTasks = false;

                // 

 
                // Actually, we do want to resume layout since invalidation causes an OnPaint, and 
                // OnPaint relies on everything being layed out already
                ResumeLayout(true); 
            }

            Invalidate();
        } 

        private class LineInfo { 
            public Line Line; 
            public DesignerActionItem Item;
            public DesignerActionList List; 

            public LineInfo(DesignerActionList list, DesignerActionItem item, Line line) {
                Debug.Assert(line != null);
                Line = line; 
                Item = item;
                List = list; 
            } 
        }
 
        internal sealed class TypeDescriptorContext : ITypeDescriptorContext {
            private IServiceProvider _serviceProvider;
            private PropertyDescriptor _propDesc;
            private object _instance; 

            public TypeDescriptorContext(IServiceProvider serviceProvider, PropertyDescriptor propDesc, object instance) { 
                _serviceProvider = serviceProvider; 
                _propDesc = propDesc;
                _instance = instance; 

            }

            private IComponentChangeService ComponentChangeService { 
                get {
                    return (IComponentChangeService)_serviceProvider.GetService(typeof(IComponentChangeService)); 
                } 
            }
 
            public IContainer Container {
                get {
                    return (IContainer)_serviceProvider.GetService(typeof(IContainer));
                } 
            }
 
            public object Instance { 
                get {
                    return _instance; 
                }
            }

            public PropertyDescriptor PropertyDescriptor { 
                get {
                    return _propDesc; 
                } 
            }
 
            public object GetService(Type serviceType) {
                return _serviceProvider.GetService(serviceType);
            }
 
            public bool OnComponentChanging() {
                if (ComponentChangeService != null) { 
                    try { 
                        ComponentChangeService.OnComponentChanging(_instance, _propDesc);
                    } 
                    catch (CheckoutException ce) {
                        if (ce == CheckoutException.Canceled) {
                            return false;
                        } 
                        throw ce;
                    } 
                } 

                return true; 
            }

            public void OnComponentChanged() {
                if (ComponentChangeService != null) { 
                    ComponentChangeService.OnComponentChanged(_instance, _propDesc, null, null);
                } 
            } 
        }
 
        private abstract class Line {
            private DesignerActionPanel _actionPanel;
            private List _addedControls;
            private IServiceProvider _serviceProvider; 

            public Line(IServiceProvider serviceProvider, DesignerActionPanel actionPanel) { 
                if (actionPanel == null) { 
                    throw new ArgumentNullException("actionPanel");
                } 

                _serviceProvider = serviceProvider;
                _actionPanel = actionPanel;
            } 

            protected DesignerActionPanel ActionPanel { 
                get { 
                    return _actionPanel;
                } 
            }

            public abstract string FocusId {
                get; 
            }
 
            protected IServiceProvider ServiceProvider { 
                get {
                    return _serviceProvider; 
                }
            }

            protected abstract void AddControls(List controls); 

            internal List GetControls() { 
                _addedControls = new List(); 
                AddControls(_addedControls);
                // Tag all the controls with the Line so we know who owns it 
                foreach (Control c in _addedControls) {
                    c.Tag = this;
                }
                return _addedControls; 
            }
 
            public abstract void Focus(); 

            public abstract Size LayoutControls(int top, int width, bool measureOnly); 

            public virtual void PaintLine(Graphics g, int lineWidth, int lineHeight) {
            }
 
            protected internal virtual bool ProcessDialogKey(Keys keyData) {
                return false; 
            } 

            internal void RemoveControls(Control.ControlCollection controls) { 
                for (int i = 0; i < _addedControls.Count; i++) {
                    Control c = _addedControls[i];
                    c.Tag = null;
                    controls.Remove(c); 
                }
            } 
 
            internal abstract void UpdateActionItem(DesignerActionList actionList, DesignerActionItem actionItem, ToolTip toolTip, ref int currentTabIndex);
        } 

        private sealed class DesignerActionPanelHeaderItem : DesignerActionItem {
            private string _subtitle;
 
            public DesignerActionPanelHeaderItem(string title, string subtitle)
                : base(title, null, null) { 
                _subtitle = subtitle; 
            }
 
            public string Subtitle {
                get {
                    return _subtitle;
                } 
            }
        } 
 
        private sealed class PanelHeaderLine : Line {
            private DesignerActionList _actionList; 
            private DesignerActionPanelHeaderItem _panelHeaderItem;
            private Label _titleLabel;
            private Label _subtitleLabel;
            private bool _formActive; 

            public PanelHeaderLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel) 
                : base(serviceProvider, actionPanel) { 
                actionPanel.FontChanged += new EventHandler(OnParentControlFontChanged);
            } 

            public sealed override string FocusId {
                get {
                    return String.Empty; 
                }
            } 
 
            protected override void AddControls(List controls) {
                _titleLabel = new Label(); 
                _titleLabel.BackColor = Color.Transparent;
                _titleLabel.ForeColor = ActionPanel.TitleBarTextColor;
                _titleLabel.TextAlign = ContentAlignment.MiddleLeft;
                _titleLabel.UseMnemonic = false; 

                _subtitleLabel = new Label(); 
                _subtitleLabel.BackColor = Color.Transparent; 
                _subtitleLabel.ForeColor = ActionPanel.TitleBarTextColor;
                _subtitleLabel.TextAlign = ContentAlignment.MiddleLeft; 
                _subtitleLabel.UseMnemonic = false;

                controls.Add(_titleLabel);
                controls.Add(_subtitleLabel); 

                // 
                ActionPanel.FormActivated += new EventHandler(OnFormActivated); 
                ActionPanel.FormDeactivate += new EventHandler(OnFormDeactivate);
            } 

            public sealed override void Focus() {
                Debug.Fail("Should never try to focus a PanelHeaderLine");
            } 

            public override Size LayoutControls(int top, int width, bool measureOnly) { 
                Size titleSize = _titleLabel.GetPreferredSize(new Size(Int32.MaxValue, Int32.MaxValue)); 
                Size subtitleSize = Size.Empty;
                if (!String.IsNullOrEmpty(_panelHeaderItem.Subtitle)) { 
                    subtitleSize = _subtitleLabel.GetPreferredSize(new Size(Int32.MaxValue, Int32.MaxValue));
                }

                if (!measureOnly) { 
                    _titleLabel.Location = new Point(LineLeftMargin, top + PanelHeaderVerticalPadding);
                    _titleLabel.Size = titleSize; 
 
                    _subtitleLabel.Location = new Point(LineLeftMargin, top + PanelHeaderVerticalPadding * 2 + titleSize.Height);
                    _subtitleLabel.Size = subtitleSize; 
                }

                int newWidth = Math.Max(titleSize.Width, subtitleSize.Width) + 2 * PanelHeaderHorizontalPadding;
                int newHeight = (subtitleSize.IsEmpty ? (titleSize.Height + 2 * PanelHeaderVerticalPadding) : (titleSize.Height + subtitleSize.Height + 3 * PanelHeaderVerticalPadding)); 
                return new Size(newWidth + 2, newHeight + 1);
            } 
 
            private void OnFormActivated(object sender, EventArgs e) {
                // 
                _formActive = true;
                ActionPanel.Invalidate();
                //ActionPanel.Invalidate(new Rectangle(EditRegionLocation, EditRegionSize), false);
            } 

            private void OnFormDeactivate(object sender, EventArgs e) { 
                // 
                _formActive = false;
                ActionPanel.Invalidate(); 
            }

            private void OnParentControlFontChanged(object sender, EventArgs e) {
                if(_titleLabel != null && _subtitleLabel != null) { 
                    _titleLabel.Font = new Font(ActionPanel.Font, FontStyle.Bold);
                    _subtitleLabel.Font = ActionPanel.Font; 
                } 
            }
 
            public override void PaintLine(Graphics g, int lineWidth, int lineHeight) {
                Color backColor = (_formActive || ActionPanel.DropDownActive) ? backColor = ActionPanel.TitleBarColor : ActionPanel.TitleBarUnselectedColor;

                using (SolidBrush b = new SolidBrush(backColor)) { 
                    g.FillRectangle(b, 1, 1, lineWidth - 2, lineHeight - 1);
                } 
 
                // Paint a line under the title label
                using (Pen p = new Pen(ActionPanel.BorderColor)) { 
                    g.DrawLine(p, 0, lineHeight - 1, lineWidth, lineHeight - 1);
                }
            }
 
            internal override void UpdateActionItem(DesignerActionList actionList, DesignerActionItem actionItem, ToolTip toolTip, ref int currentTabIndex) {
                _actionList = actionList; 
                _panelHeaderItem = (DesignerActionPanelHeaderItem)actionItem; 

                _titleLabel.Text = _panelHeaderItem.DisplayName; 
                _titleLabel.TabIndex = currentTabIndex++;
                _subtitleLabel.Text = _panelHeaderItem.Subtitle;
                _subtitleLabel.TabIndex = currentTabIndex++;
                _subtitleLabel.Visible = (_subtitleLabel.Text.Length != 0); 

                // Force the font to update 
                OnParentControlFontChanged(null, EventArgs.Empty); 
            }
        } 

        private sealed class MethodLine : Line {
            private DesignerActionList _actionList;
            private DesignerActionMethodItem _methodItem; 

            private MethodItemLinkLabel _linkLabel; 
 
            public MethodLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel)
                : base(serviceProvider, actionPanel) { 
            }

            public sealed override string FocusId {
                get { 
                    return "METHOD:" + _actionList.GetType().FullName + "." + _methodItem.MemberName;
                } 
            } 

            protected override void AddControls(List controls) { 
                _linkLabel = new MethodItemLinkLabel();
                _linkLabel.ActiveLinkColor = ActionPanel.ActiveLinkColor;
                _linkLabel.AutoSize = false;
                _linkLabel.BackColor = Color.Transparent; 
                _linkLabel.LinkBehavior = LinkBehavior.HoverUnderline;
                _linkLabel.LinkColor = ActionPanel.LinkColor; 
                _linkLabel.TextAlign = ContentAlignment.MiddleLeft; 
                _linkLabel.UseMnemonic = false;
                _linkLabel.VisitedLinkColor = ActionPanel.LinkColor; 
                _linkLabel.LinkClicked += new LinkLabelLinkClickedEventHandler(OnLinkLabelLinkClicked);

                controls.Add(_linkLabel);
            } 

            public sealed override void Focus() { 
                _linkLabel.Focus(); 
            }
 
            public override Size LayoutControls(int top, int width, bool measureOnly) {
                Size linkLabelSize = _linkLabel.GetPreferredSize(new Size(Int32.MaxValue, Int32.MaxValue));

                if (!measureOnly) { 
                    _linkLabel.Location = new Point(LineLeftMargin, top + LineVerticalPadding / 2);
                    _linkLabel.Size = linkLabelSize; 
                } 

                return linkLabelSize + new Size(LineLeftMargin + LineRightMargin, LineVerticalPadding); 
            }

            [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
            [SuppressMessage("Microsoft.Security", "CA2102:CatchNonClsCompliantExceptionsInGeneralHandlers")] 
            private void OnLinkLabelLinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
                Debug.Assert(!ActionPanel.InMethodInvoke, "Nested method invocation"); 
                ActionPanel.InMethodInvoke = true; 
                try {
                    _methodItem.Invoke(); 
                }
                catch (Exception ex) {
                    if (ex is TargetInvocationException) {
                        ex = ex.InnerException; 
                    }
                    //NOTE: We had code to rethrow if this was one of [NullReferenceException, StackOverflowException, OutOfMemoryException, 
                    //ThreadAbortException].  Removing this rethrow.  StackOverflow and ThreadAbort can't be meaningfully caught, and 
                    //NullRef and OutOfMemory really shouldn't be caught.  Out of these, OOM is the most correct one to call, but OOM is
                    //thrown by GDI+ for pretty much any problem, so isn't reliable as an actual indicator that you're out of memory.  If 
                    //you really are out of memory, it's very likely you'll get another OOM shortly.
                    ActionPanel.ShowError(SR.GetString(SR.DesignerActionPanel_ErrorInvokingAction, _methodItem.DisplayName, Environment.NewLine + ex.Message));
                }
                finally { 
                    ActionPanel.InMethodInvoke = false;
                } 
            } 

            internal override void UpdateActionItem(DesignerActionList actionList, DesignerActionItem actionItem, ToolTip toolTip, ref int currentTabIndex) { 
                _actionList = actionList;
                _methodItem = (DesignerActionMethodItem)actionItem;

                toolTip.SetToolTip(_linkLabel, _methodItem.Description); 

                _linkLabel.Text = StripAmpersands(_methodItem.DisplayName); 
                _linkLabel.AccessibleDescription = actionItem.Description; 
                _linkLabel.TabIndex = currentTabIndex++;
            } 

            private sealed class MethodItemLinkLabel : LinkLabel {
                protected override bool ProcessDialogKey(Keys keyData) {
                    if ((keyData & Keys.Control) == Keys.Control) { 
                        Keys keyCode = keyData & Keys.KeyCode;
                        switch (keyCode) { 
                            case Keys.Tab: 
                                // We specifically ignore Ctrl+Tab because it prevents the window
                                // switcher dialog from showing up in VS. Normally the key combination 
                                // is only needed when a LinkLabel contains multiple links, but that
                                // can't happen inside the DesignerActionPanel.
                                return false;
                        } 
                    }
                    return base.ProcessDialogKey(keyData); 
                } 
            }
        } 

        private abstract class PropertyLine : Line {
            private DesignerActionList _actionList;
            private DesignerActionPropertyItem _propertyItem; 

            private object _value; 
            private bool _pushingValue; 
            private PropertyDescriptor _propDesc;
            private ITypeDescriptorContext _typeDescriptorContext; 

            public PropertyLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel)
                : base(serviceProvider, actionPanel) {
            } 

            public sealed override string FocusId { 
                get { 
                    return "PROPERTY:" + _actionList.GetType().FullName + "." + _propertyItem.MemberName;
                } 
            }

            protected PropertyDescriptor PropertyDescriptor {
                get { 
                    if (_propDesc == null) {
                        _propDesc = TypeDescriptor.GetProperties(_actionList)[_propertyItem.MemberName]; 
                    } 

                    return _propDesc; 
                }
            }

            protected DesignerActionPropertyItem PropertyItem { 
                get {
                    return _propertyItem; 
                } 
            }
 
            protected ITypeDescriptorContext TypeDescriptorContext {
                get {
                    if (_typeDescriptorContext == null) {
                        _typeDescriptorContext = new TypeDescriptorContext(ServiceProvider, PropertyDescriptor, _actionList); 
                    }
 
                    return _typeDescriptorContext; 
                }
            } 

            protected object Value {
                get {
                    return _value; 
                }
            } 
 
            protected abstract void OnPropertyTaskItemUpdated(ToolTip toolTip, ref int currentTabIndex);
 
            protected abstract void OnValueChanged();

            [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
            protected void SetValue(object newValue) { 
                if (_pushingValue || ActionPanel.DropDownActive) {
                    return; 
                } 

                _pushingValue = true; 

#if MVWASSEMBLY
                ActionPanel.InPushingValue = true;
#endif 
                try {
                    // Only push the change if the values are different 
                    if (newValue != null) { 
                        Type valueType = newValue.GetType();
                        // If it's not assignable, try to convert it 
                        if (!PropertyDescriptor.PropertyType.IsAssignableFrom(valueType)) {
                            if (PropertyDescriptor.Converter != null) {
                                // If we can't convert it, show an error
                                if (!PropertyDescriptor.Converter.CanConvertFrom(_typeDescriptorContext, valueType)) { 
                                    ActionPanel.ShowError(SR.GetString(SR.DesignerActionPanel_CouldNotConvertValue, newValue, _propDesc.PropertyType));
                                    return; 
                                } 
                                else {
                                    newValue = PropertyDescriptor.Converter.ConvertFrom(_typeDescriptorContext, CultureInfo.CurrentCulture, newValue); 
                                }
                            }
                        }
                    } 
                    if (!Object.Equals(_value, newValue)) {
                        PropertyDescriptor.SetValue(_actionList, newValue); 
 
                        // Update the value we're caching
                        _value = PropertyDescriptor.GetValue(_actionList); 

                        OnValueChanged();
                    }
                } 
                catch (Exception e) {
                    if (e is TargetInvocationException) { 
                        e = e.InnerException; 
                    }
                    ActionPanel.ShowError(SR.GetString(SR.DesignerActionPanel_ErrorSettingValue, newValue, PropertyDescriptor.Name, e.Message)); 
                }
                catch {
                    //Not a critical exception
                } 
                finally {
                    _pushingValue = false; 
 
#if MVWASSEMBLY
                    ActionPanel.InPushingValue = false; 
#endif
                }
            }
 
            internal sealed override void UpdateActionItem(DesignerActionList actionList, DesignerActionItem actionItem, ToolTip toolTip, ref int currentTabIndex) {
                _actionList = actionList; 
                _propertyItem = (DesignerActionPropertyItem)actionItem; 

                _propDesc = null; 
                _typeDescriptorContext = null;

                _value = PropertyDescriptor.GetValue(actionList);
 
                OnPropertyTaskItemUpdated(toolTip, ref currentTabIndex);
 
                _pushingValue = true; 

#if MVWASSEMBLY 
                ActionPanel.InPushingValue = true;
#endif
                try {
                    OnValueChanged(); 
                }
                finally { 
                    _pushingValue = false; 

#if MVWASSEMBLY 
                    ActionPanel.InPushingValue = false;
#endif
                }
            } 
        }
 
        private sealed class CheckBoxPropertyLine : PropertyLine { 
            private CheckBox _checkBox;
 
            public CheckBoxPropertyLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel)
                : base(serviceProvider, actionPanel) {
            }
 
            protected override void AddControls(List controls) {
                _checkBox = new CheckBox(); 
                _checkBox.BackColor = Color.Transparent; 
                _checkBox.CheckAlign = ContentAlignment.MiddleLeft;
                _checkBox.CheckedChanged += new EventHandler(OnCheckBoxCheckedChanged); 
                _checkBox.TextAlign = ContentAlignment.MiddleLeft;
                _checkBox.UseMnemonic = false;

                controls.Add(_checkBox); 
            }
 
            public sealed override void Focus() { 
                _checkBox.Focus();
            } 

            public override Size LayoutControls(int top, int width, bool measureOnly) {
                Size checkBoxPreferredSize = _checkBox.GetPreferredSize(new Size(Int32.MaxValue, Int32.MaxValue));
 
                if (!measureOnly) {
                    _checkBox.Location = new Point(LineLeftMargin, top + LineVerticalPadding / 2); 
                    _checkBox.Size = checkBoxPreferredSize; 
                }
 
                return checkBoxPreferredSize + new Size(LineLeftMargin + LineRightMargin, LineVerticalPadding);
            }

            private void OnCheckBoxCheckedChanged(object sender, EventArgs e) { 
                SetValue(_checkBox.Checked);
            } 
 
            protected override void OnPropertyTaskItemUpdated(ToolTip toolTip, ref int currentTabIndex) {
                _checkBox.Text = StripAmpersands(PropertyItem.DisplayName); 
                _checkBox.AccessibleDescription = PropertyItem.Description;
                _checkBox.TabIndex = currentTabIndex++;

                toolTip.SetToolTip(_checkBox, PropertyItem.Description); 
            }
 
            protected override void OnValueChanged() { 
                _checkBox.Checked = (bool)Value;
            } 
        }

        private class TextBoxPropertyLine : PropertyLine {
            private TextBox _textBox; 
            private EditorLabel _readOnlyTextBoxLabel;
            private Control _editControl; 
            private Label _label; 

            private int _editXPos; 
            private bool _textBoxDirty;

            private Point _editRegionLocation;
            private Point _editRegionRelativeLocation; 
            private Size _editRegionSize;
 
            public TextBoxPropertyLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel) 
                : base(serviceProvider, actionPanel) {
            } 

            protected Control EditControl {
                get {
                    return _editControl; 
                }
            } 
 
            protected Point EditRegionLocation {
                get { 
                    return _editRegionLocation;
                }
            }
 
            protected Point EditRegionRelativeLocation {
                get { 
                    return _editRegionRelativeLocation; 
                }
            } 

            protected Size EditRegionSize {
                get {
                    return _editRegionSize; 
                }
            } 
 
            protected override void AddControls(List controls) {
                _label = new Label(); 
                _label.BackColor = Color.Transparent;
                _label.TextAlign = ContentAlignment.MiddleLeft;
                _label.UseMnemonic = false;
 
                _readOnlyTextBoxLabel = new EditorLabel();
                _readOnlyTextBoxLabel.BackColor = Color.Transparent; 
                _readOnlyTextBoxLabel.TabStop = true; 
                _readOnlyTextBoxLabel.TextAlign = ContentAlignment.TopLeft;
                _readOnlyTextBoxLabel.UseMnemonic = false; 
                _readOnlyTextBoxLabel.Visible = false;
                _readOnlyTextBoxLabel.MouseClick += new MouseEventHandler(OnReadOnlyTextBoxLabelClick);
                _readOnlyTextBoxLabel.Enter += new EventHandler(OnReadOnlyTextBoxLabelEnter);
                _readOnlyTextBoxLabel.Leave += new EventHandler(OnReadOnlyTextBoxLabelLeave); 
                _readOnlyTextBoxLabel.KeyDown += new KeyEventHandler(OnReadOnlyTextBoxLabelKeyDown);
 
                _textBox = new TextBox(); 
                _textBox.BorderStyle = BorderStyle.None;
                _textBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Left; 
                _textBox.Visible = false;
                _textBox.TextChanged += new EventHandler(OnTextBoxTextChanged);
                _textBox.KeyDown += new KeyEventHandler(OnTextBoxKeyDown);
                _textBox.LostFocus += new EventHandler(OnTextBoxLostFocus); 

                controls.Add(_readOnlyTextBoxLabel); 
                controls.Add(_textBox); 
                controls.Add(_label);
            } 

            public sealed override void Focus() {
                _editControl.Focus();
            } 

            internal int GetEditRegionXPos() { 
                if (String.IsNullOrEmpty(_label.Text)) { 
                    return LineLeftMargin;
                } 
                return LineLeftMargin + _label.GetPreferredSize(new Size(Int32.MaxValue, Int32.MaxValue)).Width + TextBoxLineCenterMargin;
            }

            protected virtual int GetTextBoxLeftPadding(int textBoxHeight) { 
                return TextBoxLineInnerPadding;
            } 
 
            protected virtual int GetTextBoxRightPadding(int textBoxHeight) {
                return TextBoxLineInnerPadding; 
            }

            public override Size LayoutControls(int top, int width, bool measureOnly) {
                // Figure out our minimum width 
                // Compare to proposed width
                // If we are smaller, widen the textbox to fit the line based on the bonus 
 
                int textBoxPreferredHeight = _textBox.GetPreferredSize(new Size(Int32.MaxValue, Int32.MaxValue)).Height;
                textBoxPreferredHeight += TextBoxHeightFixup; 
                int height = textBoxPreferredHeight + LineVerticalPadding + TextBoxLineInnerPadding * 2 + 2; // 2 == border size

                int editRegionXPos = Math.Max(_editXPos, GetEditRegionXPos());
 
                int minimumWidth = editRegionXPos + EditInputWidth + LineRightMargin;
                width = Math.Max(width, minimumWidth); 
                int textBoxWidthBonus = width - minimumWidth; 

                if (!measureOnly) { 
                    _editRegionLocation = new Point(editRegionXPos, top + TextBoxTopPadding);
                    _editRegionRelativeLocation = new Point(editRegionXPos, TextBoxTopPadding);
                    _editRegionSize = new Size(EditInputWidth + textBoxWidthBonus, textBoxPreferredHeight + TextBoxLineInnerPadding * 2);
 
                    _label.Location = new Point(LineLeftMargin, top);
                    int labelPreferredWidth = _label.GetPreferredSize(new Size(Int32.MaxValue, Int32.MaxValue)).Width; 
                    _label.Size = new Size(labelPreferredWidth, height); 

                    int specialPadding = 0; 
                    if (_editControl is TextBox) {
                        specialPadding = 2;
                    }
                    _editControl.Location = new Point(_editRegionLocation.X + GetTextBoxLeftPadding(textBoxPreferredHeight) + 1 + specialPadding, _editRegionLocation.Y + TextBoxLineInnerPadding + 1); 
                    _editControl.Width = _editRegionSize.Width - GetTextBoxRightPadding(textBoxPreferredHeight) - GetTextBoxLeftPadding(textBoxPreferredHeight) - specialPadding;
                    _editControl.Height = _editRegionSize.Height - TextBoxLineInnerPadding * 2 - 1; 
                } 

                return new Size(width, height); 
            }

            protected virtual bool IsReadOnly() {
                return IsReadOnlyProperty(PropertyDescriptor); 
            }
 
            protected override void OnPropertyTaskItemUpdated(ToolTip toolTip, ref int currentTabIndex) { 
                _label.Text = StripAmpersands(PropertyItem.DisplayName);
                _label.TabIndex = currentTabIndex++; 
                toolTip.SetToolTip(_label, PropertyItem.Description);

                _textBoxDirty = false;
 
                if (IsReadOnly()) {
                    _readOnlyTextBoxLabel.Visible = true; 
 
                    _textBox.Visible = false;
                    // 
                    _textBox.Location = new Point(Int32.MaxValue, Int32.MaxValue);

                    _editControl = _readOnlyTextBoxLabel;
                } 
                else {
                    _readOnlyTextBoxLabel.Visible = false; 
                    // 
                    _readOnlyTextBoxLabel.Location = new Point(Int32.MaxValue, Int32.MaxValue);
 
                    _textBox.Visible = true;

                    _editControl = _textBox;
                } 
                _editControl.AccessibleDescription = PropertyItem.Description;
                _editControl.AccessibleName = StripAmpersands(PropertyItem.DisplayName); 
                _editControl.TabIndex = currentTabIndex++; 

                _editControl.BringToFront(); 
            }

            protected virtual void OnReadOnlyTextBoxLabelClick(object sender, MouseEventArgs e) {
                if (e.Button == MouseButtons.Left) { 
                    Focus();
                } 
            } 

            private void OnReadOnlyTextBoxLabelEnter(object sender, EventArgs e) { 
                _readOnlyTextBoxLabel.ForeColor = SystemColors.HighlightText;
                _readOnlyTextBoxLabel.BackColor = SystemColors.Highlight;
            }
 
            private void OnReadOnlyTextBoxLabelLeave(object sender, EventArgs e) {
                _readOnlyTextBoxLabel.ForeColor = SystemColors.WindowText; 
                _readOnlyTextBoxLabel.BackColor = SystemColors.Window; 
            }
 
            protected TypeConverter.StandardValuesCollection GetStandardValues() {
                TypeConverter converter = PropertyDescriptor.Converter;
                if (converter != null &&
                    converter.GetStandardValuesSupported(TypeDescriptorContext)) { 
                    return converter.GetStandardValues(TypeDescriptorContext);
                } 
                return null; 
            }
 
            private void OnEditControlKeyDown(KeyEventArgs e) {
                if (e.KeyCode == Keys.Down) {
                    e.Handled = true;
                    // Try to find the existing value and then pick the one after it 
                    TypeConverter.StandardValuesCollection standardValues = GetStandardValues();
                    if (standardValues != null) { 
                        for (int i = 0; i < standardValues.Count; i++) { 
                            if (Object.Equals(Value, standardValues[i])) {
                                if (i < standardValues.Count - 1) { 
                                    SetValue(standardValues[i + 1]);
                                }
                                return;
                            } 
                        }
                        // Previous value wasn't found, select the first one by default 
                        if (standardValues.Count > 0) { 
                            SetValue(standardValues[0]);
                        } 
                    }
                    return;
                }
 
                if (e.KeyCode == Keys.Up) {
                    e.Handled = true; 
                    // Try to find the existing value and then pick the one before it 
                    TypeConverter.StandardValuesCollection standardValues = GetStandardValues();
                    if (standardValues != null) { 
                        for (int i = 0; i < standardValues.Count; i++) {
                            if (Object.Equals(Value, standardValues[i])) {
                                if (i > 0) {
                                    SetValue(standardValues[i - 1]); 
                                }
                                return; 
                            } 
                        }
                        // Previous value wasn't found, select the first one by default 
                        if (standardValues.Count > 0) {
                            SetValue(standardValues[standardValues.Count - 1]);
                        }
                    } 
                    return;
                } 
            } 

            private void OnReadOnlyTextBoxLabelKeyDown(object sender, KeyEventArgs e) { 
                // Delegate the rest of the processing to a common helper
                OnEditControlKeyDown(e);
            }
 
            private void OnTextBoxKeyDown(object sender, KeyEventArgs e) {
                if (ActionPanel.DropDownActive) { 
                    return; 
                }
 
                if (e.KeyCode == Keys.Enter) {
                    UpdateValue();
                    e.Handled = true;
                    return; 
                }
 
                // Delegate the rest of the processing to a common helper 
                OnEditControlKeyDown(e);
            } 

            private void OnTextBoxLostFocus(object sender, EventArgs e) {
                if (ActionPanel.DropDownActive) {
                    return; 
                }
 
                UpdateValue(); 
            }
 
            private void OnTextBoxTextChanged(object sender, EventArgs e) {
                _textBoxDirty = true;
            }
 
            protected override void OnValueChanged() {
                _editControl.Text = PropertyDescriptor.Converter.ConvertToString(TypeDescriptorContext, Value); 
            } 

            public override void PaintLine(Graphics g, int lineWidth, int lineHeight) { 
                Rectangle editRect = new Rectangle(EditRegionRelativeLocation, EditRegionSize);
                g.FillRectangle(SystemBrushes.Window, editRect);
                g.DrawRectangle(SystemPens.ControlDark, editRect);
            } 

            internal void SetEditRegionXPos(int xPos) { 
                // Ignore the x-position if we have no text. This allows the textbox 
                // to span the entire width of the panel.
                if (!String.IsNullOrEmpty(_label.Text)) { 
                    _editXPos = xPos;
                }
                else {
                    _editXPos = LineLeftMargin; 
                }
            } 
 
            private void UpdateValue() {
                if (_textBoxDirty) { 
                    SetValue(_editControl.Text);
                    _textBoxDirty = false;
                }
            } 

            ///  
            /// Custom label that provides accurate accessibility information and focus abilities. 
            /// 
            private sealed class EditorLabel : Label { 
                public EditorLabel() {
                    SetStyle(ControlStyles.Selectable, true);
                }
 
                protected override AccessibleObject CreateAccessibilityInstance() {
                    return new EditorLabelAccessibleObject(this); 
                } 

                protected override void OnGotFocus(EventArgs e) { 
                    base.OnGotFocus(e);
                    // Since we are not a standard focusable control, we have to raise
                    // our own accessibility events.
                    // objectID = OBJID_WINDOW 
                    // childID = CHILDID_SELF - 1 (the -1 is because WinForms always adds 1 to the value)
                    // (these consts are defined in winuser.h) 
                    AccessibilityNotifyClients(AccessibleEvents.Focus, 0, -1); 
                }
 
                protected override bool IsInputKey(Keys keyData) {
                    if (keyData == Keys.Down ||
                        keyData == Keys.Up) {
                        return true; 
                    }
                    return base.IsInputKey(keyData); 
                } 

                private sealed class EditorLabelAccessibleObject : ControlAccessibleObject { 
                    public EditorLabelAccessibleObject(EditorLabel owner)
                        : base(owner) {
                    }
 
                    public override string Value {
                        get { 
                            return Owner.Text; 
                        }
                    } 
                }
            }
        }
 
        private sealed class EditorPropertyLine : TextBoxPropertyLine, IWindowsFormsEditorService, IServiceProvider {
            private EditorButton _button; 
            private UITypeEditor _editor; 

            private bool _hasSwatch; 
            private Image _swatch;
            private FlyoutDialog _dropDownHolder;

            private bool _ignoreNextSelectChange = false; 
            private bool _ignoreDropDownValue;
 
            public EditorPropertyLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel) 
                : base(serviceProvider, actionPanel) {
            } 

            [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
            private void ActivateDropDown() {
                if (_editor != null) { 
                    try {
                        object newValue = _editor.EditValue(TypeDescriptorContext, this, Value); 
                        SetValue(newValue); 
                    }
                    catch (Exception ex) { 
                        ActionPanel.ShowError(SR.GetString(SR.DesignerActionPanel_ErrorActivatingDropDown, ex.Message));
                    }
                }
                else { 
                    ListBox listBox = new ListBox();
                    listBox.BorderStyle = BorderStyle.None; 
                    listBox.IntegralHeight = false; 
                    listBox.Font = ActionPanel.Font;
                    listBox.SelectedIndexChanged += new EventHandler(OnListBoxSelectedIndexChanged); 
                    listBox.KeyDown += new KeyEventHandler(OnListBoxKeyDown);

                    TypeConverter.StandardValuesCollection standardValues = GetStandardValues();
                    if (standardValues != null) { 
                        foreach (object o in standardValues) {
                            string newItem = PropertyDescriptor.Converter.ConvertToString(TypeDescriptorContext, CultureInfo.CurrentCulture, o); 
                            listBox.Items.Add(newItem); 

                            if ((o != null) && o.Equals(Value)) { 
                                listBox.SelectedItem = newItem;
                            }
                        }
                    } 

 
                    // All measurement code borrowed from WinForms PropertyGridView.cs 
                    int maxWidth = 0;
 
                    // The listbox draws with GDI, not GDI+.  So, we
                    // use a normal DC here.
                    IntPtr hdc = UnsafeNativeMethods.GetDC(new HandleRef(listBox, listBox.Handle));
                    IntPtr hFont = listBox.Font.ToHfont(); 
                    NativeMethods.CommonHandles.GdiHandleCollector.Add();
                    NativeMethods.TEXTMETRIC tm = new NativeMethods.TEXTMETRIC(); 
                    try { 
                        hFont = SafeNativeMethods.SelectObject(new HandleRef(listBox, hdc), new HandleRef(listBox.Font, hFont));
 
                        if (listBox.Items.Count > 0) {
                            NativeMethods.SIZE textSize = new NativeMethods.SIZE();

                            foreach (string s in listBox.Items) { 
                                SafeNativeMethods.GetTextExtentPoint32(new HandleRef(listBox, hdc), s, s.Length, textSize);
                                maxWidth = Math.Max((int)textSize.cx, maxWidth); 
                            } 
                        }
                        SafeNativeMethods.GetTextMetrics(new HandleRef(listBox, hdc), ref tm); 

                        // border + padding + scrollbar
                        maxWidth += 2 + tm.tmMaxCharWidth + SystemInformation.VerticalScrollBarWidth;
 
                        hFont = SafeNativeMethods.SelectObject(new HandleRef(listBox, hdc), new HandleRef(listBox.Font, hFont));
                    } 
                    finally { 
                        SafeNativeMethods.DeleteObject(new HandleRef(listBox.Font, hFont));
                        UnsafeNativeMethods.ReleaseDC(new HandleRef(listBox, listBox.Handle), new HandleRef(listBox, hdc)); 
                    }

                    listBox.Height = Math.Max(tm.tmHeight + 2, Math.Min(ListBoxMaximumHeight, listBox.PreferredHeight));
                    listBox.Width = Math.Max(maxWidth, EditRegionSize.Width); 

 
                    _ignoreDropDownValue = false; 

                    try { 
                        ShowDropDown(listBox, SystemColors.ControlDark);
                    }
                    finally {
                        listBox.SelectedIndexChanged -= new EventHandler(OnListBoxSelectedIndexChanged); 
                        listBox.KeyDown -= new KeyEventHandler(OnListBoxKeyDown);
                    } 
 
                    if (!_ignoreDropDownValue) {
                        if (listBox.SelectedItem != null) { 
                            SetValue(listBox.SelectedItem);
                        }
                    }
                } 
            }
 
            protected override void AddControls(List controls) { 
                base.AddControls(controls);
 
                _button = new EditorButton();
                _button.Click += new EventHandler(OnButtonClick);
                _button.GotFocus += new EventHandler(OnButtonGotFocus);
 
                controls.Add(_button);
            } 
 
            private void CloseDropDown() {
                if (_dropDownHolder != null) { 
                    _dropDownHolder.Visible = false;
                }
            }
 
            protected override int GetTextBoxLeftPadding(int textBoxHeight) {
                if (_hasSwatch) { 
                    return base.GetTextBoxLeftPadding(textBoxHeight) + textBoxHeight + 2 * EditorLineSwatchPadding; 
                }
                else { 
                    return base.GetTextBoxLeftPadding(textBoxHeight);
                }
            }
 
            protected override int GetTextBoxRightPadding(int textBoxHeight) {
                return base.GetTextBoxRightPadding(textBoxHeight) + textBoxHeight + 2 * EditorLineButtonPadding; 
            } 

            protected override bool IsReadOnly() { 
                if (base.IsReadOnly()) {
                    return true;
                }
 
                // If we can't convert from string, we are readonly because we can't convert the user's input
                bool converterReadOnly = !PropertyDescriptor.Converter.CanConvertFrom(TypeDescriptorContext, typeof(string)); 
 
                // If standard values are supported and are exclusive, we are readonly
                bool standardValuesExclusive = 
                    PropertyDescriptor.Converter.GetStandardValuesSupported(TypeDescriptorContext) &&
                    PropertyDescriptor.Converter.GetStandardValuesExclusive(TypeDescriptorContext);

                return converterReadOnly || standardValuesExclusive; 
            }
 
            public override Size LayoutControls(int top, int width, bool measureOnly) { 
                Size size = base.LayoutControls(top, width, measureOnly);
 
                if (!measureOnly) {
                    int buttonHeight = EditRegionSize.Height - EditorLineButtonPadding * 2 - 1;
                    _button.Location = new Point(EditRegionLocation.X + EditRegionSize.Width - buttonHeight - EditorLineButtonPadding, EditRegionLocation.Y + EditorLineButtonPadding + 1);
                    _button.Size = new Size(buttonHeight, buttonHeight); 
                }
 
                return size; 
            }
 
            private void OnButtonClick(object sender, EventArgs e) {
                ActivateDropDown();
            }
 
            private void OnButtonGotFocus(object sender, EventArgs e) {
                if (!_button.Ellipsis) { 
                    Focus(); 
                }
            } 

            private void OnListBoxKeyDown(object sender, KeyEventArgs e) {
                // Always respect the enter key and F4
                if (e.KeyData == Keys.Enter) { 
                    _ignoreNextSelectChange = false;
                    CloseDropDown(); 
                    e.Handled = true; 
                }
                else { 
                    // Ignore selected index change events when the user is navigating via the keyboard
                    _ignoreNextSelectChange = true;
                }
            } 

            private void OnListBoxSelectedIndexChanged(object sender, EventArgs e) { 
                // If we're ignoring this selected index change, do nothing 
                if (_ignoreNextSelectChange) {
                    _ignoreNextSelectChange = false; 
                }
                else {
                    CloseDropDown();
                } 
            }
 
            protected override void OnPropertyTaskItemUpdated(ToolTip toolTip, ref int currentTabIndex) { 
                _editor = (UITypeEditor)PropertyDescriptor.GetEditor(typeof(UITypeEditor));
 
                base.OnPropertyTaskItemUpdated(toolTip, ref currentTabIndex);

                if (_editor != null) {
                    _button.Ellipsis = (_editor.GetEditStyle(TypeDescriptorContext) == UITypeEditorEditStyle.Modal); 
                    _hasSwatch = _editor.GetPaintValueSupported(TypeDescriptorContext);
                } 
                else { 
                    _button.Ellipsis = false;
                } 

                if (_button.Ellipsis) {
                    EditControl.AccessibleRole = (IsReadOnly() ? AccessibleRole.StaticText : AccessibleRole.Text);
                } 
                else {
                    EditControl.AccessibleRole = (IsReadOnly() ? AccessibleRole.DropList : AccessibleRole.ComboBox); 
                } 

                _button.TabStop = _button.Ellipsis; 
                _button.TabIndex = currentTabIndex++;
                _button.AccessibleRole = (_button.Ellipsis ? AccessibleRole.PushButton : AccessibleRole.ButtonDropDown);

                _button.AccessibleDescription = EditControl.AccessibleDescription; 
                _button.AccessibleName = EditControl.AccessibleName;
            } 
 
            protected override void OnReadOnlyTextBoxLabelClick(object sender, MouseEventArgs e) {
                base.OnReadOnlyTextBoxLabelClick(sender, e); 

                if (e.Button == MouseButtons.Left) {
                    bool isDropDown;
                    if (_editor != null) { 
                        isDropDown = (_editor.GetEditStyle(TypeDescriptorContext) == UITypeEditorEditStyle.DropDown);
                    } 
                    else { 
                        isDropDown = true;
                    } 

                    if (ActionPanel.DropDownActive) {
                        _ignoreDropDownValue = true;
                        CloseDropDown(); 
                    }
                    else { 
                        ActivateDropDown(); 
                    }
                } 
            }

            protected override void OnValueChanged() {
                base.OnValueChanged(); 

                _swatch = null; 
                if (_hasSwatch) { 
                    ActionPanel.Invalidate(new Rectangle(EditRegionLocation, EditRegionSize), false);
                } 
            }

            public override void PaintLine(Graphics g, int lineWidth, int lineHeight) {
                base.PaintLine(g, lineWidth, lineHeight); 

                if (_hasSwatch) { 
                    if (_swatch == null) { 
                        int width = EditRegionSize.Height - EditorLineSwatchPadding * 2;
                        int height = width - 1; 
                        _swatch = new Bitmap(width, height);
                        Rectangle rect = new Rectangle(1, 1, width - 2, height - 2);
                        using (Graphics swatchGraphics = Graphics.FromImage(_swatch)) {
                            _editor.PaintValue(Value, swatchGraphics, rect); 
                            swatchGraphics.DrawRectangle(SystemPens.ControlDark, new Rectangle(0, 0, width - 1, height - 1));
                        } 
                    } 

                    g.DrawImage(_swatch, new Point(EditRegionRelativeLocation.X + 2, EditorLineSwatchPadding + 5)); 
                }
            }

            protected internal override bool ProcessDialogKey(Keys keyData) { 
                // Do this here rather than in OnKeyDown because if hierarchy is properly set,
                // VS is going to eat the F4 in PreProcessMessage, preventing it from ever 
                // getting to an OnKeyDown on this control. Doing it here also allow to not 
                // hook up to multiple events for each button.
                if (!_button.Focused && !_button.Ellipsis) { 
                    if (!ActionPanel.DropDownActive) {
                        if ((keyData == (Keys.Alt | Keys.Down)) ||
                            (keyData == (Keys.Alt | Keys.Up)) ||
                            (keyData == Keys.F4)) { 
                            ActivateDropDown();
                            return true; 
                        } 
                    }
                } 

                return base.ProcessDialogKey(keyData);
            }
 
            private void ShowDropDown(Control hostedControl, Color borderColor) {
                hostedControl.Width = Math.Max(hostedControl.Width, EditRegionSize.Width - 2); 
 
                _dropDownHolder = new DropDownHolder(hostedControl, ActionPanel, borderColor, ActionPanel.Font, this);
 
                if (ActionPanel.RightToLeft != RightToLeft.Yes) {
                    Rectangle editorBounds = new Rectangle(Point.Empty, EditRegionSize);
                    Size dropDownSize = _dropDownHolder.Size;
                    Point editorLocation = ActionPanel.PointToScreen(EditRegionLocation); 
                    Rectangle rectScreen = Screen.FromRectangle(ActionPanel.RectangleToScreen(editorBounds)).WorkingArea;
                    dropDownSize.Width = Math.Max(editorBounds.Width + 1, dropDownSize.Width); 
 
                    editorLocation.X = Math.Min(rectScreen.Right - dropDownSize.Width, // min = right screen edge clip
                        Math.Max(rectScreen.X, editorLocation.X + editorBounds.Right - dropDownSize.Width)); // max = left screen edge clip 
                    editorLocation.Y += editorBounds.Y;
                    if (rectScreen.Bottom < (dropDownSize.Height + editorLocation.Y + editorBounds.Height)) {
                        editorLocation.Y -= dropDownSize.Height + 1;
                    } 
                    else {
                        editorLocation.Y += editorBounds.Height; 
                    } 

                    _dropDownHolder.Location = editorLocation; 
                }
                else {
                    _dropDownHolder.RightToLeft = ActionPanel.RightToLeft;
 
                    Rectangle editorBounds = new Rectangle(Point.Empty, EditRegionSize);
                    Size dropDownSize = _dropDownHolder.Size; 
                    Point editorLocation = ActionPanel.PointToScreen(EditRegionLocation); 
                    Rectangle rectScreen = Screen.FromRectangle(ActionPanel.RectangleToScreen(editorBounds)).WorkingArea;
                    dropDownSize.Width = Math.Max(editorBounds.Width + 1, dropDownSize.Width); 

                    editorLocation.X = Math.Min(rectScreen.Right - dropDownSize.Width, // min = right screen edge clip
                        Math.Max(rectScreen.X, editorLocation.X - editorBounds.Width)); // max = left screen edge clip
                    editorLocation.Y += editorBounds.Y; 
                    if (rectScreen.Bottom < (dropDownSize.Height + editorLocation.Y + editorBounds.Height)) {
                        editorLocation.Y -= dropDownSize.Height + 1; 
                    } 
                    else {
                        editorLocation.Y += editorBounds.Height; 
                    }

                    _dropDownHolder.Location = editorLocation;
                } 

                ActionPanel.InMethodInvoke = true; 
                ActionPanel.SetDropDownActive(true); 
                try {
                    _dropDownHolder.ShowDropDown(_button); 
                }
                finally {
                    _button.ResetMouseStates();
                    ActionPanel.SetDropDownActive(false); 
                    ActionPanel.InMethodInvoke = false;
                } 
            } 

            #region IWindowsFormsEditorService implementation 
            void IWindowsFormsEditorService.CloseDropDown() {
                CloseDropDown();
            }
 
            void IWindowsFormsEditorService.DropDownControl(Control control) {
                ShowDropDown(control, ActionPanel.BorderColor); 
            } 

            DialogResult IWindowsFormsEditorService.ShowDialog(Form dialog) { 
                IUIService uiService = (IUIService)ServiceProvider.GetService(typeof(IUIService));
                if (uiService != null) {
                    return uiService.ShowDialog(dialog);
                } 

                return dialog.ShowDialog(); 
            } 
            #endregion
 
            #region IServiceProvider implementation
            object IServiceProvider.GetService(Type serviceType) {
                // Inject this class as the IWindowsFormsEditroService
                // so drop-down custom editors can work 
                if (serviceType == typeof(IWindowsFormsEditorService)) {
                    return this; 
                } 

                return ServiceProvider.GetService(serviceType); 
            }
            #endregion

            private class DropDownHolder : FlyoutDialog { 
                private EditorPropertyLine _parent;
 
                public DropDownHolder(Control hostedControl, Control parentControl, Color borderColor, Font font, EditorPropertyLine parent) 
                    : base(hostedControl, parentControl, borderColor, font) {
                    _parent = parent; 
                    _parent.ActionPanel.SetDropDownActive(true);
                }

                protected override void OnClosed(EventArgs e) { 
                    base.OnClosed(e);
                    _parent.ActionPanel.SetDropDownActive(false); 
                } 

                protected override bool ProcessDialogKey(Keys keyData) { 
                    if (keyData == Keys.Escape) {
                        // Indicates that the selection was aborted so we should ignore the value
                        _parent._ignoreDropDownValue = true;
                        Visible = false; 
                        return true;
                    } 
 
                    return base.ProcessDialogKey(keyData);
                } 
            }

            // Mostly copied from WinForms\Managed\System\WinForms\PropertyGridInternal\PropertyGridView.cs
            internal class FlyoutDialog : Form { 
                private Control _hostedControl;
                private Control _parentControl; 
 
                public FlyoutDialog(Control hostedControl, Control parentControl, Color borderColor, Font font) {
                    _hostedControl = hostedControl; 
                    _parentControl = parentControl;

                    BackColor = SystemColors.Window;
                    ControlBox = false; 
                    Font = font;
                    FormBorderStyle = FormBorderStyle.None; 
                    MinimizeBox = false; 
                    MaximizeBox = false;
                    ShowInTaskbar = false; 
                    StartPosition = FormStartPosition.Manual;
                    Text = String.Empty;

                    SuspendLayout(); 
                    try {
                        Controls.Add(hostedControl); 
 
                        int width = Math.Max(_hostedControl.Width, SystemInformation.MinimumWindowSize.Width);
                        int height = Math.Max(_hostedControl.Height, SystemInformation.MinimizedWindowSize.Height); 
                        if (!borderColor.IsEmpty) {
                            DockPadding.All = 1;
                            BackColor = borderColor;
                            width += 2; 
                            height += 4;
                        } 
                        _hostedControl.Dock = DockStyle.Fill; 

                        Width = width; 
                        Height = height;
                    }
                    finally {
                        ResumeLayout(); 
                    }
                } 
 
                protected override CreateParams CreateParams {
                    get { 
                        CreateParams cp = base.CreateParams;
                        cp.ExStyle |= NativeMethods.WS_EX_TOOLWINDOW;
                        cp.Style |= NativeMethods.WS_POPUP | NativeMethods.WS_BORDER;
                        cp.ClassStyle |= NativeMethods.CS_SAVEBITS; 

                        if (_parentControl != null) { 
                            if (!_parentControl.IsDisposed) { 
                                cp.Parent = _parentControl.Handle;
                            } 
                        }
                        return cp;
                    }
                } 

                public virtual void FocusComponent() { 
                    if (_hostedControl != null && Visible) { 
                        //_hostedControl.FocusInternal();
                        _hostedControl.Focus(); 
                    }
                }

                // Lifted directly from PropertyGridView.DropDownHolder. Less destructive than using ShowDialog(). 
                public void DoModalLoop() {
                    while (Visible) { 
#if MVWASSEMBLY 
                        System.Windows.Forms.Application.DoEvents();
#else 
                        Application.DoEvents();
#endif
                        UnsafeNativeMethods.MsgWaitForMultipleObjects(0, IntPtr.Zero, true, 250, NativeMethods.QS_ALLINPUT);
                    } 
                }
 
                ///  
                ///    General purpose method, based on Control.Contains()...
                /// 
                ///    Determines whether a given window (specified using native window handle)
                ///    is a descendant of this control. This catches both contained descendants
                ///    and 'owned' windows such as modal dialogs. Using window handles rather
                ///    than Control objects allows it to catch un-managed windows as well. 
                /// 
                private bool OwnsWindow(IntPtr hWnd) { 
                    while (hWnd != IntPtr.Zero) { 
                        hWnd = UnsafeNativeMethods.GetWindowLong(new HandleRef(null, hWnd), NativeMethods.GWL_HWNDPARENT);
                        if (hWnd == IntPtr.Zero) { 
                            return false;
                        }
                        if (hWnd == Handle) {
                            return true; 
                        }
                    } 
                    return false; 
                }
 


                protected override bool ProcessDialogKey(Keys keyData) {
                    if ((keyData == (Keys.Alt | Keys.Down)) || 
                        (keyData == (Keys.Alt | Keys.Up)) ||
                        (keyData == Keys.F4)) { 
                        // Any of these keys indicates the selection is accepted 
                        Visible = false;
                        return true; 
                    }

                    return base.ProcessDialogKey(keyData);
                } 

                public void ShowDropDown(Control parent) { 
                    try { 
                        UnsafeNativeMethods.SetWindowLong(new HandleRef(this, Handle), // NOTE: Forces handle creation
                            NativeMethods.GWL_HWNDPARENT, 
                                                        new HandleRef(parent, parent.Handle));

                        // Lifted directly from Form.ShowDialog()...
                        IntPtr hWndCapture = UnsafeNativeMethods.GetCapture(); 
                        if (hWndCapture != IntPtr.Zero) {
                            UnsafeNativeMethods.SendMessage(new HandleRef(null, hWndCapture), NativeMethods.WM_CANCELMODE, 0, 0); 
                            SafeNativeMethods.ReleaseCapture(); 
                        }
 
                        Visible = true; // NOTE: Do this AFTER creating handle and setting parent

                        FocusComponent();
                        DoModalLoop(); 
                    }
                    finally { 
 
                        UnsafeNativeMethods.SetWindowLong(new HandleRef(this, Handle),
                                                        NativeMethods.GWL_HWNDPARENT, 
                                                        new HandleRef(null, IntPtr.Zero));

                        // sometimes activation goes to LALA land - if our parent control is still
                        // around, remind it to take focus. 
                        if (parent != null && parent.Visible) {
                            parent.Focus(); 
                        } 
                    }
                } 

                protected override void WndProc(ref Message m) {
                    if (m.Msg == NativeMethods.WM_ACTIVATE) {
 
                        if(Visible &&
                         NativeMethods.Util.LOWORD((int)m.WParam) == NativeMethods.WA_INACTIVE) { 
 
                            if(!OwnsWindow((IntPtr)m.LParam)) {
                                Visible = false; 
                                if(m.LParam == IntPtr.Zero) { //we 're switching process
                                    // also dismiss the parent
                                    Control toplevel = _parentControl.TopLevelControl;
                                    ToolStripDropDown dropDown = toplevel as ToolStripDropDown; 
                                    if (dropDown != null) {
                                        // if it's a toolstrip dropdown let it know that we have 
                                        // a specific close reason. 
                                        dropDown.Close();
                                    } 
                                    else if (toplevel != null) {
                                        toplevel.Visible = false;
                                    }
                                } 
                                return;
                            } 
                        } 
                    }
 
                    base.WndProc(ref m);
                }
            }
 
            #region Interop definitions
            private static class NativeMethods { 
                public const int WM_ACTIVATE = 0x0006, 
                                 WM_CANCELMODE = 0x001F,
                                 WM_MOUSEACTIVATE = 0x0021, 
                                 WM_NCLBUTTONDOWN = 0x00A1,
                                 WM_NCRBUTTONDOWN = 0x00A4,
                                 WM_NCMBUTTONDOWN = 0x00A7,
                                 WM_LBUTTONDOWN = 0x0201, 
                                 WM_RBUTTONDOWN = 0x0204,
                                 WM_MBUTTONDOWN = 0x0207, 
                                 WA_INACTIVE = 0, 
                                 WA_ACTIVE = 1,
                                 WS_EX_TOOLWINDOW = 0x00000080, 
                                 WS_POPUP = unchecked((int)0x80000000),
                                 WS_BORDER = 0x00800000,
                                 GWL_HWNDPARENT = (-8),
                                 QS_KEY = 0x0001, 
                                 QS_MOUSEMOVE = 0x0002,
                                 QS_MOUSEBUTTON = 0x0004, 
                                 QS_POSTMESSAGE = 0x0008, 
                                 QS_TIMER = 0x0010,
                                 QS_PAINT = 0x0020, 
                                 QS_SENDMESSAGE = 0x0040,
                                 QS_HOTKEY = 0x0080,
                                 QS_ALLPOSTMESSAGE = 0x0100,
                                 QS_MOUSE = QS_MOUSEMOVE | QS_MOUSEBUTTON, 
                                 QS_INPUT = QS_MOUSE | QS_KEY,
                                 QS_ALLEVENTS = QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY, 
                                 QS_ALLINPUT = QS_INPUT | QS_POSTMESSAGE | QS_TIMER | QS_PAINT | QS_HOTKEY | QS_SENDMESSAGE, 
                                 CS_SAVEBITS = 0x0800;
 

                internal static class Util {
                    public static int LOWORD(int n) {
                        return n & 0xffff; 
                    }
                } 
 
                public static class CommonHandles {
                    public static HandleCollector GdiHandleCollector = new HandleCollector("GDI", 500); 
                    public static HandleCollector HdcHandleCollector = new HandleCollector("HDC", 2);
                }

                [StructLayout(LayoutKind.Sequential)] 
                public class SIZE {
                    public int cx=0; 
                    public int cy=0; 

                    public SIZE() { 
                    }
                }

                [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 
                public struct TEXTMETRIC {
                    public int tmHeight; 
                    public int tmAscent; 
                    public int tmDescent;
                    public int tmInternalLeading; 
                    public int tmExternalLeading;
                    public int tmAveCharWidth;
                    public int tmMaxCharWidth;
                    public int tmWeight; 
                    public int tmOverhang;
                    public int tmDigitizedAspectX; 
                    public int tmDigitizedAspectY; 
                    public char tmFirstChar;
                    public char tmLastChar; 
                    public char tmDefaultChar;
                    public char tmBreakChar;
                    public byte tmItalic;
                    public byte tmUnderlined; 
                    public byte tmStruckOut;
                    public byte tmPitchAndFamily; 
                    public byte tmCharSet; 
                }
 
                [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
                public struct TEXTMETRICA {
                    public int tmHeight;
                    public int tmAscent; 
                    public int tmDescent;
                    public int tmInternalLeading; 
                    public int tmExternalLeading; 
                    public int tmAveCharWidth;
                    public int tmMaxCharWidth; 
                    public int tmWeight;
                    public int tmOverhang;
                    public int tmDigitizedAspectX;
                    public int tmDigitizedAspectY; 
                    public byte tmFirstChar;
                    public byte tmLastChar; 
                    public byte tmDefaultChar; 
                    public byte tmBreakChar;
                    public byte tmItalic; 
                    public byte tmUnderlined;
                    public byte tmStruckOut;
                    public byte tmPitchAndFamily;
                    public byte tmCharSet; 
                }
            } 
 
            private static class SafeNativeMethods {
                [DllImport(ExternDllGdi32, SetLastError = true, ExactSpelling = true, EntryPoint = "DeleteObject", CharSet = System.Runtime.InteropServices.CharSet.Auto)] 
                private static extern bool IntDeleteObject(HandleRef hObject);
                public static bool DeleteObject(HandleRef hObject) {
                    NativeMethods.CommonHandles.GdiHandleCollector.Remove();
                    return IntDeleteObject(hObject); 
                }
 
                [DllImport(ExternDllUser32, CharSet = CharSet.Auto)] 
                public static extern bool ReleaseCapture();
 
                [DllImport(ExternDllGdi32, SetLastError = true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
                public static extern IntPtr SelectObject(HandleRef hDC, HandleRef hObject);

                [DllImport(ExternDllGdi32, SetLastError = true, CharSet = System.Runtime.InteropServices.CharSet.Auto)] 
                public static extern int GetTextExtentPoint32(HandleRef hDC, string str, int len, [In, Out] NativeMethods.SIZE size);
 
                [DllImport(ExternDllGdi32, SetLastError = true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Unicode)] 
                public static extern int GetTextMetricsW(HandleRef hDC, [In, Out] ref NativeMethods.TEXTMETRIC lptm);
 
                [DllImport(ExternDllGdi32, SetLastError = true, ExactSpelling = true, CharSet = System.Runtime.InteropServices.CharSet.Ansi)]
                public static extern int GetTextMetricsA(HandleRef hDC, [In, Out] ref NativeMethods.TEXTMETRICA lptm);

                public static int GetTextMetrics(HandleRef hDC, ref NativeMethods.TEXTMETRIC lptm) { 
                    if (Marshal.SystemDefaultCharSize == 1) {
                        // ANSI 
                        NativeMethods.TEXTMETRICA lptmA = new NativeMethods.TEXTMETRICA(); 
                        int retVal = SafeNativeMethods.GetTextMetricsA(hDC, ref lptmA);
 
                        lptm.tmHeight = lptmA.tmHeight;
                        lptm.tmAscent = lptmA.tmAscent;
                        lptm.tmDescent = lptmA.tmDescent;
                        lptm.tmInternalLeading = lptmA.tmInternalLeading; 
                        lptm.tmExternalLeading = lptmA.tmExternalLeading;
                        lptm.tmAveCharWidth = lptmA.tmAveCharWidth; 
                        lptm.tmMaxCharWidth = lptmA.tmMaxCharWidth; 
                        lptm.tmWeight = lptmA.tmWeight;
                        lptm.tmOverhang = lptmA.tmOverhang; 
                        lptm.tmDigitizedAspectX = lptmA.tmDigitizedAspectX;
                        lptm.tmDigitizedAspectY = lptmA.tmDigitizedAspectY;
                        lptm.tmFirstChar = (char)lptmA.tmFirstChar;
                        lptm.tmLastChar = (char)lptmA.tmLastChar; 
                        lptm.tmDefaultChar = (char)lptmA.tmDefaultChar;
                        lptm.tmBreakChar = (char)lptmA.tmBreakChar; 
                        lptm.tmItalic = lptmA.tmItalic; 
                        lptm.tmUnderlined = lptmA.tmUnderlined;
                        lptm.tmStruckOut = lptmA.tmStruckOut; 
                        lptm.tmPitchAndFamily = lptmA.tmPitchAndFamily;
                        lptm.tmCharSet = lptmA.tmCharSet;

                        return retVal; 
                    }
                    else { 
                        // Unicode 
                        return SafeNativeMethods.GetTextMetricsW(hDC, ref lptm);
                    } 
                }
            }

            private static class UnsafeNativeMethods { 
                [DllImport(ExternDllUser32, CharSet = CharSet.Auto)]
                [SuppressMessage("Microsoft.Portability", "CA1901:PInvokeDeclarationsShouldBePortable")] 
                public static extern IntPtr GetWindowLong(HandleRef hWnd, int nIndex); 

                [DllImport(ExternDllUser32, CharSet = CharSet.Auto)] 
                [SuppressMessage("Microsoft.Portability", "CA1901:PInvokeDeclarationsShouldBePortable")]
                public static extern IntPtr SetWindowLong(HandleRef hWnd, int nIndex, HandleRef dwNewLong);

                [DllImport(ExternDllUser32, CharSet = CharSet.Auto)] 
                public static extern int MsgWaitForMultipleObjects(int nCount, IntPtr pHandles, bool fWaitAll, int dwMilliseconds, int dwWakeMask);
 
                [SuppressMessage("Microsoft.Portability", "CA1901:PInvokeDeclarationsShouldBePortable")] 
                [DllImport(ExternDllUser32, CharSet = CharSet.Auto)]
                public static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, int lParam); 

                [DllImport(ExternDllUser32, CharSet = CharSet.Auto)]
                public static extern IntPtr GetCapture();
 
                [DllImport(ExternDllUser32, ExactSpelling = true, EntryPoint = "GetDC", CharSet = CharSet.Auto)]
                private static extern IntPtr IntGetDC(HandleRef hWnd); 
                public static IntPtr GetDC(HandleRef hWnd) { 
                    NativeMethods.CommonHandles.HdcHandleCollector.Add();
                    return IntGetDC(hWnd); 
                }

                [DllImport(ExternDllUser32, ExactSpelling = true, EntryPoint = "ReleaseDC", CharSet = CharSet.Auto)]
                private static extern int IntReleaseDC(HandleRef hWnd, HandleRef hDC); 
                public static int ReleaseDC(HandleRef hWnd, HandleRef hDC) {
                    NativeMethods.CommonHandles.HdcHandleCollector.Remove(); 
                    return IntReleaseDC(hWnd, hDC); 
                }
            } 
            #endregion

            // Class that renders either the ellipsis or dropdown button
            internal sealed class EditorButton : Button { 
                private bool _mouseOver;
                private bool _mouseDown; 
                private bool _ellipsis; 

                protected override void OnMouseDown(MouseEventArgs e) { 
                    base.OnMouseDown(e);

                    if (e.Button == MouseButtons.Left) {
                        _mouseDown = true; 
                    }
                } 
 
                protected override void OnMouseEnter(EventArgs e) {
                    base.OnMouseEnter(e); 
                    _mouseOver = true;
                }

                protected override void OnMouseLeave(EventArgs e) { 
                    base.OnMouseLeave(e);
                    _mouseOver = false; 
                } 

                protected override void OnMouseUp(MouseEventArgs e) { 
                    base.OnMouseUp(e);

                    if (e.Button == MouseButtons.Left) {
                        _mouseDown = false; 
                    }
                } 
 
                public bool Ellipsis {
                    get { 
                        return _ellipsis;
                    }
                    set {
                        _ellipsis = value; 
                    }
                } 
 
                protected override void OnPaint(PaintEventArgs e) {
                    Graphics g = e.Graphics; 

                    if (_ellipsis) {
                        PushButtonState buttonState = PushButtonState.Normal;
                        if (_mouseDown) { 
                            buttonState = PushButtonState.Pressed;
                        } 
                        else if (_mouseOver) { 
                            buttonState = PushButtonState.Hot;
                        } 

                        ButtonRenderer.DrawButton(g, new Rectangle(-1, -1, Width + 2, Height + 2), "�", Font, Focused, buttonState);
                    }
                    else { 
                        if (ComboBoxRenderer.IsSupported) {
                            ComboBoxState state = ComboBoxState.Normal; 
 
                            if (Enabled) {
                                if (_mouseDown) { 
                                    state = ComboBoxState.Pressed;
                                }
                                else if (_mouseOver) {
                                    state = ComboBoxState.Hot; 
                                }
                            } 
                            else { 
                                state = ComboBoxState.Disabled;
                            } 

                            ComboBoxRenderer.DrawDropDownButton(g, new Rectangle(0, 0, Width, Height), state);
                        }
                        else { 
                            PushButtonState buttonState = PushButtonState.Normal;
 
                            if (Enabled) { 
                                if (_mouseDown) {
                                    buttonState = PushButtonState.Pressed; 
                                }
                                else if (_mouseOver) {
                                    buttonState = PushButtonState.Hot;
                                } 
                            }
                            else { 
                                buttonState = PushButtonState.Disabled; 
                            }
 
                            ButtonRenderer.DrawButton(g, new Rectangle(-1, -1, Width + 2, Height + 2), String.Empty, Font, Focused, buttonState);

                            // Draw the arrow icon
                            try { 
                                Icon icon = new Icon(typeof(DesignerActionPanel), "Arrow.ico");
 
                                try { 
                                    Bitmap arrowBitmap = icon.ToBitmap();
 
                                    // Make sure we draw properly under high contrast by re-mapping
                                    // the arrow color to the WindowText color
                                    ImageAttributes attrs = new ImageAttributes();
 
                                    try {
                                        ColorMap cm = new ColorMap(); 
                                        cm.OldColor = Color.Black; 
                                        cm.NewColor = SystemColors.WindowText;
 
                                        attrs.SetRemapTable(new ColorMap[] { cm }, ColorAdjustType.Bitmap);

                                        int imageWidth = arrowBitmap.Width;
                                        int imageHeight = arrowBitmap.Height; 
                                        g.DrawImage(arrowBitmap, new Rectangle((Width - imageWidth + 1) / 2, (Height - imageHeight + 1) / 2, imageWidth, imageHeight),
                                                    0, 0, imageWidth, imageWidth, 
                                                    GraphicsUnit.Pixel, attrs, null, IntPtr.Zero); 
                                    }
 
                                    finally {
                                        if (attrs != null) {
                                            attrs.Dispose();
                                        } 
                                    }
                                } 
 
                                finally {
                                    if (icon != null) { 
                                        icon.Dispose();
                                    }
                                }
                            } 
                            catch {
                            } 
                        } 

                        if (Focused) { 
                            ControlPaint.DrawFocusRectangle(g, new Rectangle(2, 2, Width - 5, Height - 5));
                        }
                    }
                } 

                public void ResetMouseStates() { 
                    _mouseDown = false; 
                    _mouseOver = false;
 
                    Invalidate();
                }
            }
        } 

        private class TextLine : Line { 
            private Label _label; 
            private DesignerActionTextItem _textItem;
 
            public TextLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel)
                : base(serviceProvider, actionPanel) {
                actionPanel.FontChanged += new EventHandler(OnParentControlFontChanged);
            } 

            public sealed override string FocusId { 
                get { 
                    return String.Empty;
                } 
            }

            protected override void AddControls(List controls) {
                _label = new Label(); 
                _label.BackColor = Color.Transparent;
                _label.TextAlign = ContentAlignment.MiddleLeft; 
                _label.UseMnemonic = false; 

                controls.Add(_label); 
            }

            public sealed override void Focus() {
                Debug.Fail("Should never try to focus a TextLine"); 
            }
 
            public override Size LayoutControls(int top, int width, bool measureOnly) { 
                Size labelSize = _label.GetPreferredSize(new Size(Int32.MaxValue, Int32.MaxValue));
 
                if (!measureOnly) {
                    _label.Location = new Point(LineLeftMargin, top + LineVerticalPadding / 2);
                    _label.Size = labelSize;
                } 

                return labelSize + new Size(LineLeftMargin + LineRightMargin, LineVerticalPadding); 
            } 

            private void OnParentControlFontChanged(object sender, EventArgs e) { 
                if (_label.Font != null) {
                    _label.Font = GetFont();
                }
            } 

            protected virtual Font GetFont() { 
                return ActionPanel.Font; 
            }
 
            internal override void UpdateActionItem(DesignerActionList actionList, DesignerActionItem actionItem, ToolTip toolTip, ref int currentTabIndex) {
                _textItem = (DesignerActionTextItem)actionItem;

                _label.Text = StripAmpersands(_textItem.DisplayName); 
                _label.Font = GetFont();
                _label.TabIndex = currentTabIndex++; 
 
                toolTip.SetToolTip(_label, _textItem.Description);
            } 
        }

        private sealed class HeaderLine : TextLine {
            public HeaderLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel) 
                : base(serviceProvider, actionPanel) {
            } 
 
            protected override Font GetFont() {
                return new Font(ActionPanel.Font, FontStyle.Bold); 
            }
        }

        private sealed class SeparatorLine : Line { 
            private bool _isSubSeparator;
 
            public SeparatorLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel) 
                : this(serviceProvider, actionPanel, false) {
            } 

            public SeparatorLine(IServiceProvider serviceProvider, DesignerActionPanel actionPanel, bool isSubSeparator)
                : base(serviceProvider, actionPanel) {
                _isSubSeparator = isSubSeparator; 
            }
 
            public sealed override string FocusId { 
                get {
                    return String.Empty; 
                }
            }

            protected override void AddControls(System.Collections.Generic.List controls) { 
            }
 
            public sealed override void Focus() { 
                Debug.Fail("Should never try to focus a SeparatorLine");
            } 

            public override Size LayoutControls(int top, int width, bool measureOnly) {
                return new Size(MinimumWidth, 1);
            } 

            public override void PaintLine(Graphics g, int lineWidth, int lineHeight) { 
                using (Pen p = new Pen(ActionPanel.SeparatorColor)) { 
                    g.DrawLine(p, SeparatorHorizontalPadding, 0, lineWidth - (SeparatorHorizontalPadding + 1), 0);
                } 
            }

            internal override void UpdateActionItem(DesignerActionList actionList, DesignerActionItem actionItem, ToolTip toolTip, ref int currentTabIndex) {
            } 
        }
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK