using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using Storm.TextEditor.Win32;
using Storm.TextEditor.Win32.Enums;
namespace Storm.TextEditor.Core.Splitting
{
[ToolboxItem(false)]
public class SplitViewControl
: Control
{
#region Fields
private Panel vertical = null;
private Panel horizontal = null;
private Panel center = null;
private Control upperLeft = null;
private Control upperRight = null;
private Control lowerLeft = null;
private Control lowerRight = null;
private Point prevPos = new Point(0);
private bool firstTime = false;
/// <summary>
/// Required designer variable.
/// </summary>
private Container components = null;
private SizeAction action = SizeAction.None;
private Point startPos = new Point(0, 0);
#region Events
/// <summary>
/// Occurs when the split view is resizing.
/// </summary>
public event EventHandler Resizing = null;
/// <summary>
/// Occurs when the top split view is hidden.
/// </summary>
public event EventHandler HideTop = null;
/// <summary>
/// Occurs when the left split view is hidden.
/// </summary>
public event EventHandler HideLeft = null;
#endregion
#endregion
#region Properties
/// <summary>
/// Gets or sets the distance, in pixels, between the vertical split view's left edge and the SplitViewControl's left edge.
/// </summary>
public int VerticalEdgeDistance
{
get { return vertical.Left; }
set
{
vertical.Left = value;
this.DoResize();
}
}
/// <summary>
/// Gets or sets the distance, in pixels, between the horizontal split view's top edge and the SplitViewControl's top edge.
/// </summary>
public int HorizontalEdgeDistance
{
get { return horizontal.Top; }
set
{
horizontal.Top = value;
this.DoResize();
}
}
/// <summary>
/// Gets or sets the Control that should be confined in the upper left split view.
/// </summary>
public Control UpperLeft
{
get { return upperLeft; }
set
{
upperLeft = value;
this.DoResize();
}
}
/// <summary>
/// Gets or sets the Control that should be confined in the upper right split view.
/// </summary>
public Control UpperRight
{
get { return upperRight; }
set
{
upperRight = value;
this.DoResize();
}
}
/// <summary>
/// Gets or sets the Control that should be confined in the lower left split view.
/// </summary>
public Control LowerLeft
{
get { return lowerLeft; }
set
{
lowerLeft = value;
this.DoResize();
}
}
/// <summary>
/// Gets or sets the Control that should be confined in the lower right split view.
/// </summary>
public Control LowerRight
{
get { return lowerRight; }
set
{
lowerRight = value;
this.DoResize();
}
}
#endregion
#region Methods
#region Protected
/// <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 OnResize(EventArgs e)
{
// Update by calling DoResize.
this.DoResize();
}
protected override void OnControlAdded(ControlEventArgs e)
{
// Update by calling DoResize.
this.DoResize();
}
#endregion
#region Private
/// <summary>
/// Raises the Resizing event.
/// </summary>
private void OnResizing()
{
if (this.Resizing != null)
this.Resizing(this, new EventArgs());
}
/// <summary>
/// Raises the HideLeft event.
/// </summary>
private void OnHideLeft()
{
if (this.HideLeft != null)
this.HideLeft(this, new EventArgs());
}
/// <summary>
/// Raises the HideTop event.
/// </summary>
private void OnHideTop()
{
if (this.HideTop != null)
this.HideTop(this, new EventArgs());
}
/// <summary>
/// Contains logic for updating the visible Controls in the SplitViewControl.
/// </summary>
private void DoResize()
{
int newHeight = this.Height;
int newWidth = this.Width;
if (newHeight != 0 && newWidth != 0)
{
this.SuspendLayout();
this.Resize2();
this.OnResizing();
if (horizontal.Top < 15)
{
horizontal.Top = 0 - horizontal.Height;
this.OnHideTop();
}
if (vertical.Left < 15)
{
vertical.Left = 0 - vertical.Width;
this.OnHideLeft();
}
horizontal.Width = this.Width;
vertical.Height = this.Height;
horizontal.SendToBack();
vertical.SendToBack();
horizontal.BackColor = SystemColors.Control;
vertical.BackColor = SystemColors.Control;
int rightLeft = vertical.Left + vertical.Width;
int rightLowerTop = horizontal.Top + horizontal.Height;
int rightWidth = this.Width - rightLeft;
int lowerHeight = this.Height - rightLowerTop;
int upperHeight = horizontal.Top;
int leftWidth = vertical.Left;
if (lowerRight != null)
{
lowerRight.BringToFront();
lowerRight.SetBounds(rightLeft, rightLowerTop, rightWidth, lowerHeight);
}
if (upperRight != null)
{
upperRight.BringToFront();
upperRight.SetBounds(rightLeft, 0, rightWidth, upperHeight);
}
if (lowerLeft != null)
{
lowerLeft.BringToFront();
lowerLeft.SetBounds(0, rightLowerTop, leftWidth, lowerHeight);
}
if (upperLeft != null)
{
upperLeft.BringToFront();
upperLeft.SetBounds(0, 0, leftWidth, upperHeight);
}
this.ResumeLayout();
}
}
private void OnHorizontalMouseDown(object sender, MouseEventArgs e)
{
action = SizeAction.SizeH;
startPos = new Point(e.X, e.Y);
horizontal.BringToFront();
horizontal.BackColor = SystemColors.ControlDark;
firstTime = true;
}
private void OnVerticalMouseDown(object sender, MouseEventArgs e)
{
action = SizeAction.SizeV;
startPos = new Point(e.X, e.Y);
vertical.BringToFront();
vertical.BackColor = SystemColors.ControlDark;
firstTime = true;
}
private void OnCenterMouseDown(object sender, MouseEventArgs e)
{
action = SizeAction.SizeA;
startPos = new Point(e.X, e.Y);
vertical.BringToFront();
horizontal.BringToFront();
vertical.BackColor = SystemColors.ControlDark;
horizontal.BackColor = SystemColors.ControlDark;
firstTime = true;
}
private void OnHorizontalMouseUp(object sender, MouseEventArgs e)
{
int x = 0;
int y = startPos.Y - e.Y;
this.Resize(x, y);
action = SizeAction.None;
this.DoResize(); // Update
}
private void OnVerticalMouseUp(object sender, MouseEventArgs e)
{
int x = startPos.X - e.X;
int y = 0;
this.Resize(x, y);
action = SizeAction.None;
this.DoResize(); // Update.
}
private void OnCenterMouseUp(object sender, MouseEventArgs e)
{
int x = startPos.X - e.X;
int y = startPos.Y - e.Y;
this.Resize(x, y);
action = SizeAction.None;
this.DoResize(); // Update.
}
private void OnHorizontalMouseMove(object sender, MouseEventArgs e)
{
if (action == SizeAction.SizeH && e.Button == MouseButtons.Left)
{
Point start;
int x = e.X;
int y = e.Y;
if (y + horizontal.Top > Height - 4)
y = Height - 4 - horizontal.Top;
if (y + horizontal.Top < 0)
y = 0 - horizontal.Top;
if (firstTime == false)
{
start = this.PointToScreen(this.Location);
start.Y += prevPos.Y + horizontal.Location.Y;
ControlPaint.FillReversibleRectangle(new Rectangle(start.X, start.Y, this.Width, 3), Color.Black);
}
else
firstTime = false;
start = this.PointToScreen(this.Location);
start.Y += y + horizontal.Location.Y;
ControlPaint.FillReversibleRectangle(new Rectangle(start.X, start.Y, this.Width, 3), Color.Black);
prevPos = new Point(x, y);
}
}
private void OnVerticalMouseMove(object sender, MouseEventArgs e)
{
if (action == SizeAction.SizeV && e.Button == MouseButtons.Left)
{
Point start;
int x = e.X;
int y = e.Y;
if (x + vertical.Left > Width - 4)
x = Width - 4 - vertical.Left;
if (x + vertical.Left < 0)
x = 0 - vertical.Left;
if (firstTime == false)
{
start = this.PointToScreen(this.Location);
start.X += prevPos.X + vertical.Location.X;
ControlPaint.FillReversibleRectangle(new Rectangle(start.X, start.Y, 3, this.Height), Color.Black);
}
else
firstTime = false;
start = this.PointToScreen(this.Location);
start.X += x + vertical.Location.X;
ControlPaint.FillReversibleRectangle(new Rectangle(start.X, start.Y, 3, this.Height), Color.Black);
prevPos = new Point(x, y);
}
}
private void OnCenterMouseMove(object sender, MouseEventArgs e)
{
if (action == SizeAction.SizeA && e.Button == MouseButtons.Left)
{
Point start;
int x = e.X - center.Width / 2;
int y = e.Y - center.Height / 2;
if (firstTime == false)
{
start = this.PointToScreen(this.Location);
start.X += prevPos.X + vertical.Location.X;
ControlPaint.FillReversibleRectangle(new Rectangle(start.X, start.Y, 3, this.Height), Color.Black);
start = this.PointToScreen(this.Location);
start.Y += prevPos.Y + horizontal.Location.Y;
ControlPaint.FillReversibleRectangle(new Rectangle(start.X, start.Y, this.Width, 3), SystemColors.ControlDark);
}
else
firstTime = false;
start = this.PointToScreen(this.Location);
start.X += x + vertical.Location.X;
ControlPaint.FillReversibleRectangle(new Rectangle(start.X, start.Y, 3, this.Height), Color.Black);
start = this.PointToScreen(this.Location);
start.Y += y + horizontal.Location.Y;
ControlPaint.FillReversibleRectangle(new Rectangle(start.X, start.Y, this.Width, 3), SystemColors.ControlDark);
prevPos = new Point(x, y);
}
}
private new void Resize(int x, int y)
{
this.SuspendLayout();
int xx = vertical.Left - x;
int yy = horizontal.Top - y;
if (xx < 0)
xx = 0;
if (yy < 0)
yy = 0;
if (yy > this.Height - horizontal.Height - SystemInformation.VerticalScrollBarWidth * 3)
yy = this.Height - horizontal.Height - SystemInformation.VerticalScrollBarWidth * 3;
if (xx > this.Width - vertical.Width - SystemInformation.VerticalScrollBarWidth * 3)
xx = this.Width - vertical.Width - SystemInformation.VerticalScrollBarWidth * 3;
if (xx != vertical.Left)
vertical.Left = xx;
if (yy != horizontal.Top)
horizontal.Top = yy;
int centerY = (horizontal.Top + horizontal.Height / 2) - center.Height / 2;
int centerX = (vertical.Left + vertical.Width / 2) - center.Width / 2;
center.Location = new Point(centerX, centerY);
this.ResumeLayout();
this.Invalidate();
try
{
if (upperLeft != null)
upperLeft.Refresh();
if (upperLeft != null)
upperLeft.Refresh();
if (upperLeft != null)
upperLeft.Refresh();
if (upperLeft != null)
upperLeft.Refresh();
}
catch
{
}
this.OnResizing();
}
private void Resize2()
{
int xx = vertical.Left;
int yy = horizontal.Top;
if (xx < 0)
xx = 0;
if (yy < 0)
yy = 0;
if (yy > this.Height - horizontal.Height - SystemInformation.VerticalScrollBarWidth * 3)
{
yy = this.Height - horizontal.Height - SystemInformation.VerticalScrollBarWidth * 3;
if (yy != horizontal.Top)
horizontal.Top = yy;
}
if (xx > this.Width - vertical.Width - SystemInformation.VerticalScrollBarWidth * 3)
{
xx = this.Width - vertical.Width - SystemInformation.VerticalScrollBarWidth * 3;
if (xx != vertical.Left)
vertical.Left = xx;
}
int centerY = (horizontal.Top + horizontal.Height / 2) - center.Height / 2;
int centerX = (vertical.Left + vertical.Width / 2) - center.Width / 2;
center.Location = new Point(centerX, centerY);
}
private void OnCenterDoubleClick(object sender, EventArgs e)
{
horizontal.Top = -100;
vertical.Left = -100;
this.DoResize();
}
private void OnVerticalDoubleClick(object sender, EventArgs e)
{
vertical.Left = -100;
this.DoResize();
}
private void OnHorizontalDoubleClick(object sender, EventArgs e)
{
horizontal.Top = -100;
this.DoResize();
}
#endregion
#region Public
/// <summary>
/// Splits the horizontal split view 50 percent.
/// </summary>
public void SplitHorizontalHalf()
{
horizontal.Top = Height / 2;
this.DoResize();
}
/// <summary>
/// Splits the vertical split view 50 percent.
/// </summary>
public void SplitVerticalHalf()
{
vertical.Left = Width / 2;
this.DoResize();
}
/// <summary>
/// Resets the split views.
/// </summary>
public void ResetSplitview()
{
vertical.Left = 0;
horizontal.Top = 0;
this.DoResize();
}
/// <summary>
/// Start dragging the horizontal splitter.
/// </summary>
public void InvokeMouseDownHorizontal()
{
IntPtr hwnd = horizontal.Handle;
NativeUser32Api.SendMessage(hwnd, (int)WindowMessage.WM_LBUTTONDOWN, 0, 0);
}
/// <summary>
/// Start dragging the vertical splitter.
/// </summary>
public void InvokeMouseDownVertical()
{
IntPtr hwnd = vertical.Handle;
NativeUser32Api.SendMessage(hwnd, (int)WindowMessage.WM_LBUTTONDOWN, 0, 0);
}
#endregion
#endregion
/// <summary>
/// Initializes a new instance of SplitViewControl.
/// </summary>
public SplitViewControl()
{
// Required by the Windows Forms Designer.
InitializeComponent();
this.SetStyle(ControlStyles.ContainerControl, true);
this.DoResize();
this.Resize(0, 0);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
vertical = new System.Windows.Forms.Panel();
horizontal = new System.Windows.Forms.Panel();
center = new System.Windows.Forms.Panel();
SuspendLayout();
//
// Vertical
//
vertical.BackColor = System.Drawing.SystemColors.Control;
vertical.Cursor = System.Windows.Forms.Cursors.VSplit;
vertical.Name = "Vertical";
vertical.Size = new System.Drawing.Size(4, 264);
vertical.TabIndex = 0;
vertical.MouseUp += new System.Windows.Forms.MouseEventHandler(OnVerticalMouseUp);
vertical.DoubleClick += new System.EventHandler(OnVerticalDoubleClick);
vertical.MouseMove += new System.Windows.Forms.MouseEventHandler(OnVerticalMouseMove);
vertical.MouseDown += new System.Windows.Forms.MouseEventHandler(OnVerticalMouseDown);
//
// Horizontal
//
horizontal.BackColor = System.Drawing.SystemColors.Control;
horizontal.Cursor = System.Windows.Forms.Cursors.HSplit;
horizontal.Name = "Horizontal";
horizontal.Size = new System.Drawing.Size(320, 4);
horizontal.TabIndex = 1;
horizontal.MouseUp += new System.Windows.Forms.MouseEventHandler(OnHorizontalMouseUp);
horizontal.DoubleClick += new System.EventHandler(OnHorizontalDoubleClick);
horizontal.MouseMove += new System.Windows.Forms.MouseEventHandler(OnHorizontalMouseMove);
horizontal.MouseDown += new System.Windows.Forms.MouseEventHandler(OnHorizontalMouseDown);
//
// Center
//
center.BackColor = System.Drawing.SystemColors.Control;
center.Cursor = System.Windows.Forms.Cursors.SizeAll;
center.Location = new System.Drawing.Point(146, 69);
center.Name = "Center";
center.Size = new System.Drawing.Size(24, 24);
center.TabIndex = 2;
center.MouseUp += new System.Windows.Forms.MouseEventHandler(OnCenterMouseUp);
center.DoubleClick += new System.EventHandler(OnCenterDoubleClick);
center.MouseMove += new System.Windows.Forms.MouseEventHandler(OnCenterMouseMove);
center.MouseDown += new System.Windows.Forms.MouseEventHandler(OnCenterMouseDown);
//
// SplitViewControl
//
BackColor = System.Drawing.Color.Magenta;
Controls.AddRange(new System.Windows.Forms.Control[]
{
center,
horizontal,
vertical
});
Size = new System.Drawing.Size(200, 200);
ResumeLayout(false);
}
#endregion
}
}