/// /// 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; namespace JetBrains.Omea.GUIControls { /// /// Splitter with a gradient background and collapsing support. /// public class JetSplitter: Splitter { private bool _collapsed = false; private Control _controlToCollapse; private bool _isVertical; private int _splitterSize; private int _splitterCenterSize; private int _splitterCenter; // in "long" direction private int _splitterMiddle; // in "short" direction private int _splitterArrowSize; private bool _fillGradient = true; private bool _fillCenterRect = true; private Rectangle _splitterCenterRect; private ColorScheme _colorScheme; public event PaintEventHandler PaintSplitterBackground; public event EventHandler CollapsedChanged; public JetSplitter() : base() { SetStyle( ControlStyles.ResizeRedraw, true ); } protected override void Dispose( bool disposing ) { if ( disposing ) { } base.Dispose( disposing ); } [DefaultValue(null)] public Control ControlToCollapse { get { return _controlToCollapse; } set { _controlToCollapse = value; } } [DefaultValue(true)] public bool FillGradient { get { return _fillGradient; } set { _fillGradient = value; } } [DefaultValue(true)] public bool FillCenterRect { get { return _fillCenterRect; } set { _fillCenterRect = value; } } [DefaultValue(false)] public bool Collapsed { get { return _collapsed; } set { if ( _collapsed != value ) { _collapsed = value; if ( _controlToCollapse != null ) { _controlToCollapse.Visible = !_collapsed; } if ( CollapsedChanged != null ) { CollapsedChanged( this, EventArgs.Empty ); } } } } public ColorScheme ColorScheme { get { return _colorScheme; } set { if ( _colorScheme != value ) { _colorScheme = value; Invalidate(); } } } protected override void OnSizeChanged( EventArgs e ) { base.OnSizeChanged( e ); UpdateLayout(); } protected override void OnLocationChanged( EventArgs e ) { base.OnLocationChanged( e ); UpdateLayout(); } private void UpdateLayout() { _isVertical = ( Dock == DockStyle.Left || Dock == DockStyle.Right ); _splitterSize = _isVertical ? ClientSize.Height : ClientSize.Width; _splitterCenterSize = Math.Min( 120, (int) (_splitterSize * 0.7) ); if ( _isVertical ) { _splitterCenterRect = new Rectangle( ClientRectangle.Left, ClientRectangle.Top + (ClientRectangle.Height - _splitterCenterSize) / 2, ClientRectangle.Width, _splitterCenterSize ); _splitterCenter = ( ClientRectangle.Top + ClientRectangle.Bottom ) / 2; _splitterMiddle = ( ClientRectangle.Left + ClientRectangle.Right ) / 2 - 1; _splitterArrowSize = ClientRectangle.Width; } else { _splitterCenterRect = new Rectangle( ClientRectangle.Left + (ClientRectangle.Width - _splitterCenterSize) / 2, ClientRectangle.Top, _splitterCenterSize, ClientRectangle.Height ); _splitterCenter = ( ClientRectangle.Left + ClientRectangle.Right ) / 2; _splitterMiddle = ( ClientRectangle.Top + ClientRectangle.Bottom ) / 2 - 1; _splitterArrowSize = ClientRectangle.Height; } } protected override void OnPaint( PaintEventArgs e ) { base.OnPaint( e ); if ( ClientRectangle.Width == 0 || ClientRectangle.Height == 0 ) return; if ( PaintSplitterBackground != null ) { PaintSplitterBackground( this, e ); } if ( _fillGradient ) { Brush backBrush = new LinearGradientBrush( ClientRectangle, SystemColors.ControlLightLight, SystemColors.ControlDark, _isVertical ? LinearGradientMode.Horizontal : LinearGradientMode.Vertical ); using( backBrush ) { e.Graphics.FillRectangle( backBrush, ClientRectangle ); } } Rectangle rcSplitterCenter = _splitterCenterRect; if ( _fillCenterRect ) { ColorScheme.DrawRectangle( e.Graphics, _colorScheme, "Splitter.CenterBorder", new Rectangle( rcSplitterCenter.Left, rcSplitterCenter.Top, rcSplitterCenter.Width-1, rcSplitterCenter.Height-1 ), SystemPens.Control ); } if ( _isVertical ) { rcSplitterCenter.Inflate( 0, -1 ); } else { rcSplitterCenter.Inflate( -1, 0 ); } if ( _fillCenterRect && rcSplitterCenter.Width > 0 && rcSplitterCenter.Height > 0 ) { ColorScheme.FillRectangle( e.Graphics, _colorScheme, _isVertical ? "Splitter.CenterVert" : "Splitter.CenterHorz", rcSplitterCenter, SystemBrushes.Control ); } if ( _controlToCollapse != null ) { for( int coord=_splitterCenter - _splitterCenterSize/2 + 10; coord < _splitterCenter - 10; coord += 3 ) { DrawCenterDot( e.Graphics, coord ); } for( int coord=_splitterCenter + 10; coord < _splitterCenter + _splitterCenterSize/2 - 10; coord += 3 ) { DrawCenterDot( e.Graphics, coord ); } Brush arrowBrush = ColorScheme.GetBrush( _colorScheme, "Splitter.Arrow", rcSplitterCenter, Brushes.Black ); if ( Dock == DockStyle.Top && _controlToCollapse.Visible ) { e.Graphics.FillPolygon( arrowBrush, new Point[] { new Point( _splitterCenter -_splitterArrowSize, ClientRectangle.Bottom-1 ), new Point( _splitterCenter + _splitterArrowSize + 1, ClientRectangle.Bottom-1 ), new Point( _splitterCenter, ClientRectangle.Top-1 ) } ); } if ( Dock == DockStyle.Top && !_controlToCollapse.Visible ) { e.Graphics.FillPolygon( arrowBrush, new Point[] { new Point( _splitterCenter - _splitterArrowSize, ClientRectangle.Top ), new Point( _splitterCenter + _splitterArrowSize + 1, ClientRectangle.Top ), new Point( _splitterCenter, ClientRectangle.Bottom ) } ); } if ( ( Dock == DockStyle.Left && _controlToCollapse.Visible ) || ( Dock == DockStyle.Right && !_controlToCollapse.Visible ) ) { e.Graphics.FillPolygon( arrowBrush, new Point[] { new Point( ClientRectangle.Right-1, _splitterCenter -_splitterArrowSize ), new Point( ClientRectangle.Right-1, _splitterCenter + _splitterArrowSize + 1 ), new Point( ClientRectangle.Left-1, _splitterCenter ) } ); } if ( ( Dock == DockStyle.Right && _controlToCollapse.Visible ) || ( Dock == DockStyle.Left && !_controlToCollapse.Visible ) ) { e.Graphics.FillPolygon( arrowBrush, new Point[] { new Point( ClientRectangle.Left, _splitterCenter -_splitterArrowSize ), new Point( ClientRectangle.Left, _splitterCenter + _splitterArrowSize + 1 ), new Point( ClientRectangle.Right, _splitterCenter ) } ); } } else { for( int coord=_splitterCenter - _splitterCenterSize/2 + 10; coord < _splitterCenter + _splitterCenterSize/2 - 10; coord += 3 ) { DrawCenterDot( e.Graphics, coord ); } } } private void DrawCenterDot( Graphics g, int coord ) { Rectangle rcDot = _isVertical ? new Rectangle( _splitterMiddle, coord, 1, 1 ) : new Rectangle( coord, _splitterMiddle, 1, 1 ); ColorScheme.DrawRectangle( g, _colorScheme, "Splitter.Dot", rcDot, Pens.Black ); } protected override void OnMouseDown( MouseEventArgs e ) { // prevent default resize if we're collapsed and the user clicked outside the collapse rect if ( Collapsed ) { return; } base.OnMouseDown (e); } protected override void OnMouseMove( MouseEventArgs e ) { base.OnMouseMove( e ); if ( _controlToCollapse != null ) { if ( _splitterCenterRect.Contains( e.X, e.Y ) ) { Cursor = Cursors.Hand; } else { if ( _controlToCollapse.Visible ) { Cursor = _isVertical ? Cursors.VSplit : Cursors.HSplit; } else { Cursor = Cursors.Default; } } } } protected override void OnMouseUp( MouseEventArgs e ) { base.OnMouseUp( e ); if ( e.Button == MouseButtons.Left && _splitterCenterRect.Contains( e.X, e.Y ) ) { if ( _controlToCollapse != null ) { Collapsed = !Collapsed; Invalidate(); } } } } }