lipsync/trunk/Boare.Lib.AppUtil/BSplitContainer.cs

507 lines
22 KiB
C#

/*
* BSplitContainer.cs
* Copyright (c) 2008-2009 kbinani
*
* This file is part of Boare.Lib.AppUtil.
*
* Boare.Lib.AppUtil is free software; you can redistribute it and/or
* modify it under the terms of the BSD License.
*
* Boare.Lib.AppUtil is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
namespace Boare.Lib.AppUtil {
[Serializable]
public partial class BSplitContainer : ContainerControl {
private Orientation m_orientation = Orientation.Horizontal;
private int m_splitter_distance = 50;
private int m_panel1_min = 25;
private int m_panel2_min = 25;
private int m_splitter_width = 4;
private bool m_splitter_moving = false;
private int m_splitter_distance_draft = 50;
private BSplitterPanel m_panel1;
private BSplitterPanel m_panel2;
private System.ComponentModel.IContainer components = null;
private bool m_splitter_fixed = false;
private Pen m_panel1_border = null;
private Pen m_panel2_border = null;
private System.Windows.Forms.FixedPanel m_fixed_panel;
private PictureBox m_lbl_splitter;
private int m_panel2_distance = 1;
private double m_distance_rate = 0.5;
public event SplitterEventHandler SplitterMoved;
[Browsable(false)]
public event ControlEventHandler ControlAdded;
public BSplitContainer() {
InitializeComponent();
if ( m_orientation == Orientation.Horizontal ) {
m_lbl_splitter.Cursor = Cursors.VSplit;
} else {
m_lbl_splitter.Cursor = Cursors.HSplit;
}
if ( m_orientation == Orientation.Horizontal ) {
m_panel2_distance = this.Width - m_splitter_distance;
} else {
m_panel2_distance = this.Height - m_splitter_distance;
}
m_distance_rate = m_splitter_distance / (double)(m_splitter_distance + m_panel2_distance);
}
public System.Windows.Forms.FixedPanel FixedPanel {
get {
return m_fixed_panel;
}
set {
System.Windows.Forms.FixedPanel old = m_fixed_panel;
m_fixed_panel = value;
if ( m_fixed_panel != FixedPanel.None && m_fixed_panel != old ) {
if ( m_fixed_panel == FixedPanel.Panel1 ) {
m_panel2.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
if ( m_orientation == Orientation.Vertical ) {
m_panel1.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
} else {
m_panel1.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left;
}
} else {
m_panel1.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
if ( m_orientation == Orientation.Vertical ) {
m_panel2.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
} else {
m_panel2.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Right;
}
}
}
}
}
public bool IsSplitterFixed {
get {
return m_splitter_fixed;
}
set {
m_splitter_fixed = value;
if ( m_splitter_fixed ) {
m_lbl_splitter.Cursor = Cursors.Default;
} else {
if ( m_orientation == Orientation.Horizontal ) {
m_lbl_splitter.Cursor = Cursors.VSplit;
} else {
m_lbl_splitter.Cursor = Cursors.HSplit;
}
}
}
}
/// <summary>
/// 使用中のリソースをすべてクリーンアップします。
/// </summary>
/// <param name="disposing">マネージ リソースが破棄される場合 true、破棄されない場合は false です。</param>
protected override void Dispose( bool disposing ) {
if ( disposing && (components != null) ) {
components.Dispose();
}
base.Dispose( disposing );
}
/// <summary>
/// デザイナ サポートに必要なメソッドです。このメソッドの内容を
/// コード エディタで変更しないでください。
/// </summary>
private void InitializeComponent() {
this.m_lbl_splitter = new System.Windows.Forms.PictureBox();
this.m_panel2 = new Boare.Lib.AppUtil.BSplitterPanel();
this.m_panel1 = new Boare.Lib.AppUtil.BSplitterPanel();
((System.ComponentModel.ISupportInitialize)(this.m_lbl_splitter)).BeginInit();
this.SuspendLayout();
//
// m_lbl_splitter
//
this.m_lbl_splitter.BackColor = System.Drawing.Color.Transparent;
this.m_lbl_splitter.Location = new System.Drawing.Point( 0, 0 );
this.m_lbl_splitter.Name = "m_lbl_splitter";
this.m_lbl_splitter.Size = new System.Drawing.Size( 100, 50 );
this.m_lbl_splitter.TabIndex = 0;
this.m_lbl_splitter.TabStop = false;
this.m_lbl_splitter.MouseMove += new System.Windows.Forms.MouseEventHandler( this.m_lbl_splitter_MouseMove );
this.m_lbl_splitter.MouseDown += new System.Windows.Forms.MouseEventHandler( this.m_lbl_splitter_MouseDown );
this.m_lbl_splitter.MouseUp += new System.Windows.Forms.MouseEventHandler( this.m_lbl_splitter_MouseUp );
//
// m_panel2
//
this.m_panel2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.m_panel2.BorderColor = System.Drawing.Color.Black;
this.m_panel2.Location = new System.Drawing.Point( 0, 103 );
this.m_panel2.Margin = new System.Windows.Forms.Padding( 0 );
this.m_panel2.Name = "m_panel2";
this.m_panel2.Size = new System.Drawing.Size( 441, 245 );
this.m_panel2.TabIndex = 1;
this.m_panel2.BorderStyleChanged += new System.EventHandler( this.m_panel2_BorderStyleChanged );
this.m_panel2.SizeChanged += new System.EventHandler( this.m_panel2_SizeChanged );
//
// m_panel1
//
this.m_panel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.m_panel1.BorderColor = System.Drawing.Color.Black;
this.m_panel1.Location = new System.Drawing.Point( 0, 0 );
this.m_panel1.Margin = new System.Windows.Forms.Padding( 0, 0, 0, 4 );
this.m_panel1.Name = "m_panel1";
this.m_panel1.Size = new System.Drawing.Size( 441, 99 );
this.m_panel1.TabIndex = 0;
this.m_panel1.BorderStyleChanged += new System.EventHandler( this.m_panel1_BorderStyleChanged );
this.m_panel1.SizeChanged += new System.EventHandler( this.m_panel1_SizeChanged );
//
// SplitContainerEx
//
this.Controls.Add( this.m_panel2 );
this.Controls.Add( this.m_panel1 );
this.Controls.Add( this.m_lbl_splitter );
this.Size = new System.Drawing.Size( 441, 348 );
this.Paint += new System.Windows.Forms.PaintEventHandler( this.SplitContainerEx_Paint );
((System.ComponentModel.ISupportInitialize)(this.m_lbl_splitter)).EndInit();
this.ResumeLayout( false );
}
private void SplitContainerEx_Paint( object sender, PaintEventArgs e ) {
bool panel1_visible = true;
if ( Orientation == Orientation.Horizontal ) {
if ( m_panel1.Width == 0 ) {
panel1_visible = false;
}
} else {
if ( m_panel1.Height == 0 ) {
panel1_visible = false;
}
}
if ( m_panel1.BorderStyle == BorderStyle.FixedSingle && panel1_visible ) {
if ( m_panel1_border == null ) {
m_panel1_border = new Pen( m_panel1.BorderColor );
} else {
if ( !m_panel1.BorderColor.Equals( m_panel1_border.Color ) ) {
m_panel1_border = new Pen( m_panel1.BorderColor );
}
}
e.Graphics.DrawRectangle( m_panel1_border,
new Rectangle( m_panel1.Left - 1, m_panel1.Top - 1, m_panel1.Width + 1, m_panel1.Height + 1) );
}
bool panel2_visible = true;
if ( Orientation == Orientation.Horizontal ) {
if ( m_panel2.Width == 0 ) {
panel2_visible = false;
}
} else {
if ( m_panel2.Height == 0 ) {
panel2_visible = false;
}
}
if ( m_panel2.BorderStyle == BorderStyle.FixedSingle && panel2_visible ) {
if ( m_panel2_border == null ) {
m_panel2_border = new Pen( m_panel2.BorderColor );
} else {
if ( !m_panel2.BorderColor.Equals( m_panel2_border.Color ) ) {
m_panel2_border = new Pen( m_panel2.BorderColor );
}
}
e.Graphics.DrawRectangle( m_panel2_border,
new Rectangle( m_panel2.Left - 1, m_panel2.Top - 1, m_panel2.Width + 1, m_panel2.Height + 1 ) );
}
}
private void m_panel2_BorderStyleChanged( object sender, EventArgs e ) {
UpdateLayout( m_splitter_distance, m_splitter_width, m_panel1_min, m_panel2_min, false );
}
private void m_panel1_BorderStyleChanged( object sender, EventArgs e ) {
UpdateLayout( m_splitter_distance, m_splitter_width, m_panel1_min, m_panel2_min, false );
}
private void m_panel2_SizeChanged( object sender, EventArgs e ) {
m_panel2.Invalidate( true );
}
private void m_panel1_SizeChanged( object sender, EventArgs e ) {
m_panel1.Invalidate( true );
}
public int Panel1MinSize {
get {
return m_panel1_min;
}
set {
int min_splitter_distance = value;
if ( m_splitter_distance < min_splitter_distance && min_splitter_distance > 0 ) {
m_splitter_distance = min_splitter_distance;
}
UpdateLayout( m_splitter_distance, m_splitter_width, value, m_panel2_min, false );
}
}
public int Panel2MinSize {
get {
return m_panel2_min;
}
set {
int max_splitter_distance = (m_orientation == Orientation.Horizontal) ?
this.Width - m_splitter_width - value :
this.Height - m_splitter_width - value;
if ( m_splitter_distance > max_splitter_distance && max_splitter_distance > 0 ) {
m_splitter_distance = max_splitter_distance;
}
UpdateLayout( m_splitter_distance, m_splitter_width, m_panel1_min, value, false );
}
}
public int SplitterWidth {
get {
return m_splitter_width;
}
set {
if ( value < 1 ) {
value = 1;
}
UpdateLayout( m_splitter_distance, value, m_panel1_min, m_panel2_min, false );
}
}
private bool UpdateLayout( int splitter_distance, int splitter_width, int panel1_min, int panel2_min, bool check_only ) {
Point mouse = this.PointToClient( Control.MousePosition );
int pad1 = (m_panel1.BorderStyle == BorderStyle.FixedSingle) ? 1 : 0;
int pad2 = (m_panel2.BorderStyle == BorderStyle.FixedSingle) ? 1 : 0;
if ( m_orientation == Orientation.Horizontal ) {
int p1 = splitter_distance;
if ( p1 < 0 ) {
p1 = 0;
} else if ( this.Width < p1 + splitter_width ) {
p1 = this.Width - splitter_width;
}
int p2 = this.Width - p1 - splitter_width;
if ( check_only ) {
if ( p1 < panel1_min || p2 < panel2_min ) {
return false;
}
} else {
if ( p1 < panel1_min ) {
p1 = panel1_min;
}
p2 = this.Width - p1 - splitter_width;
if ( p2 < panel2_min ) {
p2 = panel2_min;
//return false;
}
}
if ( !check_only ) {
m_panel1.Left = pad1;
m_panel1.Top = pad1;
m_panel1.Width = (p1 - 2 * pad1 >= 0) ? (p1 - 2 * pad1) : 0;
m_panel1.Height = (this.Height - 2 * pad1 >= 0) ? (this.Height - 2 * pad1) : 0;
m_panel2.Left = p1 + splitter_width + pad2;
m_panel2.Top = pad2;
m_panel2.Width = (p2 - 2 * pad2 >= 0) ? (p2 - 2 * pad2) : 0;
m_panel2.Height = (this.Height - 2 * pad2 >= 0) ? (this.Height - 2 * pad2) : 0;
m_splitter_distance = p1;
m_panel2_distance = this.Width - m_splitter_distance;
m_distance_rate = m_splitter_distance / (double)(m_splitter_distance + m_panel2_distance);
if ( SplitterMoved != null ) {
SplitterMoved( this, new SplitterEventArgs( mouse.X, mouse.Y, p1, 0 ) );
}
m_splitter_width = splitter_width;
m_panel1_min = panel1_min;
m_panel2_min = panel2_min;
m_lbl_splitter.Left = p1;
m_lbl_splitter.Top = 0;
m_lbl_splitter.Width = splitter_width;
m_lbl_splitter.Height = this.Height;
}
return true;
} else {
int p1 = splitter_distance;
if ( p1 < 0 ) {
p1 = 0;
} else if ( this.Height < p1 + splitter_width ) {
p1 = this.Height - splitter_width;
}
int p2 = this.Height - p1 - splitter_width;
if ( check_only ) {
if ( p1 < panel1_min || p2 < panel2_min ) {
return false;
}
} else {
if ( p1 < panel1_min ) {
p1 = panel1_min;
}
p2 = this.Height - p1 - splitter_width;
if ( p2 < panel2_min ) {
p2 = panel2_min;
//return false;
}
}
if ( !check_only ) {
m_panel1.Left = pad1;
m_panel1.Top = pad1;
m_panel1.Width = (this.Width - 2 * pad1 >= 0) ? (this.Width - 2 * pad1) : 0;
m_panel1.Height = (p1 - 2 * pad1 >= 0) ? (p1 - 2 * pad1) : 0;
m_panel2.Left = pad2;
m_panel2.Top = p1 + splitter_width + pad2;
m_panel2.Width = (this.Width - 2 * pad2 >= 0) ? (this.Width - 2 * pad2) : 0;
m_panel2.Height = (p2 - 2 * pad2 >= 0) ? (p2 - 2 * pad2) : 0;
m_splitter_distance = p1;
m_panel2_distance = this.Height - m_splitter_distance;
m_distance_rate = m_splitter_distance / (double)(m_splitter_distance + m_panel2_distance);
if ( SplitterMoved != null ) {
SplitterMoved( this, new SplitterEventArgs( mouse.X, mouse.Y, 0, p1 ) );
}
m_splitter_width = splitter_width;
m_panel1_min = panel1_min;
m_panel2_min = panel2_min;
m_lbl_splitter.Left = 0;
m_lbl_splitter.Top = p1;
m_lbl_splitter.Width = this.Width;
m_lbl_splitter.Height = splitter_width;
}
return true;
}
}
public int SplitterDistance {
get {
return m_splitter_distance;
}
set {
UpdateLayout( value, m_splitter_width, m_panel1_min, m_panel2_min, false );
if ( m_orientation == Orientation.Horizontal ) {
m_panel2_distance = this.Width - m_splitter_distance;
} else {
m_panel2_distance = this.Height - m_splitter_distance;
}
}
}
public Orientation Orientation {
get {
return m_orientation;
}
set {
if ( m_orientation != value ) {
m_orientation = value;
UpdateLayout( m_splitter_distance, m_splitter_width, m_panel1_min, m_panel2_min, false );
if ( m_orientation == Orientation.Horizontal ) {
m_lbl_splitter.Cursor = Cursors.VSplit;
} else {
m_lbl_splitter.Cursor = Cursors.HSplit;
}
}
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public BSplitterPanel Panel1 {
get {
return m_panel1;
}
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public BSplitterPanel Panel2 {
get {
return m_panel2;
}
}
protected override void OnSizeChanged( EventArgs e ) {
#if DEBUG
Console.WriteLine( "BSplitContainer+OnSizeChanged" );
//Console.WriteLine( " FixedPanel=" + FixedPanel );
//Console.WriteLine( " m_splitter_distance=" + m_splitter_distance );
Console.WriteLine( " Width=" + Width );
Console.WriteLine( " Height=" + Height );
//Console.WriteLine( " m_panel2_distance=" + m_panel2_distance );
#endif
base.OnSizeChanged( e );
if ( Width <= 0 || Height <= 0 ) {
return;
}
if ( m_fixed_panel == FixedPanel.Panel2 ) {
if ( m_orientation == Orientation.Horizontal ) {
m_splitter_distance = this.Width - m_panel2_distance;
} else {
m_splitter_distance = this.Height - m_panel2_distance;
}
} else if ( m_fixed_panel == FixedPanel.None ) {
#if DEBUG
//Console.WriteLine( " m_distance_rate=" + m_distance_rate );
#endif
if ( m_orientation == Orientation.Horizontal ) {
m_splitter_distance = (int)(this.Width * m_distance_rate);
} else {
m_splitter_distance = (int)(this.Height * m_distance_rate);
}
}
UpdateLayout( m_splitter_distance, m_splitter_width, m_panel1_min, m_panel2_min, false );
}
private void m_lbl_splitter_MouseDown( object sender, MouseEventArgs e ) {
if ( !m_splitter_fixed ) {
m_splitter_moving = true;
m_splitter_distance_draft = m_splitter_distance;
this.Cursor = (m_orientation == Orientation.Horizontal) ? Cursors.VSplit : Cursors.HSplit;
m_lbl_splitter.BackColor = SystemColors.ControlDark;
m_lbl_splitter.BringToFront();
}
}
private void m_lbl_splitter_MouseUp( object sender, MouseEventArgs e ) {
if ( m_splitter_moving ) {
m_splitter_moving = false;
UpdateLayout( m_splitter_distance_draft, m_splitter_width, m_panel1_min, m_panel2_min, false );
this.Cursor = Cursors.Default;
m_lbl_splitter.BackColor = SystemColors.Control;
}
}
private void m_lbl_splitter_MouseMove( object sender, MouseEventArgs e ) {
base.OnMouseMove( e );
if ( m_splitter_fixed ) {
return;
}
Point mouse_local = this.PointToClient( Control.MousePosition );
if ( m_splitter_moving ) {
int new_distance = m_splitter_distance;
if ( m_orientation == Orientation.Horizontal ) {
new_distance = mouse_local.X;
} else {
new_distance = mouse_local.Y;
}
if ( UpdateLayout( new_distance, m_splitter_width, m_panel1_min, m_panel2_min, true ) ) {
m_splitter_distance_draft = new_distance;
if ( m_orientation == Orientation.Horizontal ) {
m_lbl_splitter.Left = m_splitter_distance_draft;
} else {
m_lbl_splitter.Top = m_splitter_distance_draft;
}
}
}
}
}
}