| File: System\Drawing\Design\ColorEditor.ColorUI.cs | Web Access |
| Project: src\winforms\src\System.Windows.Forms.Design\src\System.Windows.Forms.Design.csproj (System.Windows.Forms.Design) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Reflection; using System.Windows.Forms; using System.Windows.Forms.Design; namespace System.Drawing.Design; public partial class ColorEditor { /// <summary> /// Editor UI for the color editor. /// </summary> private sealed partial class ColorUI : Control { private readonly ColorEditor _editor; private IWindowsFormsEditorService? _edSvc; private object? _value; private ColorEditorTabControl _tabControl; private TabPage _systemTabPage; private TabPage _commonTabPage; private TabPage _paletteTabPage; private ListBox _lbSystem; private ListBox _lbCommon; private ColorPalette _pal; private Color[]? _systemColorConstants; private Color[]? _colorConstants; private Color[]? _customColors; private bool _commonHeightSet; private bool _systemHeightSet; public ColorUI(ColorEditor editor) { _editor = editor; InitializeComponent(); AdjustListBoxItemHeight(); } /// <summary> /// Array of standard colors. /// </summary> private Color[] ColorValues => _colorConstants ??= GetConstants(typeof(Color)); /// <summary> /// Retrieves the array of custom colors for our use. /// </summary> private Color[] CustomColors { get { if (_customColors is null) { _customColors = new Color[ColorPalette.CellsCustom]; for (int i = 0; i < ColorPalette.CellsCustom; i++) { _customColors[i] = Color.White; } } return _customColors; } } /// <summary> /// Allows someone else to close our dropdown. /// </summary> public IWindowsFormsEditorService? EditorService => _edSvc; /// <summary> /// Array of system colors. /// </summary> private Color[] SystemColorValues => _systemColorConstants ??= GetConstants(typeof(SystemColors)); public object? Value => _value; public void End() { _edSvc = null; _value = null; } private void AdjustColorUIHeight() { // Compute the default size for the color UI Size size = _pal.Size; Rectangle rectItemSize = _tabControl.GetTabRect(0); int CMARGIN = 0; Size = new Size(size.Width + 2 * CMARGIN, size.Height + 2 * CMARGIN + rectItemSize.Height); _tabControl.Size = Size; } private void AdjustListBoxItemHeight() { _lbSystem.ItemHeight = Font.Height + 2; _lbCommon.ItemHeight = Font.Height + 2; } /// <summary> /// Takes the given color and looks for an instance in the ColorValues table. /// </summary> private Color GetBestColor(Color color) { Color[] colors = ColorValues; int rgb = color.ToArgb(); for (int i = 0; i < colors.Length; i++) { if (colors[i].ToArgb() == rgb) { return colors[i]; } } return color; } /// <summary> /// Retrieves an array of color constants for the given object. /// </summary> private static Color[] GetConstants(Type enumType) { MethodAttributes attrs = MethodAttributes.Public | MethodAttributes.Static; PropertyInfo[] props = enumType.GetProperties(); List<Color> colorList = []; for (int i = 0; i < props.Length; i++) { PropertyInfo prop = props[i]; if (prop.PropertyType != typeof(Color)) { continue; } MethodInfo? method = prop.GetGetMethod(); if (method is null || (method.Attributes & attrs) != attrs) { continue; } if (prop.GetValue(obj: null, index: null) is not Color outColor) { continue; } colorList.Add(outColor); } return [.. colorList]; } [MemberNotNull( nameof(_tabControl), nameof(_pal), nameof(_paletteTabPage), nameof(_commonTabPage), nameof(_systemTabPage), nameof(_lbSystem), nameof(_lbCommon))] private void InitializeComponent() { _paletteTabPage = new TabPage(SR.ColorEditorPaletteTab); _commonTabPage = new TabPage(SR.ColorEditorStandardTab); _systemTabPage = new TabPage(SR.ColorEditorSystemTab); AccessibleName = SR.ColorEditorAccName; _tabControl = new ColorEditorTabControl(); _tabControl.TabPages.Add(_paletteTabPage); _tabControl.TabPages.Add(_commonTabPage); _tabControl.TabPages.Add(_systemTabPage); _tabControl.TabStop = false; _tabControl.SelectedTab = _systemTabPage; _tabControl.SelectedIndexChanged += OnTabControlSelChange; _tabControl.Dock = DockStyle.Fill; _tabControl.Resize += OnTabControlResize; _lbSystem = new ColorEditorListBox { DrawMode = DrawMode.OwnerDrawFixed, BorderStyle = BorderStyle.FixedSingle, IntegralHeight = false, Sorted = false }; _lbSystem.Click += OnListClick; _lbSystem.DrawItem += OnListDrawItem; _lbSystem.KeyDown += OnListKeyDown; _lbSystem.Dock = DockStyle.Fill; _lbSystem.FontChanged += OnFontChanged; _lbCommon = new ColorEditorListBox { DrawMode = DrawMode.OwnerDrawFixed, BorderStyle = BorderStyle.FixedSingle, IntegralHeight = false, Sorted = false }; _lbCommon.Click += OnListClick; _lbCommon.DrawItem += OnListDrawItem; _lbCommon.KeyDown += OnListKeyDown; _lbCommon.Dock = DockStyle.Fill; Array.Sort(ColorValues, StandardColorComparer.Instance); Array.Sort(SystemColorValues, comparer: new SystemColorComparer()); _lbCommon.Items.Clear(); foreach (Color color in ColorValues) { _lbCommon.Items.Add(color); } _lbSystem.Items.Clear(); foreach (Color color in SystemColorValues) { _lbSystem.Items.Add(color); } _pal = new ColorPalette(this, CustomColors); _pal.Picked += OnPalettePick; _paletteTabPage.Controls.Add(_pal); _systemTabPage.Controls.Add(_lbSystem); _commonTabPage.Controls.Add(_lbCommon); Controls.Add(_tabControl); } protected override void OnGotFocus(EventArgs e) { base.OnGotFocus(e); OnTabControlSelChange(this, EventArgs.Empty); } private void OnFontChanged(object? sender, EventArgs e) { _commonHeightSet = _systemHeightSet = false; } private void OnListClick(object? sender, EventArgs e) { if (sender is ListBox lb && lb.SelectedItem is Color selectedColor) { _value = selectedColor; } _edSvc?.CloseDropDown(); } private void OnListDrawItem(object? sender, DrawItemEventArgs die) { if (sender is not ListBox lb) { return; } Color value = (Color)lb.Items[die.Index]; Font font = Font; if (lb == _lbCommon && !_commonHeightSet) { lb.ItemHeight = lb.Font.Height; _commonHeightSet = true; } else if (lb == _lbSystem && !_systemHeightSet) { lb.ItemHeight = lb.Font.Height; _systemHeightSet = true; } Graphics graphics = die.Graphics; die.DrawBackground(); _editor.PaintValue(value, graphics, new Rectangle(die.Bounds.X + 2, die.Bounds.Y + 2, 22, die.Bounds.Height - 4)); graphics.DrawRectangle(SystemPens.WindowText, new Rectangle(die.Bounds.X + 2, die.Bounds.Y + 2, 22 - 1, die.Bounds.Height - 4 - 1)); Brush foreBrush = new SolidBrush(die.ForeColor); graphics.DrawString(value.Name, font, foreBrush, die.Bounds.X + 26, die.Bounds.Y); foreBrush.Dispose(); } private void OnListKeyDown(object? sender, KeyEventArgs ke) { if (ke.KeyCode == Keys.Return) { OnListClick(sender, EventArgs.Empty); } } private void OnPalettePick(object? sender, EventArgs e) { if (sender is ColorPalette palette) { _value = GetBestColor(palette.SelectedColor); } _edSvc?.CloseDropDown(); } protected override void OnFontChanged(EventArgs e) { base.OnFontChanged(e); AdjustListBoxItemHeight(); AdjustColorUIHeight(); } private void OnTabControlResize(object? sender, EventArgs e) { Rectangle rectTabControl = _tabControl.TabPages[0].ClientRectangle; Rectangle rectItemSize = _tabControl.GetTabRect(1); rectTabControl.Y = 0; rectTabControl.Height -= rectTabControl.Y; int CMARGIN = 2; _lbSystem.SetBounds(CMARGIN, rectTabControl.Y + 2 * CMARGIN, rectTabControl.Width - CMARGIN, _pal.Size.Height - rectItemSize.Height + 2 * CMARGIN); _lbCommon.Bounds = _lbSystem.Bounds; _pal.Location = new Point(0, rectTabControl.Y); } private void OnTabControlSelChange(object? sender, EventArgs e) { TabPage? selectedPage = _tabControl.SelectedTab; if (selectedPage is not null && selectedPage.Controls.Count > 0) { selectedPage.Controls[0].Focus(); } } protected override bool ProcessDialogKey(Keys keyData) { // We treat tab characters as switching tab pages. In most other contexts, // ctrl-tab switches tab pages, but I couldn't get that to work, and besides, // then there would be nothing for tab to do in this editor. if ((keyData & Keys.Alt) == 0 && (keyData & Keys.Control) == 0 && (keyData & Keys.KeyCode) == Keys.Tab) { // Logic taken straight out of TabBase bool forward = (keyData & Keys.Shift) == 0; int sel = _tabControl.SelectedIndex; if (sel != -1) { int count = _tabControl.TabPages.Count; sel = forward ? (sel + 1) % count : (sel + count - 1) % count; _tabControl.SelectedTab = _tabControl.TabPages[sel]; return true; } } return base.ProcessDialogKey(keyData); } public void Start(IWindowsFormsEditorService edSvc, object? value) { _edSvc = edSvc; _value = value; AdjustColorUIHeight(); // Now look for the current color so we can select the proper tab. if (value is not null) { Color[] values = ColorValues; TabPage selectedTab = _paletteTabPage; for (int i = 0; i < values.Length; i++) { if (values[i].Equals(value)) { _lbCommon.SelectedItem = value; selectedTab = _commonTabPage; break; } } if (selectedTab == _paletteTabPage) { values = SystemColorValues; for (int i = 0; i < values.Length; i++) { if (values[i].Equals(value)) { _lbSystem.SelectedItem = value; selectedTab = _systemTabPage; break; } } } _tabControl.SelectedTab = selectedTab; } } } }