Browse Source
git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@5656 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61pull/1/head
19 changed files with 2 additions and 2971 deletions
@ -1,159 +0,0 @@
@@ -1,159 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System.Collections.Generic; |
||||
using System.Windows.Forms; |
||||
using ICSharpCode.Core; |
||||
using ICSharpCode.SharpDevelop.Debugging; |
||||
using ICSharpCode.SharpDevelop.Widgets.TreeGrid; |
||||
|
||||
namespace Debugger.AddIn.TreeModel |
||||
{ |
||||
public class DynamicTreeDebuggerRow: DynamicTreeRow |
||||
{ |
||||
// Columns:
|
||||
// 0 = plus sign
|
||||
// 1 = icon
|
||||
// 2 = text
|
||||
// 3 = value
|
||||
Process process; |
||||
|
||||
TreeNode content; |
||||
|
||||
bool isShown; |
||||
bool isExpanded; |
||||
bool childsLoaded; |
||||
|
||||
public TreeNode Content { |
||||
get { return content; } |
||||
} |
||||
|
||||
public bool IsShown { |
||||
get { return isShown; } |
||||
} |
||||
|
||||
public bool IsExpanded { |
||||
get { return isExpanded; } |
||||
} |
||||
|
||||
public DynamicTreeDebuggerRow(Process process, TreeNode content) |
||||
{ |
||||
this.process = process; |
||||
|
||||
DebuggerGridControl.AddColumns(this.ChildColumns); |
||||
|
||||
this[1].Paint += OnIconPaint; |
||||
this[3].FinishLabelEdit += OnLabelEdited; |
||||
this[3].MouseDown += OnMouseDown; |
||||
|
||||
this.Expanded += delegate { isExpanded = true; }; |
||||
this.Collapsed += delegate { isExpanded = false; }; |
||||
this.Shown += delegate { isShown = true; }; |
||||
this.Hidden += delegate { isShown = false; }; |
||||
|
||||
SetContentRecursive(content); |
||||
} |
||||
|
||||
public void SetContentRecursive(TreeNode content) |
||||
{ |
||||
this.content = content; |
||||
|
||||
this[1].Text = ""; // Icon
|
||||
this[2].Text = content.Name; |
||||
this[3].Text = content.Text; |
||||
this[3].AllowLabelEdit = (content is ISetText) && ((ISetText)content).CanSetText; |
||||
|
||||
this.ShowPlus = (content.ChildNodes != null); |
||||
this.ShowMinusWhileExpanded = true; |
||||
|
||||
childsLoaded = false; |
||||
if (content.ChildNodes != null && isExpanded) { |
||||
LoadChilds(); |
||||
} else { |
||||
this.ChildRows.Clear(); |
||||
} |
||||
|
||||
// Repaint and process user commands
|
||||
Utils.DoEvents(process); |
||||
} |
||||
|
||||
public void SetChildContentRecursive(IEnumerable<TreeNode> contentEnum) |
||||
{ |
||||
contentEnum = contentEnum ?? new TreeNode[0]; |
||||
|
||||
int index = 0; |
||||
foreach(TreeNode content in contentEnum) { |
||||
// Add or overwrite existing items
|
||||
if (index < ChildRows.Count) { |
||||
// Overwrite
|
||||
((DynamicTreeDebuggerRow)ChildRows[index]).SetContentRecursive(content); |
||||
} else { |
||||
// Add
|
||||
ChildRows.Add(new DynamicTreeDebuggerRow(process, content)); |
||||
} |
||||
index++; |
||||
} |
||||
int count = index; |
||||
// Delete other nodes
|
||||
while(ChildRows.Count > count) { |
||||
ChildRows.RemoveAt(count); |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Called when plus is pressed in debugger tooltip.
|
||||
/// Sets the data to be show in the next level.
|
||||
/// </summary>
|
||||
protected override void OnExpanding(DynamicListEventArgs e) |
||||
{ |
||||
base.OnExpanding(e); |
||||
if (process.IsRunning) { |
||||
MessageService.ShowMessage( |
||||
"${res:MainWindow.Windows.Debug.LocalVariables.CannotExploreVariablesWhileRunning}", |
||||
"${res:MainWindow.Windows.Debug.LocalVariables}" |
||||
); |
||||
return; |
||||
} |
||||
try { |
||||
LoadChilds(); |
||||
} catch (AbortedBecauseDebuggeeResumedException) { |
||||
} |
||||
} |
||||
|
||||
void LoadChilds() |
||||
{ |
||||
if (!childsLoaded) { |
||||
childsLoaded = true; |
||||
SetChildContentRecursive(content.ChildNodes); |
||||
} |
||||
} |
||||
|
||||
void OnIconPaint(object sender, ItemPaintEventArgs e) |
||||
{ |
||||
if (content.Image != null) { |
||||
e.Graphics.DrawImageUnscaled(content.Image, e.ClipRectangle); |
||||
} |
||||
} |
||||
|
||||
void OnLabelEdited(object sender, DynamicListEventArgs e) |
||||
{ |
||||
if (((ISetText)content).CanSetText) { |
||||
((ISetText)content).SetText(((DynamicListItem)sender).Text); |
||||
} |
||||
} |
||||
|
||||
void OnMouseDown(object sender, DynamicListMouseEventArgs e) |
||||
{ |
||||
if (e.Button == MouseButtons.Right && content is IContextMenu) { |
||||
ContextMenuStrip menu = ((IContextMenu)content).GetContextMenu(); |
||||
if (menu != null) { |
||||
menu.Show(e.List, e.Location); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,149 +0,0 @@
@@ -1,149 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Drawing; |
||||
using System.Windows.Forms; |
||||
|
||||
using ICSharpCode.SharpDevelop.Widgets.TreeGrid; |
||||
using ICSharpCode.TextEditor; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Debugging |
||||
{ |
||||
public class DebuggerGridControl : DynamicList |
||||
{ |
||||
// Columns:
|
||||
// 0 = plus sign
|
||||
// 1 = icon
|
||||
// 2 = text
|
||||
// 3 = value
|
||||
|
||||
DynamicTreeRow row; |
||||
|
||||
public static void AddColumns(IList<DynamicListColumn> columns) |
||||
{ |
||||
columns.Add(new DynamicListColumn()); |
||||
columns.Add(new DynamicListColumn()); |
||||
columns.Add(new DynamicListColumn()); |
||||
columns.Add(new DynamicListColumn()); |
||||
columns[0].BackgroundBrush = Brushes.White; |
||||
columns[0].BackgroundBrushInactive = Brushes.White; |
||||
columns[0].RowHighlightBrush = null; |
||||
|
||||
// default is allowgrow = true and autosize = false
|
||||
columns[0].AllowGrow = false; |
||||
columns[1].AllowGrow = false; |
||||
columns[1].Width = 18; |
||||
columns[1].ColumnSeperatorColor = Color.Transparent; |
||||
columns[1].ColumnSeperatorColorInactive = Color.Transparent; |
||||
columns[2].AutoSize = true; |
||||
columns[2].MinimumWidth = 75; |
||||
columns[2].ColumnSeperatorColor = Color.White; |
||||
columns[2].ColumnSeperatorColorInactive = Color.FromArgb(172, 168, 153); |
||||
columns[3].AutoSize = true; |
||||
columns[3].MinimumWidth = 75; |
||||
} |
||||
|
||||
public DebuggerGridControl(DynamicTreeRow row) |
||||
{ |
||||
this.row = row; |
||||
|
||||
BeginUpdate(); |
||||
|
||||
AddColumns(Columns); |
||||
|
||||
Rows.Add(row); |
||||
|
||||
row.Expanded += delegate { isExpanded = true; }; |
||||
row.Collapsed += delegate { isExpanded = false; }; |
||||
|
||||
CreateControl(); |
||||
using (Graphics g = CreateGraphics()) { |
||||
this.Width = GetRequiredWidth(g); |
||||
} |
||||
this.Height = row.Height; |
||||
EndUpdate(); |
||||
} |
||||
|
||||
class TooltipForm : DynamicTreeRow.ChildForm |
||||
{ |
||||
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) |
||||
{ |
||||
if (base.ProcessCmdKey(ref msg, keyData)) { |
||||
return true; |
||||
} else { |
||||
Console.WriteLine("Handling " + keyData); |
||||
var window = Gui.WorkbenchSingleton.MainWindow; |
||||
foreach (System.Windows.Input.InputBinding inputBinding in window.InputBindings) { |
||||
if (inputBinding.Gesture.Matches(null, new System.Windows.Input.KeyEventArgs( |
||||
System.Windows.Input.Keyboard.PrimaryDevice, |
||||
System.Windows.PresentationSource.FromVisual(window), |
||||
0, |
||||
System.Windows.Input.KeyInterop.KeyFromVirtualKey((int)(keyData & ~Keys.Modifiers)) |
||||
))) { |
||||
if (inputBinding.Command.CanExecute(inputBinding.CommandParameter)) { |
||||
inputBinding.Command.Execute(inputBinding.CommandParameter); |
||||
return true; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
TooltipForm frm; |
||||
|
||||
public void ShowForm(ICSharpCode.TextEditor.TextArea textArea, TextLocation logicTextPos) |
||||
{ |
||||
frm = new TooltipForm(); |
||||
frm.AllowResizing = false; |
||||
frm.Owner = textArea.FindForm(); |
||||
int ypos = (textArea.Document.GetVisibleLine(logicTextPos.Y) + 1) * textArea.TextView.FontHeight - textArea.VirtualTop.Y; |
||||
Point p = new Point(0, ypos); |
||||
p = textArea.PointToScreen(p); |
||||
p.X = Control.MousePosition.X - 16; |
||||
p.Y -= 1; |
||||
frm.StartPosition = FormStartPosition.Manual; |
||||
frm.ShowInTaskbar = false; |
||||
frm.Location = p; |
||||
frm.ClientSize = new Size(Width + 2, row.Height + 2); |
||||
Dock = DockStyle.Fill; |
||||
frm.Controls.Add(this); |
||||
frm.ShowWindowWithoutActivation = true; |
||||
frm.Show(); |
||||
textArea.Click += OnTextAreaClick; |
||||
textArea.KeyDown += OnTextAreaClick; |
||||
frm.ClientSize = new Size(frm.ClientSize.Width, row.Height + 2); |
||||
} |
||||
|
||||
public bool IsMouseOver { |
||||
get { |
||||
if (frm != null && !frm.IsDisposed) { |
||||
return frm.ClientRectangle.Contains(frm.PointToClient(Control.MousePosition)); |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
void OnTextAreaClick(object sender, EventArgs e) |
||||
{ |
||||
((ICSharpCode.TextEditor.TextArea)sender).KeyDown -= OnTextAreaClick; |
||||
((ICSharpCode.TextEditor.TextArea)sender).Click -= OnTextAreaClick; |
||||
frm.Close(); |
||||
} |
||||
|
||||
bool isExpanded; |
||||
|
||||
public bool AllowClose { |
||||
get { |
||||
return !isExpanded; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,141 +0,0 @@
@@ -1,141 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Drawing; |
||||
using System.Windows.Forms; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Widgets.AutoHide |
||||
{ |
||||
public class AutoHideContainer: Panel |
||||
{ |
||||
protected Control control; |
||||
|
||||
bool autoHide = true; |
||||
bool showOverlay = false; |
||||
bool showOnMouseMove = true; |
||||
bool showOnMouseDown = true; |
||||
int activatorHeight = 1; |
||||
|
||||
protected bool mouseIn; |
||||
|
||||
public virtual bool AutoHide { |
||||
get { |
||||
return autoHide; |
||||
} |
||||
set { |
||||
autoHide = value; |
||||
Reformat(); |
||||
} |
||||
} |
||||
|
||||
public bool ShowOverlay { |
||||
get { |
||||
return showOverlay; |
||||
} |
||||
set { |
||||
showOverlay = value; |
||||
Reformat(); |
||||
} |
||||
} |
||||
|
||||
protected virtual void Reformat() |
||||
{ |
||||
if (autoHide) { |
||||
if (showOverlay) { |
||||
// Show as overlay
|
||||
this.Height = activatorHeight; |
||||
control.Dock = DockStyle.None; |
||||
control.Size = new Size(this.Width, control.PreferredSize.Height); |
||||
if (this.Dock != DockStyle.Bottom) { |
||||
control.Location = new Point(this.Left, this.Top); |
||||
} else { |
||||
control.Location = new Point(this.Left, this.Top - control.PreferredSize.Height + 1); |
||||
} |
||||
Parent.Controls.Add(control); |
||||
control.BringToFront(); |
||||
} else { |
||||
// Hidden
|
||||
this.Height = activatorHeight; |
||||
control.Dock = DockStyle.None; |
||||
control.Size = new Size(this.Width, 1); |
||||
control.Location = new Point(0, activatorHeight); |
||||
this.Controls.Add(control); |
||||
} |
||||
} else { |
||||
// Permanently shown
|
||||
this.Height = PreferredHeight; |
||||
control.Dock = DockStyle.Fill; |
||||
this.Controls.Add(control); |
||||
} |
||||
} |
||||
|
||||
protected virtual int PreferredHeight { |
||||
get { |
||||
return control.PreferredSize.Height; |
||||
} |
||||
} |
||||
|
||||
public AutoHideContainer(Control control) |
||||
{ |
||||
if (control == null) throw new ArgumentNullException("control"); |
||||
this.control = control; |
||||
this.MouseMove += delegate { if (showOnMouseMove) ShowOverlay = true; }; |
||||
this.MouseDown += delegate { if (showOnMouseDown) ShowOverlay = true; }; |
||||
control.MouseEnter += OnControlMouseEnter; |
||||
control.MouseLeave += OnControlMouseLeave; |
||||
Reformat(); |
||||
} |
||||
|
||||
protected virtual void OnControlMouseEnter(object sender, EventArgs e) |
||||
{ |
||||
mouseIn = true; |
||||
} |
||||
|
||||
protected virtual void OnControlMouseLeave(object sender, EventArgs e) |
||||
{ |
||||
mouseIn = false; |
||||
ShowOverlay = false; |
||||
} |
||||
|
||||
public bool ShowOnMouseMove { |
||||
get { |
||||
return showOnMouseMove; |
||||
} |
||||
set { |
||||
showOnMouseMove = value; |
||||
} |
||||
} |
||||
|
||||
public bool ShowOnMouseDown { |
||||
get { |
||||
return showOnMouseDown; |
||||
} |
||||
set { |
||||
showOnMouseDown = value; |
||||
} |
||||
} |
||||
|
||||
public Color ActivatorColor { |
||||
get { |
||||
return this.ForeColor; |
||||
} |
||||
set { |
||||
this.ForeColor = value; |
||||
} |
||||
} |
||||
|
||||
public int ActivatorHeight { |
||||
get { |
||||
return activatorHeight; |
||||
} |
||||
set { |
||||
activatorHeight = value; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,58 +0,0 @@
@@ -1,58 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Windows.Forms; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Widgets.AutoHide |
||||
{ |
||||
/// <summary>
|
||||
/// AutoHideMenuStripContainer can be used instead of MenuStrip to get a menu
|
||||
/// which is automaticaly hiden and shown. It is especially useful in fullscreen.
|
||||
/// </summary>
|
||||
public class AutoHideMenuStripContainer: AutoHideContainer |
||||
{ |
||||
protected bool dropDownOpened; |
||||
|
||||
Padding? defaultPadding; |
||||
|
||||
protected override void Reformat() |
||||
{ |
||||
if (defaultPadding == null) { |
||||
defaultPadding = ((MenuStrip)control).Padding; |
||||
} |
||||
((MenuStrip)control).Padding = AutoHide ? Padding.Empty : (Padding)defaultPadding; |
||||
base.Reformat(); |
||||
} |
||||
|
||||
public AutoHideMenuStripContainer(MenuStrip menuStrip):base(menuStrip) |
||||
{ |
||||
menuStrip.AutoSize = false; |
||||
menuStrip.ItemAdded += OnMenuItemAdded; |
||||
foreach(ToolStripMenuItem menuItem in menuStrip.Items) { |
||||
AddEventHandlersForItem(menuItem); |
||||
} |
||||
} |
||||
|
||||
void OnMenuItemAdded(object sender, EventArgs e) |
||||
{ |
||||
AddEventHandlersForItem((ToolStripMenuItem)sender); |
||||
} |
||||
|
||||
void AddEventHandlersForItem(ToolStripMenuItem menuItem) |
||||
{ |
||||
menuItem.DropDownOpened += delegate { dropDownOpened = true; }; |
||||
menuItem.DropDownClosed += delegate { dropDownOpened = false; if (!mouseIn) ShowOverlay = false; }; |
||||
} |
||||
|
||||
protected override void OnControlMouseLeave(object sender, EventArgs e) |
||||
{ |
||||
mouseIn = false; |
||||
if (!dropDownOpened) ShowOverlay = false; |
||||
} |
||||
} |
||||
} |
||||
@ -1,38 +0,0 @@
@@ -1,38 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Windows.Forms; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Widgets.AutoHide |
||||
{ |
||||
/// <summary>
|
||||
/// AutoHideStatusStripContainer can be used instead of StatusStrip to get a status strip
|
||||
/// which is automaticaly hiden and shown. It is especially useful in fullscreen.
|
||||
/// </summary>
|
||||
public class AutoHideStatusStripContainer: AutoHideContainer |
||||
{ |
||||
public AutoHideStatusStripContainer(StatusStrip statusStrip): base(statusStrip) |
||||
{ |
||||
statusStrip.AutoSize = false; |
||||
statusStrip.MouseMove += StatusStripMouseMove; |
||||
statusStrip.ItemAdded += delegate(object sender, ToolStripItemEventArgs e) { |
||||
e.Item.MouseMove += StatusStripMouseMove; |
||||
}; |
||||
foreach(ToolStripItem i in statusStrip.Items) { |
||||
i.MouseMove += StatusStripMouseMove; |
||||
} |
||||
} |
||||
|
||||
void StatusStripMouseMove(object sender, MouseEventArgs e) |
||||
{ |
||||
if (e.Y < control.Height / 2) { |
||||
ShowOverlay = false; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,37 +0,0 @@
@@ -1,37 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <author name="Daniel Grunwald"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Windows.Forms; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Widgets |
||||
{ |
||||
public static class DesignHelper |
||||
{ |
||||
static int shadowStatus; |
||||
|
||||
/// <summary>
|
||||
/// Adds a shadow to the create params if it is supported by the operating system.
|
||||
/// </summary>
|
||||
public static void AddShadowToWindow(CreateParams createParams) |
||||
{ |
||||
if (shadowStatus == 0) { |
||||
// Test OS version
|
||||
shadowStatus = -1; // shadow not supported
|
||||
if (Environment.OSVersion.Platform == PlatformID.Win32NT) { |
||||
Version ver = Environment.OSVersion.Version; |
||||
if (ver.Major > 5 || ver.Major == 5 && ver.Minor >= 1) { |
||||
shadowStatus = 1; |
||||
} |
||||
} |
||||
} |
||||
if (shadowStatus == 1) { |
||||
createParams.ClassStyle |= 0x00020000; // set CS_DROPSHADOW
|
||||
} |
||||
} |
||||
} |
||||
} |
||||
@ -1,99 +0,0 @@
@@ -1,99 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <author name="Markus Palme"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Windows.Forms; |
||||
using System.Drawing; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Widgets |
||||
{ |
||||
public class SpinnerControl : UserControl |
||||
{ |
||||
private int lines = 8; |
||||
private int current = 0; |
||||
private Timer timer; |
||||
|
||||
public SpinnerControl() |
||||
{ |
||||
SetStyle(ControlStyles.UserPaint, true); |
||||
SetStyle(ControlStyles.OptimizedDoubleBuffer, true); |
||||
SetStyle(ControlStyles.AllPaintingInWmPaint, true); |
||||
} |
||||
|
||||
public int Lines |
||||
{ |
||||
get |
||||
{ |
||||
return lines; |
||||
} |
||||
set |
||||
{ |
||||
this.lines = value; |
||||
} |
||||
} |
||||
|
||||
public void Start() |
||||
{ |
||||
timer = new Timer(); |
||||
timer.Interval = 100; |
||||
timer.Tick += new EventHandler(timer_Tick); |
||||
timer.Start(); |
||||
} |
||||
|
||||
void timer_Tick(object sender, EventArgs e) |
||||
{ |
||||
if (this.current >= this.lines - 1) |
||||
{ |
||||
this.current = 0; |
||||
} |
||||
else |
||||
{ |
||||
this.current++; |
||||
} |
||||
Invalidate(); |
||||
} |
||||
|
||||
public void Stop () |
||||
{ |
||||
timer.Stop(); |
||||
} |
||||
|
||||
protected override void OnPaint(PaintEventArgs e) |
||||
{ |
||||
double x, y; |
||||
double radius; |
||||
double half; |
||||
int i; |
||||
|
||||
x = Width / 2; |
||||
y = Height / 2; |
||||
radius = Math.Min(Width / 2, Height / 2) - 5; |
||||
half = lines / 2; |
||||
|
||||
for (i = 0; i < lines; i++) |
||||
{ |
||||
double inset = 0.7 * radius; |
||||
double t = (double)((i + lines - current) % lines) / lines; |
||||
|
||||
Color c = Color.FromArgb((int)(t * 255), 0, 0, 0); |
||||
Pen pen = new Pen(c); |
||||
pen.Width = 2; |
||||
|
||||
PointF start = new PointF((float)(x + (radius - inset) * Math.Cos(i * Math.PI / half)), |
||||
(float)(y + (radius - inset) * Math.Sin(i * Math.PI / half))); |
||||
|
||||
PointF end = new PointF((float)(x + radius * Math.Cos(i * Math.PI / half)), |
||||
(float)(y + radius * Math.Sin(i * Math.PI / half))); |
||||
|
||||
e.Graphics.DrawLine(pen, start, end); |
||||
pen.Dispose(); |
||||
} |
||||
|
||||
base.OnPaint(e); |
||||
} |
||||
} |
||||
} |
||||
@ -1,148 +0,0 @@
@@ -1,148 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Diagnostics; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Widgets.TreeGrid |
||||
{ |
||||
public class CollectionItemEventArgs<T> : EventArgs |
||||
{ |
||||
T item; |
||||
|
||||
public T Item { |
||||
get { |
||||
return item; |
||||
} |
||||
} |
||||
|
||||
public CollectionItemEventArgs(T item) |
||||
{ |
||||
this.item = item; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// A collection that fires events when items are added or removed.
|
||||
/// </summary>
|
||||
public sealed class CollectionWithEvents<T> : IList<T> |
||||
{ |
||||
List<T> list = new List<T>(); |
||||
public event EventHandler<CollectionItemEventArgs<T>> Added; |
||||
public event EventHandler<CollectionItemEventArgs<T>> Removed; |
||||
|
||||
void OnAdded(T item) |
||||
{ |
||||
if (Added != null) |
||||
Added(this, new CollectionItemEventArgs<T>(item)); |
||||
} |
||||
void OnRemoved(T item) |
||||
{ |
||||
if (Removed != null) |
||||
Removed(this, new CollectionItemEventArgs<T>(item)); |
||||
} |
||||
|
||||
public T this[int index] { |
||||
get { |
||||
return list[index]; |
||||
} |
||||
set { |
||||
T oldValue = list[index]; |
||||
if (!object.Equals(oldValue, value)) { |
||||
list[index] = value; |
||||
OnRemoved(oldValue); |
||||
OnAdded(value); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public int Count { |
||||
[DebuggerStepThrough] |
||||
get { |
||||
return list.Count; |
||||
} |
||||
} |
||||
|
||||
public bool IsReadOnly { |
||||
get { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
public int IndexOf(T item) |
||||
{ |
||||
return list.IndexOf(item); |
||||
} |
||||
|
||||
public void Insert(int index, T item) |
||||
{ |
||||
list.Insert(index, item); |
||||
OnAdded(item); |
||||
} |
||||
|
||||
public void RemoveAt(int index) |
||||
{ |
||||
T item = list[index]; |
||||
list.RemoveAt(index); |
||||
OnRemoved(item); |
||||
} |
||||
|
||||
public void Add(T item) |
||||
{ |
||||
list.Add(item); |
||||
OnAdded(item); |
||||
} |
||||
|
||||
public void AddRange(IEnumerable<T> range) |
||||
{ |
||||
foreach(T t in range) { |
||||
Add(t); |
||||
} |
||||
} |
||||
|
||||
public void Clear() |
||||
{ |
||||
List<T> oldList = list; |
||||
list = new List<T>(); |
||||
foreach (T item in oldList) { |
||||
OnRemoved(item); |
||||
} |
||||
} |
||||
|
||||
public bool Contains(T item) |
||||
{ |
||||
return list.Contains(item); |
||||
} |
||||
|
||||
public void CopyTo(T[] array, int arrayIndex) |
||||
{ |
||||
list.CopyTo(array, arrayIndex); |
||||
} |
||||
|
||||
public bool Remove(T item) |
||||
{ |
||||
if (list.Remove(item)) { |
||||
OnRemoved(item); |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
[DebuggerStepThrough] |
||||
public IEnumerator<T> GetEnumerator() |
||||
{ |
||||
return list.GetEnumerator(); |
||||
} |
||||
|
||||
[DebuggerStepThrough] |
||||
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() |
||||
{ |
||||
return list.GetEnumerator(); |
||||
} |
||||
} |
||||
} |
||||
@ -1,573 +0,0 @@
@@ -1,573 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.ComponentModel; |
||||
using System.Diagnostics; |
||||
using System.Drawing; |
||||
using System.Windows.Forms; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Widgets.TreeGrid |
||||
{ |
||||
public class DynamicList : UserControl, VerticalScrollContainer.IScrollable |
||||
{ |
||||
public const int MaxColumnCount = 1000; |
||||
|
||||
public DynamicList() |
||||
: this(new CollectionWithEvents<DynamicListColumn>(), new CollectionWithEvents<DynamicListRow>()) |
||||
{ |
||||
} |
||||
|
||||
public DynamicList(CollectionWithEvents<DynamicListColumn> columns, CollectionWithEvents<DynamicListRow> rows) |
||||
{ |
||||
inUpdate = true; |
||||
if (columns == null) |
||||
throw new ArgumentNullException("columns"); |
||||
if (rows == null) |
||||
throw new ArgumentNullException("rows"); |
||||
this.columns = columns; |
||||
this.rows = rows; |
||||
// we have to register our events on the existing items
|
||||
foreach (DynamicListColumn column in columns) { |
||||
OnColumnAdded(null, new CollectionItemEventArgs<DynamicListColumn>(column)); |
||||
} |
||||
foreach (DynamicListRow row in rows) { |
||||
OnRowAdded(null, new CollectionItemEventArgs<DynamicListRow>(row)); |
||||
} |
||||
columns.Added += OnColumnAdded; |
||||
columns.Removed += OnColumnRemoved; |
||||
rows.Added += OnRowAdded; |
||||
rows.Removed += OnRowRemoved; |
||||
this.BackColor = DefaultBackColor; |
||||
this.SetStyle(ControlStyles.UserPaint, true); |
||||
this.SetStyle(ControlStyles.Selectable, true); |
||||
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); |
||||
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); |
||||
inUpdate = false; |
||||
RecalculateColumnWidths(); |
||||
} |
||||
|
||||
public new static readonly Color DefaultBackColor = Color.White; |
||||
|
||||
protected override void Dispose(bool disposing) |
||||
{ |
||||
base.Dispose(disposing); |
||||
if (disposing) { |
||||
columns.Added -= OnColumnAdded; |
||||
columns.Removed -= OnColumnRemoved; |
||||
rows.Added -= OnRowAdded; |
||||
rows.Removed -= OnRowRemoved; |
||||
foreach (DynamicListColumn column in columns) { |
||||
OnColumnRemoved(null, new CollectionItemEventArgs<DynamicListColumn>(column)); |
||||
} |
||||
foreach (DynamicListRow row in rows) { |
||||
OnRowRemoved(null, new CollectionItemEventArgs<DynamicListRow>(row)); |
||||
} |
||||
} |
||||
} |
||||
|
||||
void OnColumnAdded(object sender, CollectionItemEventArgs<DynamicListColumn> e) |
||||
{ |
||||
e.Item.MinimumWidthChanged += ColumnMinimumWidthChanged; |
||||
e.Item.WidthChanged += ColumnWidthChanged; |
||||
RecalculateColumnWidths(); |
||||
} |
||||
|
||||
void OnColumnRemoved(object sender, CollectionItemEventArgs<DynamicListColumn> e) |
||||
{ |
||||
e.Item.MinimumWidthChanged -= ColumnMinimumWidthChanged; |
||||
e.Item.WidthChanged -= ColumnWidthChanged; |
||||
RecalculateColumnWidths(); |
||||
} |
||||
|
||||
void OnRowAdded(object sender, CollectionItemEventArgs<DynamicListRow> e) |
||||
{ |
||||
e.Item.HeightChanged += RowHeightChanged; |
||||
e.Item.ItemChanged += RowItemChanged; |
||||
if (Visible && Parent != null) |
||||
e.Item.NotifyListVisibilityChange(this, true); |
||||
} |
||||
|
||||
void OnRowRemoved(object sender, CollectionItemEventArgs<DynamicListRow> e) |
||||
{ |
||||
e.Item.HeightChanged -= RowHeightChanged; |
||||
e.Item.ItemChanged -= RowItemChanged; |
||||
if (Visible) |
||||
e.Item.NotifyListVisibilityChange(this, false); |
||||
} |
||||
|
||||
bool oldVisible = false; |
||||
|
||||
protected override void OnVisibleChanged(EventArgs e) |
||||
{ |
||||
base.OnVisibleChanged(e); |
||||
bool visible = Visible && Parent != null; |
||||
if (visible == oldVisible) |
||||
return; |
||||
oldVisible = visible; |
||||
foreach (DynamicListRow row in Rows) { |
||||
row.NotifyListVisibilityChange(this, visible); |
||||
} |
||||
} |
||||
|
||||
void ColumnMinimumWidthChanged(object sender, EventArgs e) |
||||
{ |
||||
RecalculateColumnWidths(); |
||||
} |
||||
|
||||
void RowHeightChanged(object sender, EventArgs e) |
||||
{ |
||||
Redraw(); |
||||
} |
||||
|
||||
void RowItemChanged(object sender, EventArgs e) |
||||
{ |
||||
Redraw(); |
||||
} |
||||
|
||||
bool inRecalculateColumnWidths; |
||||
bool inRecalculateNeedsRedraw; |
||||
|
||||
void RecalculateColumnWidths() |
||||
{ |
||||
if (inUpdate) return; |
||||
if (inRecalculateColumnWidths) return; |
||||
inRecalculateColumnWidths = true; |
||||
inRecalculateNeedsRedraw = false; |
||||
try { |
||||
int availableWidth = ClientSize.Width; |
||||
int minRequiredWidth = 0; |
||||
foreach (DynamicListColumn c in columns) { |
||||
if (c.AllowGrow) |
||||
minRequiredWidth += c.MinimumWidth; |
||||
else |
||||
availableWidth -= c.Width; |
||||
availableWidth -= 1; |
||||
} |
||||
// everyone gets c.MinimumWidth * availableWidth / minRequiredWidth
|
||||
foreach (DynamicListColumn c in columns) { |
||||
if (c.AllowGrow) |
||||
c.Width = Math.Max(2, c.MinimumWidth * availableWidth / minRequiredWidth); |
||||
} |
||||
} finally { |
||||
inRecalculateColumnWidths = false; |
||||
} |
||||
if (inRecalculateNeedsRedraw) { |
||||
Redraw(); |
||||
} |
||||
} |
||||
|
||||
void ColumnWidthChanged(object sender, EventArgs e) |
||||
{ |
||||
if (inRecalculateColumnWidths) { |
||||
inRecalculateNeedsRedraw = true; |
||||
return; |
||||
} |
||||
Redraw(); |
||||
} |
||||
|
||||
bool inUpdate; |
||||
|
||||
public void BeginUpdate() |
||||
{ |
||||
inUpdate = true; |
||||
} |
||||
|
||||
public void EndUpdate() |
||||
{ |
||||
inUpdate = false; |
||||
RecalculateColumnWidths(); |
||||
} |
||||
|
||||
void Redraw() |
||||
{ |
||||
if (inUpdate) return; |
||||
Invalidate(); |
||||
} |
||||
|
||||
List<Control> allowedControls = new List<Control>(); |
||||
List<Control> removedControls = new List<Control>(); |
||||
int scrollOffset = 0; |
||||
|
||||
public int ScrollOffset { |
||||
get { |
||||
return scrollOffset; |
||||
} |
||||
set { |
||||
if (scrollOffset != value) { |
||||
scrollOffset = value; |
||||
Redraw(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
int VerticalScrollContainer.IScrollable.ScrollOffsetY { |
||||
get { |
||||
return this.ScrollOffset; |
||||
} |
||||
set { |
||||
this.ScrollOffset = value; |
||||
} |
||||
} |
||||
|
||||
int VerticalScrollContainer.IScrollable.ScrollHeightY { |
||||
get { |
||||
return this.TotalRowHeight; |
||||
} |
||||
} |
||||
|
||||
public int GetRequiredWidth(Graphics graphics) |
||||
{ |
||||
int width = 0; |
||||
for (int i = 0; i < columns.Count; i++) { |
||||
if (columns[i].AutoSize) { |
||||
int minimumWidth = DynamicListColumn.DefaultWidth; |
||||
foreach (DynamicListRow row in Rows) { |
||||
DynamicListItem item = row[i]; |
||||
item.MeasureMinimumWidth(graphics, ref minimumWidth); |
||||
} |
||||
width += minimumWidth; |
||||
} else { |
||||
width += columns[i].Width; |
||||
} |
||||
width += 1; |
||||
} |
||||
return width; |
||||
} |
||||
|
||||
int lineMarginY = 0; |
||||
|
||||
public int LineMarginY { |
||||
get { |
||||
return lineMarginY; |
||||
} |
||||
set { |
||||
if (lineMarginY == value) |
||||
return; |
||||
lineMarginY = value; |
||||
Redraw(); |
||||
} |
||||
} |
||||
|
||||
bool inOnPaint; |
||||
|
||||
protected override void OnPaint(PaintEventArgs e) |
||||
{ |
||||
if (inOnPaint) { |
||||
Debug.WriteLine("Prevent nested OnPaint call"); |
||||
base.OnPaint(e); |
||||
return; |
||||
} |
||||
inOnPaint = true; |
||||
try { |
||||
DoPaint(e); |
||||
base.OnPaint(e); |
||||
} finally { |
||||
inOnPaint = false; |
||||
} |
||||
} |
||||
|
||||
void DoPaint(PaintEventArgs e) |
||||
{ |
||||
Debug.WriteLine("DynamicList.DoPaint"); |
||||
Graphics g = e.Graphics; |
||||
allowedControls.Clear(); |
||||
|
||||
int columnIndex = -1; |
||||
foreach (DynamicListColumn col in Columns) { |
||||
columnIndex += 1; |
||||
if (!col.AutoSize) |
||||
continue; |
||||
int minimumWidth = DynamicListColumn.DefaultWidth; |
||||
foreach (DynamicListRow row in Rows) { |
||||
DynamicListItem item = row[columnIndex]; |
||||
item.MeasureMinimumWidth(e.Graphics, ref minimumWidth); |
||||
} |
||||
col.MinimumWidth = minimumWidth; |
||||
} |
||||
|
||||
int controlIndex = 0; |
||||
int xPos; |
||||
int yPos = -scrollOffset; |
||||
Size clientSize = ClientSize; |
||||
foreach (DynamicListRow row in Rows) { |
||||
if (yPos + row.Height > 0 && yPos < clientSize.Height) { |
||||
xPos = 0; |
||||
for (columnIndex = 0; columnIndex < columns.Count; columnIndex++) { |
||||
DynamicListColumn col = columns[columnIndex]; |
||||
Rectangle rect = new Rectangle(xPos, yPos, col.Width, row.Height); |
||||
if (columnIndex == columns.Count - 1) |
||||
rect.Width = clientSize.Width - 1 - rect.Left; |
||||
DynamicListItem item = row[columnIndex]; |
||||
Control ctl = item.Control; |
||||
if (ctl != null) { |
||||
allowedControls.Add(ctl); |
||||
if (rect != ctl.Bounds) |
||||
ctl.Bounds = rect; |
||||
if (!this.Controls.Contains(ctl)) { |
||||
this.Controls.Add(ctl); |
||||
this.Controls.SetChildIndex(ctl, controlIndex); |
||||
} |
||||
controlIndex += 1; |
||||
} else { |
||||
item.PaintTo(e.Graphics, rect, this, col, item == itemAtMousePosition); |
||||
} |
||||
xPos += col.Width + 1; |
||||
} |
||||
} |
||||
yPos += row.Height + lineMarginY; |
||||
} |
||||
xPos = 0; |
||||
Form containerForm = FindForm(); |
||||
bool isFocused; |
||||
if (containerForm is IActivatable) |
||||
isFocused = (containerForm as IActivatable).IsActivated; |
||||
else |
||||
isFocused = this.Focused; |
||||
for (columnIndex = 0; columnIndex < columns.Count - 1; columnIndex++) { |
||||
DynamicListColumn col = columns[columnIndex]; |
||||
|
||||
xPos += col.Width + 1; |
||||
|
||||
Color separatorColor; |
||||
if (isFocused) { |
||||
separatorColor = col.ColumnSeperatorColor; |
||||
if (separatorColor.IsEmpty) |
||||
separatorColor = col.ColumnSeperatorColorInactive; |
||||
} else { |
||||
separatorColor = col.ColumnSeperatorColorInactive; |
||||
if (separatorColor.IsEmpty) |
||||
separatorColor = col.ColumnSeperatorColor; |
||||
} |
||||
if (separatorColor.IsEmpty) separatorColor = BackColor; |
||||
using (Pen separatorPen = new Pen(separatorColor)) { |
||||
e.Graphics.DrawLine(separatorPen, xPos - 1, 1, xPos - 1, Math.Min(clientSize.Height, yPos) - 2); |
||||
} |
||||
} |
||||
removedControls.Clear(); |
||||
foreach (Control ctl in Controls) { |
||||
if (!allowedControls.Contains(ctl)) |
||||
removedControls.Add(ctl); |
||||
} |
||||
foreach (Control ctl in removedControls) { |
||||
Debug.WriteLine("DynamicList Removing control"); |
||||
Controls.Remove(ctl); |
||||
Debug.WriteLine("DynamicList Control removed"); |
||||
} |
||||
allowedControls.Clear(); |
||||
removedControls.Clear(); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets if the parent form of this list is the active window.
|
||||
/// </summary>
|
||||
public bool IsActivated { |
||||
get { |
||||
Form containerForm = FindForm(); |
||||
if (containerForm is IActivatable) |
||||
return (containerForm as IActivatable).IsActivated; |
||||
else |
||||
return this.Focused; |
||||
} |
||||
} |
||||
|
||||
protected override void OnSizeChanged(EventArgs e) |
||||
{ |
||||
base.OnSizeChanged(e); |
||||
RecalculateColumnWidths(); |
||||
} |
||||
|
||||
public DynamicListRow GetRowFromPoint(int yPos) |
||||
{ |
||||
int y = -scrollOffset; |
||||
foreach (DynamicListRow row in Rows) { |
||||
if (yPos < y) |
||||
break; |
||||
if (yPos <= y + row.Height) |
||||
return row; |
||||
y += row.Height + lineMarginY; |
||||
} |
||||
return null; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the upper left corner of the specified row.
|
||||
/// </summary>
|
||||
public Point GetPositionFromRow(DynamicListRow row) |
||||
{ |
||||
int y = -scrollOffset; |
||||
foreach (DynamicListRow r in Rows) { |
||||
if (r == row) |
||||
return new Point(0, y); |
||||
y += r.Height + lineMarginY; |
||||
} |
||||
throw new ArgumentException("The row in not in this list!"); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets the height of all rows.
|
||||
/// </summary>
|
||||
public int TotalRowHeight { |
||||
get { |
||||
int y = 0; |
||||
foreach (DynamicListRow r in Rows) { |
||||
y += r.Height + lineMarginY; |
||||
} |
||||
return y; |
||||
} |
||||
} |
||||
|
||||
public int GetColumnIndexFromPoint(int xPos) |
||||
{ |
||||
int columnIndex = 0; |
||||
int x = 0; |
||||
foreach (DynamicListColumn col in Columns) { |
||||
if (xPos < x) |
||||
break; |
||||
if (xPos <= x + col.Width) |
||||
return columnIndex; |
||||
x += col.Width + 1; |
||||
columnIndex += 1; |
||||
} |
||||
return -1; |
||||
} |
||||
|
||||
public DynamicListItem GetItemFromPoint(Point position) |
||||
{ |
||||
DynamicListRow row = GetRowFromPoint(position.Y); |
||||
if (row == null) |
||||
return null; |
||||
int columnIndex = GetColumnIndexFromPoint(position.X); |
||||
if (columnIndex < 0) |
||||
return null; |
||||
return row[columnIndex]; |
||||
} |
||||
|
||||
protected override void OnClick(EventArgs e) |
||||
{ |
||||
base.OnClick(e); |
||||
DynamicListItem item = GetItemFromPoint(PointToClient(Control.MousePosition)); |
||||
if (item != null) item.PerformClick(this); |
||||
} |
||||
|
||||
protected override void OnDoubleClick(EventArgs e) |
||||
{ |
||||
base.OnDoubleClick(e); |
||||
DynamicListItem item = GetItemFromPoint(PointToClient(Control.MousePosition)); |
||||
if (item != null) item.PerformDoubleClick(this); |
||||
} |
||||
|
||||
protected override void OnMouseHover(EventArgs e) |
||||
{ |
||||
base.OnMouseHover(e); |
||||
DynamicListItem item = GetItemFromPoint(PointToClient(Control.MousePosition)); |
||||
if (item != null) item.OnMouseHover(this); |
||||
} |
||||
|
||||
DynamicListItem itemAtMousePosition; |
||||
DynamicListRow rowAtMousePosition; |
||||
|
||||
public DynamicListItem ItemAtMousePosition { |
||||
get { |
||||
return itemAtMousePosition; |
||||
} |
||||
} |
||||
|
||||
public DynamicListRow RowAtMousePosition { |
||||
get { |
||||
return rowAtMousePosition; |
||||
} |
||||
} |
||||
|
||||
protected override void OnMouseMove(MouseEventArgs e) |
||||
{ |
||||
base.OnMouseMove(e); |
||||
DynamicListRow row = GetRowFromPoint(e.Y); |
||||
if (rowAtMousePosition != row) { |
||||
rowAtMousePosition = row; |
||||
Invalidate(); |
||||
} |
||||
if (row == null) |
||||
return; |
||||
int columnIndex = GetColumnIndexFromPoint(e.X); |
||||
if (columnIndex < 0) |
||||
return; |
||||
DynamicListItem item = row[columnIndex]; |
||||
if (itemAtMousePosition != item) { |
||||
if (itemAtMousePosition != null) { |
||||
OnLeaveItem(itemAtMousePosition); |
||||
} |
||||
ResetMouseEventArgs(); // raise hover again
|
||||
itemAtMousePosition = item; |
||||
if (item != null) { |
||||
if (item.Cursor != null) |
||||
this.Cursor = item.Cursor; |
||||
item.OnMouseEnter(this); |
||||
} |
||||
} |
||||
if (item != null) { |
||||
item.OnMouseMove(new DynamicListMouseEventArgs(this, e)); |
||||
} |
||||
} |
||||
|
||||
protected override void OnMouseDown(MouseEventArgs e) |
||||
{ |
||||
base.OnMouseDown(e); |
||||
DynamicListItem item = GetItemFromPoint(e.Location); |
||||
if (item != null) item.OnMouseDown(new DynamicListMouseEventArgs(this, e)); |
||||
} |
||||
|
||||
protected override void OnMouseUp(MouseEventArgs e) |
||||
{ |
||||
base.OnMouseUp(e); |
||||
DynamicListItem item = GetItemFromPoint(e.Location); |
||||
if (item != null) item.OnMouseUp(new DynamicListMouseEventArgs(this, e)); |
||||
} |
||||
|
||||
protected override void OnMouseLeave(EventArgs e) |
||||
{ |
||||
rowAtMousePosition = null; |
||||
if (itemAtMousePosition != null) { |
||||
OnLeaveItem(itemAtMousePosition); |
||||
itemAtMousePosition = null; |
||||
} |
||||
base.OnMouseLeave(e); |
||||
} |
||||
|
||||
protected virtual void OnLeaveItem(DynamicListItem item) |
||||
{ |
||||
itemAtMousePosition.OnMouseLeave(this); |
||||
this.Cursor = Cursors.Default; |
||||
} |
||||
|
||||
readonly CollectionWithEvents<DynamicListColumn> columns; |
||||
readonly CollectionWithEvents<DynamicListRow> rows; |
||||
|
||||
public CollectionWithEvents<DynamicListColumn> Columns { |
||||
[DebuggerStepThrough] |
||||
get { |
||||
return columns; |
||||
} |
||||
} |
||||
|
||||
[Browsable(false)] |
||||
public CollectionWithEvents<DynamicListRow> Rows { |
||||
[DebuggerStepThrough] |
||||
get { |
||||
return rows; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public interface IActivatable |
||||
{ |
||||
bool IsActivated { get; } |
||||
event EventHandler Activated; |
||||
event EventHandler Deactivate; |
||||
} |
||||
} |
||||
@ -1,158 +0,0 @@
@@ -1,158 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Drawing; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Widgets.TreeGrid |
||||
{ |
||||
public class DynamicListColumn : ICloneable |
||||
{ |
||||
public const int DefaultWidth = 16; |
||||
|
||||
int width = DefaultWidth; |
||||
int minimumWidth = DefaultWidth; |
||||
bool allowGrow = true; |
||||
bool autoSize = false; |
||||
|
||||
public static readonly Color DefaultBackColor = Color.FromArgb(247, 245, 233); |
||||
public static readonly Brush DefaultBackBrush = new SolidBrush(DefaultBackColor); |
||||
public static readonly Color DefaultRowHighlightBackColor = Color.FromArgb(221, 218, 203); |
||||
public static readonly Brush DefaultRowHighlightBrush = new SolidBrush(DefaultRowHighlightBackColor); |
||||
public static readonly Color DefaultInactiveBackColor = Color.FromArgb(242, 240, 228); |
||||
public static readonly Brush DefaultInactiveBackBrush = new SolidBrush(DefaultInactiveBackColor); |
||||
|
||||
Brush backgroundBrush = DefaultBackBrush; |
||||
Brush backgroundBrushInactive = DefaultInactiveBackBrush; |
||||
Brush rowHighlightBrush = DefaultRowHighlightBrush; |
||||
|
||||
public virtual DynamicListColumn Clone() |
||||
{ |
||||
return (DynamicListColumn)base.MemberwiseClone(); |
||||
} |
||||
|
||||
object ICloneable.Clone() |
||||
{ |
||||
return this.Clone(); |
||||
} |
||||
|
||||
#region Properties
|
||||
public int MinimumWidth { |
||||
get { |
||||
return minimumWidth; |
||||
} |
||||
set { |
||||
if (value < 2) |
||||
throw new ArgumentOutOfRangeException("value", value, "MinimumWidth must be at least 2"); |
||||
if (minimumWidth != value) { |
||||
minimumWidth = value; |
||||
if (MinimumWidthChanged != null) { |
||||
MinimumWidthChanged(this, EventArgs.Empty); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public event EventHandler MinimumWidthChanged; |
||||
|
||||
public int Width { |
||||
get { |
||||
return width; |
||||
} |
||||
set { |
||||
if (value < 2) |
||||
throw new ArgumentOutOfRangeException("value", value, "Width must be at least 2"); |
||||
if (width != value) { |
||||
width = value; |
||||
if (WidthChanged != null) { |
||||
WidthChanged(this, EventArgs.Empty); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
public event EventHandler WidthChanged; |
||||
|
||||
public bool AllowGrow { |
||||
get { |
||||
return allowGrow; |
||||
} |
||||
set { |
||||
allowGrow = value; |
||||
} |
||||
} |
||||
|
||||
public bool AutoSize { |
||||
get { |
||||
return autoSize; |
||||
} |
||||
set { |
||||
autoSize = value; |
||||
} |
||||
} |
||||
|
||||
public Brush BackgroundBrush { |
||||
get { |
||||
return backgroundBrush; |
||||
} |
||||
set { |
||||
if (value == null) |
||||
throw new ArgumentNullException("value"); |
||||
backgroundBrush = value; |
||||
} |
||||
} |
||||
|
||||
public Brush BackgroundBrushInactive { |
||||
get { |
||||
return backgroundBrushInactive; |
||||
} |
||||
set { |
||||
if (value == null) |
||||
throw new ArgumentNullException("value"); |
||||
backgroundBrushInactive = value; |
||||
} |
||||
} |
||||
|
||||
public Brush RowHighlightBrush { |
||||
get { |
||||
return rowHighlightBrush; |
||||
} |
||||
set { |
||||
rowHighlightBrush = value; |
||||
} |
||||
} |
||||
|
||||
Color columnSeperatorColor = Color.Empty; |
||||
|
||||
/// <summary>
|
||||
/// Sets the color that is used to the right of this column as separator color.
|
||||
/// </summary>
|
||||
public Color ColumnSeperatorColor { |
||||
get { |
||||
return columnSeperatorColor; |
||||
} |
||||
set { |
||||
columnSeperatorColor = value; |
||||
} |
||||
} |
||||
|
||||
Color columnSeperatorColorInactive = Color.Empty; |
||||
|
||||
/// <summary>
|
||||
/// Sets the color that is used to the right of this column as separator color.
|
||||
/// </summary>
|
||||
public Color ColumnSeperatorColorInactive { |
||||
get { |
||||
return columnSeperatorColorInactive; |
||||
} |
||||
set { |
||||
columnSeperatorColorInactive = value; |
||||
} |
||||
} |
||||
#endregion
|
||||
} |
||||
} |
||||
@ -1,502 +0,0 @@
@@ -1,502 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
using System.Drawing; |
||||
using System.Windows.Forms; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Widgets.TreeGrid |
||||
{ |
||||
public sealed class DynamicListItem |
||||
{ |
||||
DynamicListRow row; |
||||
|
||||
internal DynamicListItem(DynamicListRow row) |
||||
{ |
||||
this.row = row; |
||||
} |
||||
|
||||
public void RaiseItemChanged() |
||||
{ |
||||
row.RaiseItemChanged(this); |
||||
} |
||||
|
||||
Cursor cursor; |
||||
|
||||
public DynamicListRow Row { |
||||
get { |
||||
return row; |
||||
} |
||||
} |
||||
|
||||
public Cursor Cursor { |
||||
get { |
||||
return cursor; |
||||
} |
||||
set { |
||||
cursor = value; |
||||
} |
||||
} |
||||
|
||||
#region BackgroundBrush / Control
|
||||
Brush backgroundBrush; |
||||
|
||||
public Brush BackgroundBrush { |
||||
get { |
||||
return backgroundBrush; |
||||
} |
||||
set { |
||||
if (backgroundBrush != value) { |
||||
backgroundBrush = value; |
||||
RaiseItemChanged(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
Brush backgroundBrushInactive; |
||||
|
||||
public Brush BackgroundBrushInactive { |
||||
get { |
||||
return backgroundBrushInactive; |
||||
} |
||||
set { |
||||
if (backgroundBrushInactive != value) { |
||||
backgroundBrushInactive = value; |
||||
RaiseItemChanged(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
Brush highlightBrush; |
||||
|
||||
public Brush HighlightBrush { |
||||
get { |
||||
return highlightBrush; |
||||
} |
||||
set { |
||||
if (highlightBrush != value) { |
||||
highlightBrush = value; |
||||
RaiseItemChanged(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
Control control; |
||||
|
||||
public Control Control { |
||||
get { |
||||
return control; |
||||
} |
||||
set { |
||||
if (control != value) { |
||||
control = value; |
||||
RaiseItemChanged(); |
||||
} |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
#region MeasureWidth / Paint
|
||||
public event EventHandler<MeasureWidthEventArgs> MeasureWidth; |
||||
|
||||
internal void MeasureMinimumWidth(Graphics graphics, ref int minimumWidth) |
||||
{ |
||||
if (MeasureWidth != null) { |
||||
MeasureWidthEventArgs e = new MeasureWidthEventArgs(graphics); |
||||
MeasureWidth(this, e); |
||||
minimumWidth = Math.Max(minimumWidth, e.ItemWidth); |
||||
} |
||||
if (text.Length > 0) { |
||||
// Prevent GDI exception (forum-12284) when text is very long
|
||||
if (text.Length > short.MaxValue) { |
||||
text = text.Substring(0, short.MaxValue - 1); |
||||
} |
||||
int width = 2 + (int)graphics.MeasureString(text, font, new PointF(0, 0), textFormat).Width; |
||||
minimumWidth = Math.Max(minimumWidth, width); |
||||
} |
||||
} |
||||
|
||||
public event EventHandler<ItemPaintEventArgs> Paint; |
||||
|
||||
internal void PaintTo(Graphics g, Rectangle rectangle, DynamicList list, DynamicListColumn column, bool isMouseEntered) |
||||
{ |
||||
Rectangle fillRectangle = rectangle; |
||||
fillRectangle.Width += 1; |
||||
if (highlightBrush != null && isMouseEntered) { |
||||
g.FillRectangle(highlightBrush, fillRectangle); |
||||
} else { |
||||
bool isActivated = list.IsActivated; |
||||
Brush bgBrush = GetBrush(isActivated, backgroundBrush, backgroundBrushInactive); |
||||
if (bgBrush == null) { |
||||
bgBrush = GetBrush(isActivated, column.BackgroundBrush, column.BackgroundBrushInactive); |
||||
if (isActivated && list.RowAtMousePosition == row && column.RowHighlightBrush != null) |
||||
bgBrush = column.RowHighlightBrush; |
||||
} |
||||
g.FillRectangle(bgBrush, fillRectangle); |
||||
} |
||||
if (Paint != null) { |
||||
Paint(this, new ItemPaintEventArgs(g, rectangle, fillRectangle, list, column, this, isMouseEntered)); |
||||
} |
||||
if (text.Length > 0) { |
||||
g.DrawString(text, font, textBrush, rectangle, textFormat); |
||||
} |
||||
} |
||||
|
||||
Brush GetBrush(bool isActive, Brush activeBrush, Brush inactiveBrush) |
||||
{ |
||||
return isActive ? (activeBrush ?? inactiveBrush) : (inactiveBrush ?? activeBrush); |
||||
} |
||||
#endregion
|
||||
|
||||
#region Text drawing
|
||||
string text = string.Empty; |
||||
|
||||
public string Text { |
||||
get { |
||||
return text; |
||||
} |
||||
set { |
||||
if (value == null) |
||||
throw new ArgumentNullException("value", "Use string.Empty instead of null!"); |
||||
if (text != value) { |
||||
text = value; |
||||
RaiseItemChanged(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
Font font = Control.DefaultFont; |
||||
|
||||
public Font Font { |
||||
get { |
||||
return font; |
||||
} |
||||
set { |
||||
if (value == null) |
||||
throw new ArgumentNullException("value"); |
||||
if (font != value) { |
||||
font = value; |
||||
RaiseItemChanged(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
Brush textBrush = SystemBrushes.ControlText; |
||||
|
||||
public Brush TextBrush { |
||||
get { |
||||
return textBrush; |
||||
} |
||||
set { |
||||
if (value == null) |
||||
throw new ArgumentNullException("value"); |
||||
if (textBrush != value) { |
||||
textBrush = value; |
||||
RaiseItemChanged(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
static StringFormat defaultTextFormat; |
||||
|
||||
public static StringFormat DefaultTextFormat { |
||||
get { |
||||
if (defaultTextFormat == null) { |
||||
defaultTextFormat = (StringFormat)StringFormat.GenericDefault.Clone(); |
||||
defaultTextFormat.FormatFlags |= StringFormatFlags.NoWrap; |
||||
} |
||||
return defaultTextFormat; |
||||
} |
||||
} |
||||
|
||||
StringFormat textFormat = DefaultTextFormat; |
||||
|
||||
public StringFormat TextFormat { |
||||
get { |
||||
return textFormat; |
||||
} |
||||
set { |
||||
if (value == null) |
||||
throw new ArgumentNullException("value"); |
||||
if (textFormat != value) { |
||||
textFormat = value; |
||||
RaiseItemChanged(); |
||||
} |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
#region Mouse Events
|
||||
public event EventHandler<DynamicListEventArgs> Click; |
||||
|
||||
public void PerformClick(DynamicList list) |
||||
{ |
||||
if (Click != null) |
||||
Click(this, new DynamicListEventArgs(list)); |
||||
HandleLabelEditClick(list); |
||||
} |
||||
|
||||
public event EventHandler<DynamicListEventArgs> DoubleClick; |
||||
|
||||
public void PerformDoubleClick(DynamicList list) |
||||
{ |
||||
if (DoubleClick != null) |
||||
DoubleClick(this, new DynamicListEventArgs(list)); |
||||
} |
||||
|
||||
public event EventHandler<DynamicListEventArgs> MouseHover; |
||||
|
||||
internal void OnMouseHover(DynamicList list) |
||||
{ |
||||
if (MouseHover != null) { |
||||
MouseHover(this, new DynamicListEventArgs(list)); |
||||
} |
||||
} |
||||
|
||||
public event EventHandler<DynamicListEventArgs> MouseLeave; |
||||
|
||||
internal void OnMouseLeave(DynamicList list) |
||||
{ |
||||
if (MouseLeave != null) { |
||||
MouseLeave(this, new DynamicListEventArgs(list)); |
||||
} |
||||
if (highlightBrush != null) RaiseItemChanged(); |
||||
} |
||||
|
||||
public event EventHandler<DynamicListEventArgs> MouseEnter; |
||||
|
||||
internal void OnMouseEnter(DynamicList list) |
||||
{ |
||||
if (MouseEnter != null) { |
||||
MouseEnter(this, new DynamicListEventArgs(list)); |
||||
} |
||||
if (highlightBrush != null) RaiseItemChanged(); |
||||
} |
||||
|
||||
public event EventHandler<DynamicListMouseEventArgs> MouseMove; |
||||
|
||||
internal void OnMouseMove(DynamicListMouseEventArgs e) |
||||
{ |
||||
if (MouseMove != null) { |
||||
MouseMove(this, e); |
||||
} |
||||
} |
||||
|
||||
public event EventHandler<DynamicListMouseEventArgs> MouseDown; |
||||
|
||||
internal void OnMouseDown(DynamicListMouseEventArgs e) |
||||
{ |
||||
if (MouseDown != null) { |
||||
MouseDown(this, e); |
||||
} |
||||
} |
||||
|
||||
public event EventHandler<DynamicListMouseEventArgs> MouseUp; |
||||
|
||||
internal void OnMouseUp(DynamicListMouseEventArgs e) |
||||
{ |
||||
if (MouseUp != null) { |
||||
MouseUp(this, e); |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
#region Label editing
|
||||
bool allowLabelEdit; |
||||
|
||||
public bool AllowLabelEdit { |
||||
get { |
||||
return allowLabelEdit; |
||||
} |
||||
set { |
||||
allowLabelEdit = value; |
||||
} |
||||
} |
||||
|
||||
public event EventHandler<DynamicListEventArgs> BeginLabelEdit; |
||||
public event EventHandler<DynamicListEventArgs> FinishLabelEdit; |
||||
public event EventHandler<DynamicListEventArgs> CanceledLabelEdit; |
||||
|
||||
void HandleLabelEditClick(DynamicList list) |
||||
{ |
||||
if (!allowLabelEdit) |
||||
return; |
||||
TextBox txt = new TextBox(); |
||||
txt.Text = this.Text; |
||||
AssignControlUntilFocusChange(txt); |
||||
if (BeginLabelEdit != null) |
||||
BeginLabelEdit(this, new DynamicListEventArgs(list)); |
||||
bool escape = false; |
||||
txt.KeyDown += delegate(object sender2, KeyEventArgs e2) { |
||||
if (e2.KeyData == Keys.Enter || e2.KeyData == Keys.Escape) { |
||||
e2.Handled = true; |
||||
if (e2.KeyData == Keys.Escape) { |
||||
if (CanceledLabelEdit != null) |
||||
CanceledLabelEdit(this, new DynamicListEventArgs(list)); |
||||
escape = true; |
||||
} |
||||
this.Control = null; |
||||
txt.Dispose(); |
||||
} |
||||
}; |
||||
txt.LostFocus += delegate { |
||||
if (!escape) { |
||||
this.Text = txt.Text; |
||||
if (FinishLabelEdit != null) |
||||
FinishLabelEdit(this, new DynamicListEventArgs(list)); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Display the control for this item. Automatically assign focus to the control
|
||||
/// and removes+disposes the control when it looses focus.
|
||||
/// </summary>
|
||||
public void AssignControlUntilFocusChange(Control control) |
||||
{ |
||||
MethodInvoker method = delegate { |
||||
if (!control.Focus()) { |
||||
control.Focus(); |
||||
} |
||||
control.LostFocus += delegate { |
||||
this.Control = null; |
||||
control.Dispose(); |
||||
}; |
||||
}; |
||||
|
||||
control.HandleCreated += delegate { |
||||
control.BeginInvoke(method); |
||||
}; |
||||
this.Control = control; |
||||
} |
||||
#endregion
|
||||
} |
||||
|
||||
public class DynamicListEventArgs : EventArgs |
||||
{ |
||||
DynamicList list; |
||||
|
||||
public DynamicList List { |
||||
[DebuggerStepThrough] |
||||
get { |
||||
return list; |
||||
} |
||||
} |
||||
|
||||
public DynamicListEventArgs(DynamicList list) |
||||
{ |
||||
if (list == null) throw new ArgumentNullException("list"); |
||||
this.list = list; |
||||
} |
||||
} |
||||
|
||||
public class DynamicListMouseEventArgs : MouseEventArgs |
||||
{ |
||||
DynamicList list; |
||||
|
||||
public DynamicList List { |
||||
[DebuggerStepThrough] |
||||
get { |
||||
return list; |
||||
} |
||||
} |
||||
|
||||
public DynamicListMouseEventArgs(DynamicList list, MouseEventArgs me) |
||||
: base(me.Button, me.Clicks, me.X, me.Y, me.Delta) |
||||
{ |
||||
if (list == null) throw new ArgumentNullException("list"); |
||||
this.list = list; |
||||
} |
||||
} |
||||
|
||||
public class MeasureWidthEventArgs : EventArgs |
||||
{ |
||||
Graphics graphics; |
||||
|
||||
public Graphics Graphics { |
||||
get { |
||||
return graphics; |
||||
} |
||||
} |
||||
|
||||
int itemWidth; |
||||
|
||||
public int ItemWidth { |
||||
get { |
||||
return itemWidth; |
||||
} |
||||
set { |
||||
itemWidth = value; |
||||
} |
||||
} |
||||
|
||||
public MeasureWidthEventArgs(Graphics graphics) |
||||
{ |
||||
if (graphics == null) |
||||
throw new ArgumentNullException("graphics"); |
||||
this.graphics = graphics; |
||||
} |
||||
} |
||||
|
||||
public class ItemPaintEventArgs : PaintEventArgs |
||||
{ |
||||
DynamicList list; |
||||
DynamicListColumn column; |
||||
DynamicListItem item; |
||||
bool isMouseEntered; |
||||
Rectangle fillRectangle; |
||||
|
||||
public Rectangle FillRectangle { |
||||
get { |
||||
return fillRectangle; |
||||
} |
||||
} |
||||
|
||||
public DynamicList List { |
||||
get { |
||||
return list; |
||||
} |
||||
} |
||||
|
||||
public DynamicListColumn Column { |
||||
get { |
||||
return column; |
||||
} |
||||
} |
||||
|
||||
public DynamicListRow Row { |
||||
get { |
||||
return item.Row; |
||||
} |
||||
} |
||||
|
||||
public DynamicListItem Item { |
||||
get { |
||||
return item; |
||||
} |
||||
} |
||||
|
||||
public bool IsMouseEntered { |
||||
get { |
||||
return isMouseEntered; |
||||
} |
||||
} |
||||
|
||||
public ItemPaintEventArgs(Graphics graphics, Rectangle rectangle, Rectangle fillRectangle, |
||||
DynamicList list, DynamicListColumn column, |
||||
DynamicListItem item, bool isMouseEntered) |
||||
: base(graphics, rectangle) |
||||
{ |
||||
this.fillRectangle = fillRectangle; |
||||
this.list = list; |
||||
this.column = column; |
||||
this.item = item; |
||||
this.isMouseEntered = isMouseEntered; |
||||
} |
||||
} |
||||
} |
||||
@ -1,107 +0,0 @@
@@ -1,107 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Diagnostics; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Widgets.TreeGrid |
||||
{ |
||||
public class DynamicListRow |
||||
{ |
||||
int height = 16; |
||||
|
||||
public int Height { |
||||
get { |
||||
return height; |
||||
} |
||||
set { |
||||
if (value < 2) |
||||
throw new ArgumentOutOfRangeException("value", value, "value must be at least 2"); |
||||
if (height != value) { |
||||
height = value; |
||||
OnHeightChanged(EventArgs.Empty); |
||||
} |
||||
} |
||||
} |
||||
|
||||
public event EventHandler HeightChanged; |
||||
|
||||
protected virtual void OnHeightChanged(EventArgs e) |
||||
{ |
||||
if (HeightChanged != null) { |
||||
HeightChanged(this, e); |
||||
} |
||||
} |
||||
|
||||
public event EventHandler<DynamicListEventArgs> Shown; |
||||
public event EventHandler<DynamicListEventArgs> Hidden; |
||||
|
||||
protected virtual void OnShown(DynamicListEventArgs e) |
||||
{ |
||||
if (Shown != null) { |
||||
Shown(this, e); |
||||
} |
||||
} |
||||
|
||||
protected virtual void OnHidden(DynamicListEventArgs e) |
||||
{ |
||||
if (Hidden != null) { |
||||
Hidden(this, e); |
||||
} |
||||
} |
||||
|
||||
internal void NotifyListVisibilityChange(DynamicList list, bool visible) |
||||
{ |
||||
if (visible) |
||||
OnShown(new DynamicListEventArgs(list)); |
||||
else |
||||
OnHidden(new DynamicListEventArgs(list)); |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Fired when any item has changed.
|
||||
/// </summary>
|
||||
public event EventHandler ItemChanged; |
||||
|
||||
protected virtual void OnItemChanged(EventArgs e) |
||||
{ |
||||
if (ItemChanged != null) { |
||||
ItemChanged(this, e); |
||||
} |
||||
} |
||||
|
||||
internal void RaiseItemChanged(DynamicListItem item) |
||||
{ |
||||
OnItemChanged(EventArgs.Empty); |
||||
} |
||||
|
||||
DynamicListItem[] items = new DynamicListItem[10]; |
||||
|
||||
public DynamicListItem this[int columnIndex] { |
||||
[DebuggerStepThrough] |
||||
get { |
||||
if (columnIndex < 0) |
||||
throw new ArgumentOutOfRangeException("columnIndex", columnIndex, "columnIndex must be >= 0"); |
||||
if (columnIndex > DynamicList.MaxColumnCount) |
||||
throw new ArgumentOutOfRangeException("columnIndex", columnIndex, "columnIndex must be <= " + DynamicList.MaxColumnCount); |
||||
if (columnIndex >= items.Length) { |
||||
Array.Resize(ref items, columnIndex * 2 + 1); |
||||
} |
||||
DynamicListItem item = items[columnIndex]; |
||||
if (item == null) { |
||||
items[columnIndex] = item = CreateItem(); |
||||
} |
||||
return item; |
||||
} |
||||
} |
||||
|
||||
protected virtual DynamicListItem CreateItem() |
||||
{ |
||||
return new DynamicListItem(this); |
||||
} |
||||
} |
||||
} |
||||
@ -1,461 +0,0 @@
@@ -1,461 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Drawing; |
||||
using System.Drawing.Drawing2D; |
||||
using System.Windows.Forms; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Widgets.TreeGrid |
||||
{ |
||||
public class DynamicTreeRow : DynamicListRow |
||||
{ |
||||
CollectionWithEvents<DynamicListColumn> childColumns = new CollectionWithEvents<DynamicListColumn>(); |
||||
CollectionWithEvents<DynamicListRow> childRows = new CollectionWithEvents<DynamicListRow>(); |
||||
|
||||
DynamicListItem plus; |
||||
|
||||
public DynamicTreeRow() |
||||
{ |
||||
plus = this[0]; |
||||
ShowPlus = true; |
||||
} |
||||
|
||||
#region Plus painting
|
||||
bool showPlus; |
||||
|
||||
public bool ShowPlus { |
||||
get { |
||||
return showPlus; |
||||
} |
||||
set { |
||||
if (showPlus == value) |
||||
return; |
||||
showPlus = value; |
||||
plus.HighlightBrush = showPlus ? Brushes.AliceBlue : null; |
||||
plus.Cursor = showPlus ? Cursors.Hand : null; |
||||
if (showPlus) { |
||||
plus.Click += OnPlusClick; |
||||
plus.Paint += OnPlusPaint; |
||||
} else { |
||||
plus.Click -= OnPlusClick; |
||||
plus.Paint -= OnPlusPaint; |
||||
} |
||||
OnShowPlusChanged(EventArgs.Empty); |
||||
} |
||||
} |
||||
|
||||
static readonly Color PlusBorder = Color.FromArgb(120, 152, 181); |
||||
static readonly Color LightPlusBorder = Color.FromArgb(176, 194, 221); |
||||
public static readonly Color DefaultExpandedRowColor = Color.FromArgb(235, 229, 209); |
||||
|
||||
public static void DrawPlusSign(Graphics graphics, Rectangle r, bool drawMinus) |
||||
{ |
||||
using (Brush b = new LinearGradientBrush(r, Color.White, DynamicListColumn.DefaultRowHighlightBackColor, 66f)) { |
||||
graphics.FillRectangle(b, r); |
||||
} |
||||
using (Pen p = new Pen(PlusBorder)) { |
||||
graphics.DrawRectangle(p, r); |
||||
} |
||||
using (Brush b = new SolidBrush(LightPlusBorder)) { |
||||
graphics.FillRectangle(b, new Rectangle(r.X, r.Y, 1, 1)); |
||||
graphics.FillRectangle(b, new Rectangle(r.Right, r.Y, 1, 1)); |
||||
graphics.FillRectangle(b, new Rectangle(r.X, r.Bottom, 1, 1)); |
||||
graphics.FillRectangle(b, new Rectangle(r.Right, r.Bottom, 1, 1)); |
||||
} |
||||
graphics.DrawLine(Pens.Black, r.Left + 2, r.Top + r.Height / 2, r.Right - 2, r.Top + r.Height / 2); |
||||
if (!drawMinus) { |
||||
graphics.DrawLine(Pens.Black, r.Left + r.Width / 2, r.Top + 2, r.Left + r.Width / 2, r.Bottom - 2); |
||||
} |
||||
} |
||||
|
||||
protected virtual void OnPlusPaint(object sender, ItemPaintEventArgs e) |
||||
{ |
||||
Rectangle r = e.ClipRectangle; |
||||
r.Inflate(-4, -4); |
||||
DrawPlusSign(e.Graphics, r, expandedIn != null && expandedIn.Contains(e.List)); |
||||
} |
||||
|
||||
protected override DynamicListItem CreateItem() |
||||
{ |
||||
DynamicListItem item = base.CreateItem(); |
||||
item.Paint += delegate(object sender, ItemPaintEventArgs e) { |
||||
if (e.Item != plus && expandedIn != null && !expandedRowColor.IsEmpty && expandedIn.Contains(e.List)) { |
||||
using (Brush b = new SolidBrush(expandedRowColor)) { |
||||
e.Graphics.FillRectangle(b, e.FillRectangle); |
||||
} |
||||
} |
||||
}; |
||||
return item; |
||||
} |
||||
|
||||
List<DynamicList> expandedIn; |
||||
Color expandedRowColor = DefaultExpandedRowColor; |
||||
|
||||
public bool ShowMinusWhileExpanded { |
||||
get { |
||||
return expandedIn != null; |
||||
} |
||||
set { |
||||
if (this.ShowMinusWhileExpanded == value) |
||||
return; |
||||
expandedIn = value ? new List<DynamicList>() : null; |
||||
} |
||||
} |
||||
|
||||
/// <summary>
|
||||
/// Gets/Sets the row color used when the row is expanded. Only works together with ShowMinusWhileExpanded.
|
||||
/// </summary>
|
||||
public Color ExpandedRowColor { |
||||
get { |
||||
return expandedRowColor; |
||||
} |
||||
set { |
||||
expandedRowColor = value; |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
#region Events
|
||||
public event EventHandler<DynamicListEventArgs> Expanding; |
||||
public event EventHandler<DynamicListEventArgs> Expanded; |
||||
public event EventHandler<DynamicListEventArgs> Collapsed; |
||||
public event EventHandler ShowPlusChanged; |
||||
|
||||
protected virtual void OnExpanding(DynamicListEventArgs e) |
||||
{ |
||||
if (Expanding != null) { |
||||
Expanding(this, e); |
||||
} |
||||
} |
||||
protected virtual void OnExpanded(DynamicListEventArgs e) |
||||
{ |
||||
if (Expanded != null) { |
||||
Expanded(this, e); |
||||
} |
||||
} |
||||
protected virtual void OnCollapsed(DynamicListEventArgs e) |
||||
{ |
||||
if (Collapsed != null) { |
||||
Collapsed(this, e); |
||||
} |
||||
} |
||||
public virtual void OnShowPlusChanged(EventArgs e) |
||||
{ |
||||
if (ShowPlusChanged != null) { |
||||
ShowPlusChanged(this, e); |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public CollectionWithEvents<DynamicListColumn> ChildColumns { |
||||
get { |
||||
return childColumns; |
||||
} |
||||
set { |
||||
if (value == null) |
||||
throw new ArgumentNullException("value"); |
||||
childColumns = value; |
||||
} |
||||
} |
||||
|
||||
public CollectionWithEvents<DynamicListRow> ChildRows { |
||||
get { |
||||
return childRows; |
||||
} |
||||
set { |
||||
if (value == null) |
||||
throw new ArgumentNullException("value"); |
||||
childRows = value; |
||||
} |
||||
} |
||||
|
||||
public static readonly Color DefaultBorderColor = Color.FromArgb(195, 192, 175); |
||||
|
||||
Color childBorderColor = DefaultBorderColor; |
||||
|
||||
public Color ChildBorderColor { |
||||
get { |
||||
return childBorderColor; |
||||
} |
||||
set { |
||||
childBorderColor = value; |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
#region Child form
|
||||
static bool isOpeningChild; |
||||
|
||||
/// <summary>
|
||||
/// Block the next click event - used to ensure that a click on the "-" sign
|
||||
/// does not cause the submenu to open again when the "-" sign becomes a "+" sign
|
||||
/// before the click event is handled.
|
||||
/// </summary>
|
||||
bool blockClickEvent; |
||||
|
||||
protected virtual void OnPlusClick(object sender, DynamicListEventArgs e) |
||||
{ |
||||
if (blockClickEvent) { blockClickEvent = false; return; } |
||||
OnExpanding(e); |
||||
// If OnExpanding displaies an error message, focus is lost, form is closed and we can not access the handle anymore
|
||||
if (e.List.IsDisposed) return; |
||||
ChildForm frm = new ChildForm(); |
||||
frm.Closed += delegate { |
||||
blockClickEvent = true; |
||||
if (expandedIn != null) |
||||
expandedIn.Remove(e.List); |
||||
OnCollapsed(e); |
||||
plus.RaiseItemChanged(); |
||||
Timer timer = new Timer(); |
||||
timer.Interval = 85; |
||||
timer.Tick += delegate(object sender2, EventArgs e2) { |
||||
((Timer)sender2).Stop(); |
||||
((Timer)sender2).Dispose(); |
||||
blockClickEvent = false; |
||||
}; |
||||
timer.Start(); |
||||
}; |
||||
Point p = e.List.PointToScreen(e.List.GetPositionFromRow(this)); |
||||
p.Offset(e.List.Columns[0].Width, Height); |
||||
frm.StartPosition = FormStartPosition.Manual; |
||||
frm.BackColor = childBorderColor; |
||||
frm.Location = p; |
||||
frm.ShowInTaskbar = false; |
||||
frm.Owner = e.List.FindForm(); |
||||
|
||||
VerticalScrollContainer scrollContainer = new VerticalScrollContainer(); |
||||
scrollContainer.Dock = DockStyle.Fill; |
||||
|
||||
DynamicList childList = new DynamicList(childColumns, childRows); |
||||
childList.Dock = DockStyle.Fill; |
||||
childList.KeyDown += delegate(object sender2, KeyEventArgs e2) { |
||||
if (e2.KeyData == Keys.Escape) { |
||||
frm.Close(); |
||||
// workaround focus problem: sometimes the mainform gets focus after this
|
||||
e.List.FindForm().Focus(); |
||||
} |
||||
}; |
||||
scrollContainer.Controls.Add(childList); |
||||
|
||||
frm.Controls.Add(scrollContainer); |
||||
|
||||
int screenHeight = Screen.FromPoint(p).WorkingArea.Bottom - p.Y; |
||||
screenHeight -= frm.Size.Height - frm.ClientSize.Height; |
||||
int requiredHeight = childList.TotalRowHeight + 4; |
||||
int formHeight = Math.Min(requiredHeight, screenHeight); |
||||
if (formHeight < requiredHeight) { |
||||
int missingHeight = Math.Min(100, requiredHeight - formHeight); |
||||
formHeight += missingHeight; |
||||
frm.Top -= missingHeight; |
||||
} |
||||
// Autosize child window
|
||||
int formWidth; |
||||
using (Graphics g = childList.CreateGraphics()) { |
||||
formWidth = 8 + childList.GetRequiredWidth(g); |
||||
} |
||||
int screenWidth = Screen.FromPoint(p).WorkingArea.Right - p.X; |
||||
if (formWidth > screenWidth) { |
||||
int missingWidth = Math.Min(100, formWidth - screenWidth); |
||||
formWidth = screenWidth + missingWidth; |
||||
frm.Left -= missingWidth; |
||||
} |
||||
frm.ClientSize = new Size(formWidth, formHeight); |
||||
frm.MinimumSize = new Size(100, Math.Min(50, formHeight)); |
||||
isOpeningChild = true; |
||||
frm.Show(); |
||||
isOpeningChild = false; |
||||
childList.Focus(); |
||||
if (expandedIn != null) |
||||
expandedIn.Add(e.List); |
||||
OnExpanded(e); |
||||
plus.RaiseItemChanged(); |
||||
} |
||||
|
||||
public class ChildForm : Form, IActivatable |
||||
{ |
||||
bool isActivated = true; |
||||
|
||||
public bool IsActivated { |
||||
get { |
||||
return isActivated; |
||||
} |
||||
} |
||||
|
||||
bool allowResizing = true; |
||||
|
||||
public bool AllowResizing { |
||||
get { |
||||
return allowResizing; |
||||
} |
||||
set { |
||||
if (allowResizing == value) |
||||
return; |
||||
allowResizing = value; |
||||
this.DockPadding.All = value ? 2 : 1; |
||||
} |
||||
} |
||||
|
||||
public ChildForm() |
||||
{ |
||||
this.FormBorderStyle = FormBorderStyle.None; |
||||
this.DockPadding.All = 2; |
||||
this.BackColor = DefaultBorderColor; |
||||
} |
||||
|
||||
bool showWindowWithoutActivation; |
||||
|
||||
/// <summary>
|
||||
/// Gets/Sets whether the window will receive focus when it is shown.
|
||||
/// </summary>
|
||||
public bool ShowWindowWithoutActivation { |
||||
get { |
||||
return showWindowWithoutActivation; |
||||
} |
||||
set { |
||||
showWindowWithoutActivation = value; |
||||
} |
||||
} |
||||
|
||||
protected override bool ShowWithoutActivation { |
||||
get { |
||||
return showWindowWithoutActivation; |
||||
} |
||||
} |
||||
|
||||
protected override CreateParams CreateParams { |
||||
get { |
||||
CreateParams p = base.CreateParams; |
||||
DesignHelper.AddShadowToWindow(p); |
||||
return p; |
||||
} |
||||
} |
||||
|
||||
#region Resizing the form
|
||||
private enum MousePositionCodes |
||||
{ |
||||
HTERROR = (-2), |
||||
HTTRANSPARENT = (-1), |
||||
HTNOWHERE = 0, |
||||
HTCLIENT = 1, |
||||
HTCAPTION = 2, |
||||
HTSYSMENU = 3, |
||||
HTGROWBOX = 4, |
||||
HTSIZE = HTGROWBOX, |
||||
HTMENU = 5, |
||||
HTHSCROLL = 6, |
||||
HTVSCROLL = 7, |
||||
HTMINBUTTON = 8, |
||||
HTMAXBUTTON = 9, |
||||
HTLEFT = 10, |
||||
HTRIGHT = 11, |
||||
HTTOP = 12, |
||||
HTTOPLEFT = 13, |
||||
HTTOPRIGHT = 14, |
||||
HTBOTTOM = 15, |
||||
HTBOTTOMLEFT = 16, |
||||
HTBOTTOMRIGHT = 17, |
||||
HTBORDER = 18, |
||||
HTREDUCE = HTMINBUTTON, |
||||
HTZOOM = HTMAXBUTTON, |
||||
HTSIZEFIRST = HTLEFT, |
||||
HTSIZELAST = HTBOTTOMRIGHT, |
||||
HTOBJECT = 19, |
||||
HTCLOSE = 20, |
||||
HTHELP = 21 |
||||
} |
||||
|
||||
protected override void WndProc(ref Message m) |
||||
{ |
||||
base.WndProc(ref m); |
||||
if (m.Msg == 0x0084) // WM_NCHITTEST
|
||||
HitTest(ref m); |
||||
} |
||||
|
||||
void HitTest(ref Message m) |
||||
{ |
||||
if (!allowResizing) |
||||
return; |
||||
int mousePos = m.LParam.ToInt32(); |
||||
int mouseX = mousePos & 0xffff; |
||||
int mouseY = mousePos >> 16; |
||||
//System.Diagnostics.Debug.WriteLine(mouseX + " / " + mouseY);
|
||||
Rectangle bounds = Bounds; |
||||
bool isLeft = mouseX == bounds.Left || mouseX + 1 == bounds.Left; |
||||
bool isTop = mouseY == bounds.Top || mouseY + 1 == bounds.Top; |
||||
bool isRight = mouseX == bounds.Right - 1 || mouseX == bounds.Right - 2; |
||||
bool isBottom = mouseY == bounds.Bottom - 1 || mouseY == bounds.Bottom - 2; |
||||
if (isLeft) { |
||||
if (isTop) |
||||
m.Result = new IntPtr((int)MousePositionCodes.HTTOPLEFT); |
||||
else if (isBottom) |
||||
m.Result = new IntPtr((int)MousePositionCodes.HTBOTTOMLEFT); |
||||
else |
||||
m.Result = new IntPtr((int)MousePositionCodes.HTLEFT); |
||||
} else if (isRight) { |
||||
if (isTop) |
||||
m.Result = new IntPtr((int)MousePositionCodes.HTTOPRIGHT); |
||||
else if (isBottom) |
||||
m.Result = new IntPtr((int)MousePositionCodes.HTBOTTOMRIGHT); |
||||
else |
||||
m.Result = new IntPtr((int)MousePositionCodes.HTRIGHT); |
||||
} else if (isTop) { |
||||
m.Result = new IntPtr((int)MousePositionCodes.HTTOP); |
||||
} else if (isBottom) { |
||||
m.Result = new IntPtr((int)MousePositionCodes.HTBOTTOM); |
||||
} |
||||
} |
||||
#endregion
|
||||
|
||||
protected override void OnActivated(EventArgs e) |
||||
{ |
||||
isActivated = true; |
||||
base.OnActivated(e); |
||||
Refresh(); |
||||
} |
||||
|
||||
protected override void OnDeactivate(EventArgs e) |
||||
{ |
||||
isActivated = false; |
||||
base.OnDeactivate(e); |
||||
if (isOpeningChild) { |
||||
Refresh(); |
||||
return; |
||||
} |
||||
BeginInvoke(new MethodInvoker(CloseOnDeactivate)); |
||||
} |
||||
|
||||
void CloseOnDeactivate() |
||||
{ |
||||
ChildForm owner = Owner as ChildForm; |
||||
if (owner != null) { |
||||
if (owner.isActivated) |
||||
Close(); |
||||
else |
||||
owner.CloseOnDeactivate(); |
||||
} else { |
||||
Close(); |
||||
} |
||||
} |
||||
|
||||
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) |
||||
{ |
||||
if (base.ProcessCmdKey(ref msg, keyData)) { |
||||
return true; |
||||
} else { |
||||
ChildForm owner = Owner as ChildForm; |
||||
if (owner != null) |
||||
return owner.ProcessCmdKey(ref msg, keyData); |
||||
return false; |
||||
} |
||||
} |
||||
} |
||||
#endregion
|
||||
} |
||||
} |
||||
@ -1,120 +0,0 @@
@@ -1,120 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Drawing; |
||||
using System.Windows.Forms; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Widgets.TreeGrid |
||||
{ |
||||
public class ScrollButtonControl : Control |
||||
{ |
||||
public ScrollButtonControl() |
||||
{ |
||||
this.BackColor = DynamicListColumn.DefaultBackColor; |
||||
this.TabStop = false; |
||||
this.SetStyle(ControlStyles.Selectable, false); |
||||
this.SetStyle(ControlStyles.ResizeRedraw, true); |
||||
} |
||||
|
||||
protected override Size DefaultSize { |
||||
get { |
||||
return new Size(14, 14); |
||||
} |
||||
} |
||||
|
||||
ScrollButton arrow = ScrollButton.Down; |
||||
|
||||
public ScrollButton Arrow { |
||||
get { |
||||
return arrow; |
||||
} |
||||
set { |
||||
arrow = value; |
||||
Invalidate(); |
||||
} |
||||
} |
||||
|
||||
bool drawSeparatorLine = true; |
||||
|
||||
public bool DrawSeparatorLine { |
||||
get { |
||||
return drawSeparatorLine; |
||||
} |
||||
set { |
||||
drawSeparatorLine = value; |
||||
Invalidate(); |
||||
} |
||||
} |
||||
|
||||
Color highlightColor = SystemColors.Highlight; |
||||
|
||||
public Color HighlightColor { |
||||
get { |
||||
return highlightColor; |
||||
} |
||||
set { |
||||
highlightColor = value; |
||||
Invalidate(); |
||||
} |
||||
} |
||||
|
||||
protected override void OnPaint(PaintEventArgs e) |
||||
{ |
||||
base.OnPaint(e); |
||||
const int margin = 2; |
||||
int height = this.ClientSize.Height; |
||||
int size = height - 2 * margin; |
||||
int width = this.ClientSize.Width; |
||||
int left = (width - size) / 2; |
||||
int right = (width + size) / 2; |
||||
Point[] triangle; |
||||
switch (arrow) { |
||||
case ScrollButton.Down: |
||||
triangle = new Point[] { |
||||
new Point(left, margin), new Point(right, margin), new Point(width / 2, margin + size) |
||||
}; |
||||
if (drawSeparatorLine) |
||||
e.Graphics.DrawLine(SystemPens.GrayText, 0, 0, width, 0); |
||||
break; |
||||
case ScrollButton.Up: |
||||
triangle = new Point[] { |
||||
new Point(left, margin + size), new Point(right, margin + size), new Point(width / 2, margin) |
||||
}; |
||||
if (drawSeparatorLine) |
||||
e.Graphics.DrawLine(SystemPens.GrayText, 0, height - 1, width, height - 1); |
||||
break; |
||||
default: |
||||
return; |
||||
} |
||||
Color color; |
||||
if (Enabled) |
||||
color = cursorEntered ? HighlightColor : ForeColor; |
||||
else |
||||
color = SystemColors.GrayText; |
||||
using (Brush b = new SolidBrush(color)) { |
||||
e.Graphics.FillPolygon(b, triangle); |
||||
} |
||||
} |
||||
|
||||
bool cursorEntered = false; |
||||
|
||||
protected override void OnMouseEnter(EventArgs e) |
||||
{ |
||||
base.OnMouseEnter(e); |
||||
cursorEntered = true; |
||||
Invalidate(); |
||||
} |
||||
|
||||
protected override void OnMouseLeave(EventArgs e) |
||||
{ |
||||
base.OnMouseLeave(e); |
||||
cursorEntered = false; |
||||
Invalidate(); |
||||
} |
||||
} |
||||
} |
||||
@ -1,174 +0,0 @@
@@ -1,174 +0,0 @@
|
||||
// <file>
|
||||
// <copyright see="prj:///doc/copyright.txt"/>
|
||||
// <license see="prj:///doc/license.txt"/>
|
||||
// <owner name="Daniel Grunwald" email="daniel@danielgrunwald.de"/>
|
||||
// <version>$Revision$</version>
|
||||
// </file>
|
||||
|
||||
using System; |
||||
using System.Windows.Forms; |
||||
|
||||
namespace ICSharpCode.SharpDevelop.Widgets.TreeGrid |
||||
{ |
||||
public class VerticalScrollContainer : Control |
||||
{ |
||||
public interface IScrollable |
||||
{ |
||||
int ScrollOffsetY { get; set; } |
||||
int ScrollHeightY { get; } |
||||
int Height { get; } |
||||
event MouseEventHandler MouseWheel; |
||||
} |
||||
|
||||
IScrollable scrollable; |
||||
bool showButtonsOnlyIfRequired = true; |
||||
ScrollButtonControl down = new ScrollButtonControl(); |
||||
ScrollButtonControl up = new ScrollButtonControl(); |
||||
Timer timer = new Timer(); |
||||
|
||||
int scrollSpeed = 5; |
||||
|
||||
public int ScrollSpeed { |
||||
get { |
||||
return scrollSpeed; |
||||
} |
||||
set { |
||||
scrollSpeed = value; |
||||
} |
||||
} |
||||
|
||||
public VerticalScrollContainer() |
||||
{ |
||||
up.Arrow = ScrollButton.Up; |
||||
down.Arrow = ScrollButton.Down; |
||||
up.Dock = DockStyle.Top; |
||||
down.Dock = DockStyle.Bottom; |
||||
this.TabStop = false; |
||||
this.SetStyle(ControlStyles.Selectable, false); |
||||
Controls.Add(up); |
||||
Controls.Add(down); |
||||
UpdateEnabled(); |
||||
|
||||
timer.Interval = 50; |
||||
timer.Tick += delegate { |
||||
ScrollBy((int)timer.Tag); |
||||
}; |
||||
up.MouseDown += delegate { |
||||
timer.Tag = -scrollSpeed; |
||||
ScrollBy(-scrollSpeed); |
||||
timer.Start(); |
||||
}; |
||||
down.MouseDown += delegate { |
||||
timer.Tag = scrollSpeed; |
||||
ScrollBy(scrollSpeed); |
||||
timer.Start(); |
||||
}; |
||||
up.MouseUp += StopTimer; |
||||
down.MouseUp += StopTimer; |
||||
} |
||||
|
||||
void StopTimer(object sender, MouseEventArgs e) |
||||
{ |
||||
timer.Stop(); |
||||
} |
||||
|
||||
protected override void Dispose(bool disposing) |
||||
{ |
||||
base.Dispose(disposing); |
||||
if (disposing) { |
||||
timer.Dispose(); |
||||
} |
||||
} |
||||
|
||||
void UpdateEnabled() |
||||
{ |
||||
if (scrollable == null) { |
||||
up.Visible = down.Visible = true; |
||||
up.Enabled = down.Enabled = false; |
||||
} else { |
||||
int scrollHeightY = scrollable.ScrollHeightY; |
||||
if (showButtonsOnlyIfRequired) { |
||||
if (scrollHeightY <= this.Height) { |
||||
scrollable.ScrollOffsetY = 0; |
||||
up.Visible = down.Visible = false; |
||||
return; |
||||
} |
||||
up.Visible = down.Visible = true; |
||||
} else { |
||||
up.Visible = down.Visible = true; |
||||
if (scrollable.ScrollHeightY <= scrollable.Height) { |
||||
scrollable.ScrollOffsetY = 0; |
||||
up.Enabled = down.Enabled = false; |
||||
return; |
||||
} |
||||
} |
||||
// set enabled
|
||||
up.Enabled = scrollable.ScrollOffsetY > 0; |
||||
down.Enabled = scrollable.ScrollOffsetY < scrollHeightY - scrollable.Height; |
||||
} |
||||
} |
||||
|
||||
void ScrollBy(int amount) |
||||
{ |
||||
if (amount != 0) { |
||||
scrollable.ScrollOffsetY = Math.Max(0, Math.Min(scrollable.ScrollOffsetY + amount, scrollable.ScrollHeightY - scrollable.Height)); |
||||
UpdateEnabled(); |
||||
} |
||||
} |
||||
|
||||
public bool ShowButtonsOnlyIfRequired { |
||||
get { |
||||
return showButtonsOnlyIfRequired; |
||||
} |
||||
set { |
||||
if (showButtonsOnlyIfRequired != value) { |
||||
showButtonsOnlyIfRequired = value; |
||||
UpdateEnabled(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
MouseWheelHandler mouseWheelHandler = new MouseWheelHandler(); |
||||
|
||||
void ScrollableWheel(object sender, MouseEventArgs e) |
||||
{ |
||||
ScrollBy(mouseWheelHandler.GetScrollAmount(e) * -16); |
||||
} |
||||
|
||||
protected override void OnSizeChanged(EventArgs e) |
||||
{ |
||||
base.OnSizeChanged(e); |
||||
UpdateEnabled(); |
||||
} |
||||
|
||||
protected override void OnControlAdded(ControlEventArgs e) |
||||
{ |
||||
base.OnControlAdded(e); |
||||
if (scrollable == null && !DesignMode) { |
||||
scrollable = e.Control as IScrollable; |
||||
if (scrollable != null) { |
||||
scrollable.MouseWheel += ScrollableWheel; |
||||
Controls.SetChildIndex(e.Control, 0); |
||||
UpdateEnabled(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
protected override void OnControlRemoved(ControlEventArgs e) |
||||
{ |
||||
base.OnControlRemoved(e); |
||||
if (scrollable == e.Control) { |
||||
scrollable.MouseWheel -= ScrollableWheel; |
||||
scrollable = null; |
||||
UpdateEnabled(); |
||||
} |
||||
} |
||||
|
||||
protected override void OnHandleCreated(EventArgs e) |
||||
{ |
||||
base.OnHandleCreated(e); |
||||
// HACK: Windows.Forms bug workaround
|
||||
BeginInvoke(new MethodInvoker(PerformLayout)); |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue