/// /// Copyright © 2003-2008 JetBrains s.r.o. /// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder). /// using System; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; using System.Windows.Forms; using JetBrains.Omea.GUIControls; using JetBrains.UI.Interop; using JetBrains.Omea.OpenAPI; namespace JetBrains.Omea { /// /// A clickable vertical button. /// internal class VerticalButton: Control { private IContainer components; private int _angle; private IntPtr _fontHandle; private bool _pressed; private bool _pressing; private bool _hot; private Icon _icon; private Timer _dragOverTimer; private bool _customDrawFailed = false; private GraphicsPath _borderPath; private double _heightMultiplier = 1.0; private ColorScheme _colorScheme; public VerticalButton() { // This call is required by the Windows.Forms Form Designer. InitializeComponent(); SetStyle( ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.SupportsTransparentBackColor | ControlStyles.DoubleBuffer | ControlStyles.ResizeRedraw, true ); SetStyle( ControlStyles.Selectable, false ); CreateVerticalFont(); CreateBorderPath(); } /// /// Clean up any resources being used. /// protected override void Dispose( bool disposing ) { if( disposing ) { if ( _fontHandle != IntPtr.Zero ) { Win32Declarations.DeleteObject( _fontHandle ); _fontHandle = IntPtr.Zero; } if ( _borderPath != null ) { _borderPath.Dispose(); } if(components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.components = new Container(); this._dragOverTimer = new Timer(this.components); // // _dragOverTimer // this._dragOverTimer.Interval = 500; this._dragOverTimer.Tick += new EventHandler(this._dragOverTimer_Tick); // // VerticalButton // this.AllowDrop = true; this.Name = "VerticalButton"; } #endregion public int Angle { get { return _angle; } set { _angle = value; CreateVerticalFont(); } } public Icon Icon { get { return _icon; } set { _icon = value; } } public ColorScheme ColorScheme { get { return _colorScheme; } set { if ( _colorScheme != value ) { _colorScheme = value; Invalidate(); } } } public bool Pressed { get { return _pressed; } set { if ( _pressed != value ) { _pressed = value; Invalidate(); if ( PressedChanged != null ) { PressedChanged( this, EventArgs.Empty ); } } } } public int PreferredHeight { get { using( Graphics g = CreateGraphics() ) { IntPtr hdc = g.GetHdc(); SIZE sz = new SIZE(); Win32Declarations.GetTextExtentPoint32( hdc, Text, Text.Length, ref sz ); g.ReleaseHdc( hdc ); return sz.cx + 26; // 10 px - top space, 10 px - bottom space, 16 px - icon } } } public double HeightMultiplier { get { return _heightMultiplier; } set { _heightMultiplier = value; } } public event EventHandler PressedChanged; private void CreateVerticalFont() { if ( _fontHandle != IntPtr.Zero ) { Win32Declarations.DeleteObject( _fontHandle ); _fontHandle = IntPtr.Zero; } int logPixY; using( Graphics g = CreateGraphics() ) { IntPtr hdc = g.GetHdc(); logPixY = Win32Declarations.GetDeviceCaps( hdc, Win32Declarations.LOGPIXELSY ); g.ReleaseHdc( hdc ); } _fontHandle = Win32Declarations.CreateFont( (int) (-Font.SizeInPoints * logPixY / 72), 0, _angle * 10, 0, Win32Declarations.FW_NORMAL, 0, 0, 0, 0, 0, 0, 0, 0, Font.Name ); } private void CreateBorderPath() { if ( _borderPath != null ) { _borderPath.Dispose(); } _borderPath = GdiPlusTools.BuildRoundRectPath( ClientRectangle ); } protected override void OnFontChanged( EventArgs e ) { base.OnFontChanged( e ); CreateVerticalFont(); } protected override void OnSizeChanged( EventArgs e ) { base.OnSizeChanged( e ); CreateBorderPath(); } protected override void OnPaint( PaintEventArgs e ) { base.OnPaint( e ); if ( _customDrawFailed ) return; try { int left = ClientRectangle.Left; int top = ClientRectangle.Top; int right = ClientRectangle.Right; int bottom = ClientRectangle.Bottom; bool drawPressed = _pressed || ( _pressing && _hot); string backBrushId = drawPressed ? "Sidebar.Button.BackgroundPressed" : "Sidebar.Button.Background"; Brush backBrush = GUIControls.ColorScheme.GetBrush( _colorScheme, backBrushId, ClientRectangle, SystemBrushes.Control ); e.Graphics.FillPath( backBrush, _borderPath ); Pen borderPen = GUIControls.ColorScheme.GetPen( _colorScheme, "Sidebar.Button.Border", SystemPens.ControlDark ); e.Graphics.DrawPath( borderPen, _borderPath ); if ( _hot ) { Pen hotPen = GUIControls.ColorScheme.GetPen( _colorScheme, "Sidebar.Button.BorderHot", Pens.Blue ); e.Graphics.DrawLine( hotPen, left+1, top+2, left+1, bottom-3 ); e.Graphics.DrawLine( hotPen, left+2, top+1, right-3, top+1 ); e.Graphics.DrawLine( hotPen, right-2, top+2, right-2, bottom-3 ); e.Graphics.DrawLine( hotPen, left+2, bottom-2, right-3, bottom-2 ); e.Graphics.DrawRectangle( hotPen, left+2, top+2, ClientRectangle.Width-5, ClientRectangle.Height-5 ); } else { string leftPenId = drawPressed ? "Sidebar.Button.BorderDarkPressed" : "Sidebar.Button.BorderLight"; string rightPenId = drawPressed ? "Sidebar.Button.BorderLight" : "Sidebar.Button.BorderDark"; Pen leftPen = GUIControls.ColorScheme.GetPen( _colorScheme, leftPenId, Pens.White ); e.Graphics.DrawLine( leftPen, left+1, top+2, left+1, bottom-3 ); e.Graphics.DrawLine( leftPen, left+2, top+1, right-3, top+1 ); Pen rightPen = GUIControls.ColorScheme.GetPen( _colorScheme, rightPenId, SystemPens.ControlDark ); e.Graphics.DrawLine( rightPen, right-2, top+2, right-2, bottom-3 ); e.Graphics.DrawLine( rightPen, left+2, bottom-2, right-3, bottom-2 ); } IntPtr hdc = e.Graphics.GetHdc(); IntPtr oldFont = Win32Declarations.SelectObject( hdc, _fontHandle ); BackgroundMode oldMode = Win32Declarations.SetBkMode( hdc, BackgroundMode.TRANSPARENT ); int delta = drawPressed ? 1 : 0; int topSpace = 6; int iconAreaHeight = 20; int maxTextHeight = ClientRectangle.Height - topSpace - iconAreaHeight - 2; SIZE sz = new SIZE(); Win32Declarations.GetTextExtentPoint32( hdc, Text, Text.Length, ref sz ); string textToDraw = Text; if ( sz.cx > maxTextHeight ) { // calculate how many characters fit if we leave space for the ellipsis SIZE szClip = new SIZE(); int charsFit; Win32Declarations.GetTextExtentExPoint( hdc, Text, Text.Length, maxTextHeight-10, out charsFit, IntPtr.Zero, out szClip ); if ( charsFit > 0 ) { textToDraw = Text.Substring( 0, charsFit ) + "..."; } else { textToDraw = Text.Substring( 0, 1 ); } Win32Declarations.GetTextExtentPoint32( hdc, textToDraw, textToDraw.Length, ref sz ); } if ( _angle == 270 ) { Win32Declarations.TextOut( hdc, ClientRectangle.Right - 2 + delta, ClientRectangle.Top + topSpace + delta, textToDraw, textToDraw.Length ); } else if ( _angle == 90 ) { Win32Declarations.TextOut( hdc, ClientRectangle.Left + 2 + delta, ClientRectangle.Top + topSpace + sz.cx + delta, textToDraw, textToDraw.Length ); } Win32Declarations.SetBkMode( hdc, oldMode ); Win32Declarations.SelectObject( hdc, oldFont ); e.Graphics.ReleaseHdc( hdc ); if ( _icon != null ) { int iconX = (ClientRectangle.Width - 16) / 2; e.Graphics.DrawIcon( _icon, ClientRectangle.Left + iconX, ClientRectangle.Bottom - iconAreaHeight + delta ); } } catch( Exception ex ) { Core.ReportBackgroundException( ex ); _customDrawFailed = true; } } protected override void OnMouseDown( MouseEventArgs e ) { base.OnMouseDown( e ); if ( e.Button == MouseButtons.Left ) { _pressing = true; Capture = true; Invalidate(); } } protected override void OnMouseUp( MouseEventArgs e ) { base.OnMouseUp( e ); if ( e.Button == MouseButtons.Left ) { _pressing = false; Capture = false; if ( ClientRectangle.Contains( e.X, e.Y ) ) { Pressed = !Pressed; _hot = true; } else { Invalidate(); } } } protected override void OnMouseMove( MouseEventArgs e ) { base.OnMouseMove( e ); if ( _pressing ) { bool oldHot = _hot; _hot = ClientRectangle.Contains( e.X, e.Y ); if ( oldHot != _hot ) { Invalidate(); } } } protected override void OnMouseEnter( EventArgs e ) { base.OnMouseEnter( e ); _hot = true; Invalidate(); } protected override void OnMouseLeave( EventArgs e ) { base.OnMouseLeave( e ); _hot = false; Invalidate(); } protected override void OnDragEnter( DragEventArgs drgevent ) { base.OnDragEnter( drgevent ); _dragOverTimer.Start(); } protected override void OnDragLeave(EventArgs e) { base.OnDragLeave( e ); _dragOverTimer.Stop(); } private void _dragOverTimer_Tick( object sender, EventArgs e ) { _dragOverTimer.Stop(); Pressed = true; } } }