Debugger: Added horizontal scrolling for code windows

This commit is contained in:
Souryo 2016-11-23 22:57:17 -05:00
parent 5bef5bdd1a
commit 144d6c95b7
3 changed files with 122 additions and 18 deletions

View file

@ -44,6 +44,7 @@ namespace Mesen.GUI.Debugger
this.ctrlTextbox.ShowLineNumbers = true;
this.ctrlTextbox.ShowLineInHex = true;
this.hScrollBar.ValueChanged += hScrollBar_ValueChanged;
this.vScrollBar.ValueChanged += vScrollBar_ValueChanged;
this.ctrlTextbox.ScrollPositionChanged += ctrlTextbox_ScrollPositionChanged;
@ -76,6 +77,18 @@ namespace Mesen.GUI.Debugger
private void ctrlTextbox_ScrollPositionChanged(object sender, EventArgs e)
{
this.vScrollBar.Value = this.ctrlTextbox.ScrollPosition;
this.hScrollBar.Value = this.ctrlTextbox.HorizontalScrollPosition;
UpdateHorizontalScrollbar();
}
private void UpdateHorizontalScrollbar()
{
this.hScrollBar.Visible = this.ctrlTextbox.HorizontalScrollWidth > 0;
int newMax = this.ctrlTextbox.HorizontalScrollWidth + this.hScrollBar.LargeChange - 1;
if(this.hScrollBar.Value > this.ctrlTextbox.HorizontalScrollWidth) {
this.hScrollBar.Value = this.ctrlTextbox.HorizontalScrollWidth;
}
this.hScrollBar.Maximum = newMax;
}
public void ClearLineStyles()
@ -195,12 +208,18 @@ namespace Mesen.GUI.Debugger
this.ctrlTextbox.ScrollPosition = this.vScrollBar.Value;
}
private void hScrollBar_ValueChanged(object sender, EventArgs e)
{
this.ctrlTextbox.HorizontalScrollPosition = this.hScrollBar.Value;
}
public string[] TextLines
{
set
{
this.ctrlTextbox.TextLines = value;
this.vScrollBar.Maximum = this.ctrlTextbox.LineCount + this.vScrollBar.LargeChange;
UpdateHorizontalScrollbar();
}
}

View file

@ -34,6 +34,7 @@
this.picSearchNext = new System.Windows.Forms.PictureBox();
this.picSearchPrevious = new System.Windows.Forms.PictureBox();
this.cboSearch = new System.Windows.Forms.ComboBox();
this.hScrollBar = new System.Windows.Forms.HScrollBar();
this.ctrlTextbox = new Mesen.GUI.Debugger.ctrlTextbox();
this.panelSearch.SuspendLayout();
this.tableLayoutPanel1.SuspendLayout();
@ -48,7 +49,7 @@
this.vScrollBar.LargeChange = 20;
this.vScrollBar.Location = new System.Drawing.Point(305, 0);
this.vScrollBar.Name = "vScrollBar";
this.vScrollBar.Size = new System.Drawing.Size(18, 174);
this.vScrollBar.Size = new System.Drawing.Size(18, 156);
this.vScrollBar.TabIndex = 0;
//
// panelSearch
@ -132,15 +133,25 @@
this.cboSearch.TextUpdate += new System.EventHandler(this.cboSearch_TextUpdate);
this.cboSearch.KeyDown += new System.Windows.Forms.KeyEventHandler(this.cboSearch_KeyDown);
//
// hScrollBar
//
this.hScrollBar.Dock = System.Windows.Forms.DockStyle.Bottom;
this.hScrollBar.Location = new System.Drawing.Point(0, 156);
this.hScrollBar.Name = "hScrollBar";
this.hScrollBar.Size = new System.Drawing.Size(323, 18);
this.hScrollBar.TabIndex = 3;
//
// ctrlTextbox
//
this.ctrlTextbox.Dock = System.Windows.Forms.DockStyle.Fill;
this.ctrlTextbox.Font = new System.Drawing.Font("Consolas", 13F);
this.ctrlTextbox.Location = new System.Drawing.Point(0, 0);
this.ctrlTextbox.Name = "ctrlTextbox";
this.ctrlTextbox.ShowContentNotes = false;
this.ctrlTextbox.ShowLineInHex = false;
this.ctrlTextbox.ShowLineNumberNotes = false;
this.ctrlTextbox.ShowLineNumbers = true;
this.ctrlTextbox.Size = new System.Drawing.Size(305, 174);
this.ctrlTextbox.Size = new System.Drawing.Size(305, 156);
this.ctrlTextbox.TabIndex = 1;
//
// ctrlScrollableTextbox
@ -151,6 +162,7 @@
this.Controls.Add(this.panelSearch);
this.Controls.Add(this.ctrlTextbox);
this.Controls.Add(this.vScrollBar);
this.Controls.Add(this.hScrollBar);
this.Name = "ctrlScrollableTextbox";
this.Size = new System.Drawing.Size(323, 174);
this.panelSearch.ResumeLayout(false);
@ -173,6 +185,6 @@
private System.Windows.Forms.PictureBox picSearchNext;
private System.Windows.Forms.PictureBox picCloseSearch;
private System.Windows.Forms.ComboBox cboSearch;
private System.Windows.Forms.HScrollBar hScrollBar;
}
}

