// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for details. using System; using System.ComponentModel; using System.Drawing; using System.Windows.Forms; using OpenLiveWriter.Localization.Bidi; namespace OpenLiveWriter.Controls { public class ImageComboBox : ComboBox { /// <summary> /// Required designer variable. /// </summary> private Container components = null; public ImageComboBox(Size imageSize) { DropDownStyle = ComboBoxStyle.DropDownList; DrawMode = DrawMode.OwnerDrawFixed; ItemHeight = CalculateItemHeight(imageSize); } public bool AllowMirroring { get { return _allowMirroring; } set { _allowMirroring = value; } } private bool _allowMirroring = true; /// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose(bool disposing) { if (disposing) { if (components != null) { components.Dispose(); } } base.Dispose(disposing); } protected override void OnDrawItem(DrawItemEventArgs e) { // screen invalid drawing states if (DesignMode || e.Index == -1) return; // get item text and image string itemText = Items[e.Index].ToString(); IComboItem comboItem = (IComboItem)Items[e.Index]; Image itemImage = comboItem.Image; // determine state bool selected = (e.State & DrawItemState.Selected) > 0; // calculate colors Color backColor, textColor; if (selected && Focused) { textColor = SystemColors.ControlText; backColor = Color.FromArgb(50, SystemColors.Highlight); } else { backColor = SystemColors.Window; textColor = SystemColors.ControlText; } Rectangle area = e.Bounds; //overlap issue in RTL builds in the selected box area ONLY if (area.X == 21) { area = ClientRectangle; } BidiGraphics g = new BidiGraphics(e.Graphics, area); // draw background (always paint white over it first) g.FillRectangle(Brushes.White, area); using (SolidBrush solidBrush = new SolidBrush(backColor)) g.FillRectangle(solidBrush, area); // draw icon g.DrawImage(AllowMirroring, itemImage, area.Left + IMAGE_INSET, area.Top + area.Height / 2 - itemImage.Height / 2); // text format and drawing metrics TextFormatFlags ellipsesStringFormat = TextFormatFlags.VerticalCenter | TextFormatFlags.WordBreak | TextFormatFlags.ExpandTabs | TextFormatFlags.WordEllipsis; int leftMargin = IMAGE_INSET + itemImage.Width + TEXT_INSET; // draw title line // post title int titleWidth = area.Right - leftMargin; Rectangle titleRectangle = new Rectangle(area.Left + leftMargin, area.Top, titleWidth, area.Height); g.DrawText( itemText, e.Font, titleRectangle, textColor, ellipsesStringFormat); // separator line if necessary if (!selected && DroppedDown) { using (Pen pen = new Pen(SystemColors.ControlLight)) g.DrawLine(pen, area.Left, area.Bottom - 1, area.Right, area.Bottom - 1); } // focus rectange if necessary e.DrawFocusRectangle(); } private int CalculateItemHeight(Size imageSize) { float fontHeight = Font.GetHeight(); return TOP_INSET + // top-margin Math.Max(Convert.ToInt32(fontHeight), imageSize.Height) + // contentHeight BOTTOM_INSET; // air at bottom } // item metrics private const int TOP_INSET = 2; private const int BOTTOM_INSET = 2; private const int IMAGE_INSET = 3; private const int TEXT_INSET = 5; public interface IComboItem { Image Image { get; } } } }