Mesen-X/GUI.NET/Debugger/FastColoredTextBox/DocumentMap.cs

251 lines
7.4 KiB
C#
Raw Normal View History

2017-08-30 18:31:27 -04:00
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;
namespace FastColoredTextBoxNS
{
/// <summary>
/// Shows document map of FCTB
/// </summary>
public class DocumentMap : Control
{
public EventHandler TargetChanged;
FastColoredTextBox target;
private float scale = 0.3f;
private bool needRepaint = true;
private Place startPlace = Place.Empty;
private bool scrollbarVisible = true;
[Description("Target FastColoredTextBox")]
public FastColoredTextBox Target
{
get { return target; }
set
{
if (target != null)
UnSubscribe(target);
target = value;
if (value != null)
{
Subscribe(target);
}
OnTargetChanged();
}
}
/// <summary>
/// Scale
/// </summary>
[Description("Scale")]
[DefaultValue(0.3f)]
public new float Scale
{
get { return scale; }
set
{
scale = value;
NeedRepaint();
}
}
/// <summary>
/// Scrollbar visibility
/// </summary>
[Description("Scrollbar visibility")]
[DefaultValue(true)]
public bool ScrollbarVisible
{
get { return scrollbarVisible; }
set
{
scrollbarVisible = value;
NeedRepaint();
}
}
public DocumentMap()
{
ForeColor = Color.Maroon;
SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.UserPaint | ControlStyles.ResizeRedraw, true);
Application.Idle += Application_Idle;
}
void Application_Idle(object sender, EventArgs e)
{
if(needRepaint)
Invalidate();
}
protected virtual void OnTargetChanged()
{
NeedRepaint();
if (TargetChanged != null)
TargetChanged(this, EventArgs.Empty);
}
protected virtual void UnSubscribe(FastColoredTextBox target)
{
target.Scroll -= new ScrollEventHandler(Target_Scroll);
target.SelectionChangedDelayed -= new EventHandler(Target_SelectionChanged);
target.VisibleRangeChanged -= new EventHandler(Target_VisibleRangeChanged);
}
protected virtual void Subscribe(FastColoredTextBox target)
{
target.Scroll += new ScrollEventHandler(Target_Scroll);
target.SelectionChangedDelayed += new EventHandler(Target_SelectionChanged);
target.VisibleRangeChanged += new EventHandler(Target_VisibleRangeChanged);
}
protected virtual void Target_VisibleRangeChanged(object sender, EventArgs e)
{
NeedRepaint();
}
protected virtual void Target_SelectionChanged(object sender, EventArgs e)
{
NeedRepaint();
}
protected virtual void Target_Scroll(object sender, ScrollEventArgs e)
{
NeedRepaint();
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
NeedRepaint();
}
public void NeedRepaint()
{
needRepaint = true;
}
protected override void OnPaint(PaintEventArgs e)
{
if (target == null)
return;
var zoom = this.Scale * 100 / target.Zoom;
if (zoom <= float.Epsilon)
return;
//calc startPlace
var r = target.VisibleRange;
if (startPlace.iLine > r.Start.iLine)
startPlace.iLine = r.Start.iLine;
else
{
var endP = target.PlaceToPoint(r.End);
endP.Offset(0, -(int)(ClientSize.Height / zoom) + target.CharHeight);
var pp = target.PointToPlace(endP);
if (pp.iLine > startPlace.iLine)
startPlace.iLine = pp.iLine;
}
startPlace.iChar = 0;
//calc scroll pos
var linesCount = target.Lines.Count;
var sp1 = (float)r.Start.iLine / linesCount;
var sp2 = (float)r.End.iLine / linesCount;
//scale graphics
e.Graphics.ScaleTransform(zoom, zoom);
//draw text
var size = new SizeF(ClientSize.Width / zoom, ClientSize.Height / zoom);
target.DrawText(e.Graphics, startPlace, size.ToSize());
//draw visible rect
var p0 = target.PlaceToPoint(startPlace);
var p1 = target.PlaceToPoint(r.Start);
var p2 = target.PlaceToPoint(r.End);
var y1 = p1.Y - p0.Y;
var y2 = p2.Y + target.CharHeight - p0.Y;
e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
using (var brush = new SolidBrush(Color.FromArgb(50, ForeColor)))
using (var pen = new Pen(brush, 1 / zoom))
{
var rect = new Rectangle(0, y1, (int)((ClientSize.Width - 1) / zoom), y2 - y1);
e.Graphics.FillRectangle(brush, rect);
e.Graphics.DrawRectangle(pen, rect);
}
//draw scrollbar
if (scrollbarVisible)
{
e.Graphics.ResetTransform();
e.Graphics.SmoothingMode = SmoothingMode.None;
using (var brush = new SolidBrush(Color.FromArgb(200, ForeColor)))
{
var rect = new RectangleF(ClientSize.Width - 3, ClientSize.Height*sp1, 2,
ClientSize.Height*(sp2 - sp1));
e.Graphics.FillRectangle(brush, rect);
}
}
needRepaint = false;
}
protected override void OnMouseDown(MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
Scroll(e.Location);
base.OnMouseDown(e);
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
Scroll(e.Location);
base.OnMouseMove(e);
}
private void Scroll(Point point)
{
if (target == null)
return;
var zoom = this.Scale*100/target.Zoom;
if (zoom <= float.Epsilon)
return;
var p0 = target.PlaceToPoint(startPlace);
p0 = new Point(0, p0.Y + (int) (point.Y/zoom));
var pp = target.PointToPlace(p0);
target.DoRangeVisible(new Range(target, pp, pp), true);
BeginInvoke((MethodInvoker)OnScroll);
}
private void OnScroll()
{
Refresh();
target.Refresh();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Application.Idle -= Application_Idle;
if (target != null)
UnSubscribe(target);
}
base.Dispose(disposing);
}
}
}