View file

@ -32,6 +32,8 @@ namespace Mesen.GUI.Debugger
{
public event EventHandler ScrollPositionChanged;
private const float HorizontalScrollFactor = 8;
private string[] _contents = new string[0];
private string[] _contentNotes = new string[0];
private string[] _compareContents = null;
@ -46,10 +48,12 @@ namespace Mesen.GUI.Debugger
private bool _showContentNotes = false;
private int _cursorPosition = 0;
private int _scrollPosition = 0;
private int _horizontalScrollPosition = 0;
private string _searchString = null;
private string _header = null;
private Font _noteFont = null;
private int _marginWidth = 6;
private float _maxLineWidth = 0;
public ctrlTextbox()
{
@ -62,13 +66,25 @@ namespace Mesen.GUI.Debugger
{
set
{
int maxLength = 0;
int maxLengthIndex = 0;
_contents = new string[value.Length];
_lineMargins = new int[value.Length];
for(int i = 0, len = value.Length; i < len; i++) {
_contents[i] = value[i].TrimStart();
if(_contents[i].Length > maxLength) {
maxLength = _contents[i].Length;
maxLengthIndex = i;
}
_lineMargins[i] = (value[i].Length - _contents[i].Length) * 10;
}
using(Graphics g = this.CreateGraphics()) {
_maxLineWidth = g.MeasureString(_contents[maxLengthIndex], this.Font).Width;
}
UpdateHorizontalScrollWidth();
_lineNumbers = new int[_contents.Length];
_lineNumberIndex.Clear();
for(int i = _contents.Length - 1; i >=0; i--) {
@ -348,7 +364,7 @@ namespace Mesen.GUI.Debugger
int lineIndex;
if(this.GetCharIndex(position, out charIndex, out lineIndex)) {
string text = ((useCompareText && _compareContents != null) ? _compareContents[lineIndex] : _contents[lineIndex]).Replace("\x2", "");
List<char> wordDelimiters = new List<char>(new char[] { ' ', ',', '|', ';', '(', ')' });
List<char> wordDelimiters = new List<char>(new char[] { ' ', ',', '|', ';', '(', ')', '.', '-', ':' });
if(wordDelimiters.Contains(text[charIndex])) {
return string.Empty;
} else {
@ -420,6 +436,37 @@ namespace Mesen.GUI.Debugger
}
}
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int HorizontalScrollPosition
{
get { return _horizontalScrollPosition; }
set
{
_horizontalScrollPosition = value;
if(this.ScrollPositionChanged != null) {
ScrollPositionChanged(this, null);
}
this.Invalidate();
}
}
public int HorizontalScrollWidth { get; set; } = 0;
private void UpdateHorizontalScrollWidth()
{
using(Graphics g = this.CreateGraphics()) {
HorizontalScrollWidth = (int)(Math.Max(0, 8 + _maxLineWidth - (this.Width - GetMargin(g))) / HorizontalScrollFactor);
}
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
UpdateHorizontalScrollWidth();
ScrollPositionChanged?.Invoke(this, e);
}
public bool ShowLineNumbers
{
get { return _showLineNumbers; }
@ -462,14 +509,9 @@ namespace Mesen.GUI.Debugger
float codeStringLength = g.MeasureString(codeString, this.Font).Width;
float addressStringLength = g.MeasureString(addressString, this.Font).Width;
if(this.ShowLineNumbers) {
//Show line number
this.DrawLineNumber(g, currentLine, marginLeft, positionY);
}
if(currentLine == this.CursorPosition) {
//Highlight current line
g.FillRectangle(Brushes.AliceBlue, marginLeft, positionY, this.ClientRectangle.Width - marginLeft, this.LineHeight);
g.FillRectangle(Brushes.AliceBlue, marginLeft, positionY, Math.Max(_maxLineWidth, this.ClientRectangle.Width), this.LineHeight);
}
//Adjust background color highlights based on number of spaces in front of content
@ -491,8 +533,6 @@ namespace Mesen.GUI.Debugger
g.DrawRectangle(outlinePen, marginLeft, positionY + 1, codeStringLength, this.LineHeight-1);
}
}
this.DrawLineSymbols(g, positionY, lineProperties);
}
this.DrawLineText(g, currentLine, marginLeft, positionY, codeString, addressString, commentString, codeStringLength, addressStringLength, textColor);
@ -514,21 +554,27 @@ namespace Mesen.GUI.Debugger
using(Brush fgBrush = new SolidBrush(textColor)) {
if(codeString.StartsWith("--") && codeString.EndsWith("--")) {
//Draw block start
g.TranslateTransform(HorizontalScrollPosition * HorizontalScrollFactor, 0);
string text = codeString.Substring(2, codeString.Length - 4);
float textLength = g.MeasureString(text, this._noteFont).Width;
g.DrawString(text, this._noteFont, fgBrush, (marginLeft + this.Width - textLength) / 2, positionY);
g.DrawLine(Pens.Black, marginLeft, positionY+this.LineHeight-2, marginLeft+this.Width, positionY+this.LineHeight-2);
g.TranslateTransform(-HorizontalScrollPosition * HorizontalScrollFactor, 0);
} else if(codeString.StartsWith("__") && codeString.EndsWith("__")) {
//Draw block end
g.TranslateTransform(HorizontalScrollPosition * HorizontalScrollFactor, 0);
string text = codeString.Substring(2, codeString.Length - 4);
float textLength = g.MeasureString(text, this._noteFont).Width;
g.DrawString(text, this._noteFont, fgBrush, (marginLeft + this.Width - textLength) / 2, positionY + 4);
g.DrawLine(Pens.Black, marginLeft, positionY+2, marginLeft+this.Width, positionY+2);
g.TranslateTransform(-HorizontalScrollPosition * HorizontalScrollFactor, 0);
} else if(codeString.StartsWith("[[") && codeString.EndsWith("]]")) {
//Draw small centered text
g.TranslateTransform(HorizontalScrollPosition * HorizontalScrollFactor, 0);
string text = codeString.Substring(2, codeString.Length - 4);
float textLength = g.MeasureString(text, this._noteFont).Width;
g.DrawString(text, new Font(this._noteFont, FontStyle.Italic), fgBrush, (marginLeft + this.Width - textLength) / 2, positionY + 2);
g.TranslateTransform(-HorizontalScrollPosition * HorizontalScrollFactor, 0);
} else {
//Draw line content
g.DrawString(codeString, this.Font, fgBrush, marginLeft, positionY);
@ -631,6 +677,21 @@ namespace Mesen.GUI.Debugger
}
}
private void DrawMargin(Graphics g, int currentLine, int marginLeft, int positionY)
{
if(this.ShowLineNumbers) {
//Show line number
this.DrawLineNumber(g, currentLine, marginLeft, positionY);
}
//Adjust background color highlights based on number of spaces in front of content
marginLeft += _lineMargins[currentLine];
if(_lineProperties.ContainsKey(currentLine)) {
this.DrawLineSymbols(g, positionY, _lineProperties[currentLine]);
}
}
protected override void OnPaint(PaintEventArgs pe)
{
pe.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
@ -639,17 +700,14 @@ namespace Mesen.GUI.Debugger
Rectangle rect = this.ClientRectangle;
pe.Graphics.FillRectangle(Brushes.White, rect);
int marginLeft = this.GetMargin(pe.Graphics);
if(this.ShowLineNumbers) {
pe.Graphics.FillRectangle(lightGrayBrush, 0, 0, marginLeft, rect.Bottom);
pe.Graphics.DrawLine(grayPen, marginLeft, rect.Top, marginLeft, rect.Bottom);
}
pe.Graphics.TranslateTransform(-HorizontalScrollPosition * HorizontalScrollFactor, 0);
int marginLeft = this.GetMargin(pe.Graphics);
int currentLine = this.ScrollPosition;
int positionY = 0;
if(!string.IsNullOrWhiteSpace(this._header)) {
pe.Graphics.FillRectangle(lightGrayBrush, marginLeft, 0, rect.Right, this.LineHeight);
pe.Graphics.FillRectangle(lightGrayBrush, marginLeft, 0, Math.Max(_maxLineWidth, rect.Right), this.LineHeight);
pe.Graphics.DrawString(_header, this.Font, Brushes.Gray, marginLeft, positionY);
positionY += this.LineHeight;
}
@ -659,6 +717,21 @@ namespace Mesen.GUI.Debugger
positionY += this.LineHeight;
currentLine++;
}
pe.Graphics.TranslateTransform(HorizontalScrollPosition * HorizontalScrollFactor, 0);
if(this.ShowLineNumbers) {
pe.Graphics.FillRectangle(lightGrayBrush, 0, 0, marginLeft, rect.Bottom);
pe.Graphics.DrawLine(grayPen, marginLeft, rect.Top, marginLeft, rect.Bottom);
}
currentLine = this.ScrollPosition;
positionY = 0;
while(positionY < rect.Bottom && currentLine < _contents.Length) {
this.DrawMargin(pe.Graphics, currentLine, marginLeft, positionY);
positionY += this.LineHeight;
currentLine++;
}
}
}
}