Mesen-SX/UI/Debugger/Controls/ctrlScrollableTextbox.cs

576 lines
15 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Mesen.GUI.Controls;
using Mesen.GUI.Config;
using System.Globalization;
namespace Mesen.GUI.Debugger.Controls
{
public partial class ctrlScrollableTextbox : BaseControl
{
public event EventHandler ScrollPositionChanged;
private bool _showScrollbars = true;
public new event MouseEventHandler MouseUp
{
add { this.ctrlTextbox.MouseUp += value; }
remove { this.ctrlTextbox.MouseUp -= value; }
}
public new event MouseEventHandler MouseMove
{
add { this.ctrlTextbox.MouseMove += value; }
remove { this.ctrlTextbox.MouseMove -= value; }
}
public new event MouseEventHandler MouseDown
{
add { this.ctrlTextbox.MouseDown += value; }
remove { this.ctrlTextbox.MouseDown -= value; }
}
public new event MouseEventHandler MouseDoubleClick
{
add { this.ctrlTextbox.MouseDoubleClick += value; }
remove { this.ctrlTextbox.MouseDoubleClick -= value; }
}
public new event EventHandler MouseLeave
{
add { this.ctrlTextbox.MouseLeave += value; }
remove { this.ctrlTextbox.MouseLeave -= value; }
}
public event EventHandler TextZoomChanged;
public ctrlScrollableTextbox()
{
InitializeComponent();
bool designMode = (LicenseManager.UsageMode == LicenseUsageMode.Designtime);
if(!designMode) {
this.panelSearch.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)));
this.panelSearch.Location = new System.Drawing.Point(this.Width - this.panelSearch.Width - 20, -1);
this.ctrlTextbox.ShowLineNumbers = true;
this.ctrlTextbox.ShowLineInHex = true;
this.hScrollBar.ValueChanged += hScrollBar_ValueChanged;
this.vScrollBar.ValueChanged += vScrollBar_ValueChanged;
this.ctrlTextbox.ScrollPositionChanged += ctrlTextbox_ScrollPositionChanged;
this.ctrlTextbox.SelectedLineChanged += ctrlTextbox_SelectedLineChanged;
new ToolTip().SetToolTip(picCloseSearch, "Close");
new ToolTip().SetToolTip(picSearchNext, "Find Next (F3)");
new ToolTip().SetToolTip(picSearchPrevious, "Find Previous (Shift-F3)");
}
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
this.panelSearch.Location = new System.Drawing.Point(this.Width - this.panelSearch.Width - 20, -1);
}
public bool ShowScrollbars
{
get
{
return this._showScrollbars;
}
set
{
this._showScrollbars = value;
this.hScrollBar.Visible = value;
this.vScrollBar.Visible = value;
}
}
public IScrollbarColorProvider ScrollbarColorProvider
{
set { this.vScrollBar.ColorProvider = value; }
}
private void ctrlTextbox_SelectedLineChanged(object sender, EventArgs e)
{
this.vScrollBar.Invalidate();
}
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Font BaseFont
{
get { return this.ctrlTextbox.BaseFont; }
set
{
this.ctrlTextbox.BaseFont = value;
UpdateHorizontalScrollbar();
this.ctrlTextbox.Invalidate();
}
}
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public int TextZoom
{
get { return this.ctrlTextbox.TextZoom; }
set {
if(this.ctrlTextbox.TextZoom != value) {
this.ctrlTextbox.TextZoom = value;
UpdateHorizontalScrollbar();
if(this.TextZoomChanged != null) {
this.TextZoomChanged(this, null);
}
}
}
}
public string GetWordUnderLocation(Point position)
{
return this.ctrlTextbox.GetWordUnderLocation(position);
}
private void ctrlTextbox_ScrollPositionChanged(object sender, EventArgs e)
{
this.vScrollBar.Value = this.ctrlTextbox.ScrollPosition;
this.hScrollBar.Value = this.ctrlTextbox.HorizontalScrollPosition;
UpdateHorizontalScrollbar();
UpdateVerticalScrollbar();
ScrollPositionChanged?.Invoke(null, null);
}
private void UpdateVerticalScrollbar()
{
this.vScrollBar.Maximum = this.ctrlTextbox.LineCount;
this.vScrollBar.VisibleLineCount = this.ctrlTextbox.GetNumberVisibleLines();
}
private void UpdateHorizontalScrollbar()
{
this.hScrollBar.Visible = this.ctrlTextbox.HorizontalScrollWidth > 0 && _showScrollbars;
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 ctrlTextbox.ILineStyleProvider StyleProvider { set { this.ctrlTextbox.StyleProvider = value; } }
public int GetLineIndex(int lineNumber)
{
return this.ctrlTextbox.GetLineIndex(lineNumber);
}
public int GetLineIndexAtPosition(int yPos)
{
return this.ctrlTextbox.GetLineIndexAtPosition(yPos);
}
public string GetLineNoteAtLineIndex(int lineIndex)
{
if(lineIndex >= 0 && lineIndex < this.ctrlTextbox.LineNumberNotes.Length) {
return this.ctrlTextbox.LineNumberNotes[lineIndex];
} else {
return "";
}
}
public int GetLineNumber(int lineIndex)
{
return this.ctrlTextbox.GetLineNumber(lineIndex);
}
public int GetLineNumberAtPosition(int yPos)
{
return this.GetLineNumber(this.GetLineIndexAtPosition(yPos));
}
public int GetNumberVisibleLines()
{
return this.ctrlTextbox.GetNumberVisibleLines();
}
public void ScrollToLineIndex(int lineIndex, eHistoryType historyType = eHistoryType.Always, bool scrollToTop = false, bool forceScroll = false)
{
this.ctrlTextbox.ScrollToLineIndex(lineIndex, historyType, scrollToTop, forceScroll);
}
public void ScrollToLineNumber(int lineNumber, eHistoryType historyType = eHistoryType.Always, bool scrollToTop = false, bool forceScroll = false)
{
this.ctrlTextbox.ScrollToLineNumber(lineNumber, historyType, scrollToTop, forceScroll);
}
public void CopySelection(bool copyLineNumbers, bool copyContentNotes, bool copyComments)
{
this.ctrlTextbox.CopySelection(copyLineNumbers, copyContentNotes, copyComments);
}
public void SetMessage(TextboxMessageInfo message)
{
this.ctrlTextbox.SetMessage(message);
}
public int CurrentLine
{
get { return this.ctrlTextbox.CurrentLine; }
}
public int SelectedLine
{
get { return this.ctrlTextbox.SelectedLine; }
}
public int LastSelectedLine
{
get { return this.ctrlTextbox.LastSelectedLine; }
}
public int CodeMargin
{
get { return this.ctrlTextbox.CodeMargin; }
}
protected override void OnMouseWheel(MouseEventArgs e)
{
base.OnMouseWheel(e);
this.vScrollBar.Value = Math.Min(this.vScrollBar.Maximum, Math.Max(0, this.vScrollBar.Value - e.Delta / 40));
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if(!this.cboSearch.Focused) {
//TODO
/*if(keyData == ConfigManager.Config.DebugInfo.Shortcuts.SelectAll) {
this.SelectAll();
return true;
}*/
switch(keyData) {
case Keys.Right | Keys.Shift:
case Keys.Down | Keys.Shift:
this.ctrlTextbox.MoveSelectionDown();
return true;
case Keys.Down:
case Keys.Right:
this.ctrlTextbox.SelectionStart = this.ctrlTextbox.SelectedLine + 1;
this.ctrlTextbox.SelectionLength = 0;
return true;
case Keys.Up | Keys.Shift:
case Keys.Left | Keys.Shift:
this.ctrlTextbox.MoveSelectionUp();
return true;
case Keys.Up:
case Keys.Left:
this.ctrlTextbox.SelectionStart = this.ctrlTextbox.SelectedLine - 1;
this.ctrlTextbox.SelectionLength = 0;
return true;
case Keys.Home | Keys.Shift:
this.ctrlTextbox.MoveSelectionUp(this.ctrlTextbox.LineCount);
break;
case Keys.End | Keys.Shift:
this.ctrlTextbox.MoveSelectionDown(this.ctrlTextbox.LineCount);
break;
case Keys.Home:
this.ctrlTextbox.SelectionStart = 0;
this.ctrlTextbox.SelectionLength = 0;
return true;
case Keys.End:
this.ctrlTextbox.SelectionStart = this.ctrlTextbox.LineCount - 1;
this.ctrlTextbox.SelectionLength = 0;
return true;
}
}
//TODO
/*
if(keyData == ConfigManager.Config.DebugInfo.Shortcuts.IncreaseFontSize) {
this.TextZoom += 10;
return true;
} else if(keyData == ConfigManager.Config.DebugInfo.Shortcuts.DecreaseFontSize) {
this.TextZoom -= 10;
return true;
} else if(keyData == ConfigManager.Config.DebugInfo.Shortcuts.ResetFontSize) {
this.TextZoom = 100;
return true;
} else if(keyData == ConfigManager.Config.DebugInfo.Shortcuts.Find) {
this.OpenSearchBox(true);
return true;
}*/
if(keyData == (Keys.Control | Keys.F)) {
this.OpenSearchBox(true);
return true;
}
switch(keyData) {
case Keys.PageUp | Keys.Shift:
this.ctrlTextbox.MoveSelectionUp(20);
return true;
case Keys.PageUp:
this.ctrlTextbox.SelectionStart-=20;
this.ctrlTextbox.SelectionLength = 0;
return true;
case Keys.PageDown | Keys.Shift:
this.ctrlTextbox.MoveSelectionDown(20);
return true;
case Keys.PageDown:
this.ctrlTextbox.SelectionStart+=20;
this.ctrlTextbox.SelectionLength = 0;
return true;
case Keys.Escape:
if(this.cboSearch.Focused) {
this.CloseSearchBox();
return true;
}
break;
}
return base.ProcessCmdKey(ref msg, keyData);
}
public void SelectAll()
{
this.ctrlTextbox.SelectionStart = 0;
this.ctrlTextbox.SelectionLength = this.ctrlTextbox.LineCount;
}
private void vScrollBar_ValueChanged(object sender, EventArgs e)
{
this.ctrlTextbox.ScrollPosition = this.vScrollBar.Value;
}
private void hScrollBar_ValueChanged(object sender, EventArgs e)
{
this.ctrlTextbox.HorizontalScrollPosition = this.hScrollBar.Value;
}
public string[] Addressing { set { this.ctrlTextbox.Addressing = value; } }
public string[] Comments { set { this.ctrlTextbox.Comments = value; } }
public int[] LineIndentations{ set { this.ctrlTextbox.LineIndentations = value; } }
public string[] TextLines
{
set
{
this.ctrlTextbox.TextLines = value;
UpdateVerticalScrollbar();
UpdateHorizontalScrollbar();
}
}
public string[] TextLineNotes
{
set
{
this.ctrlTextbox.TextLineNotes = value;
}
}
public string[] CompareLines
{
set
{
this.ctrlTextbox.CompareLines = value;
}
}
public int[] LineNumbers
{
set
{
this.ctrlTextbox.LineNumbers = value;
}
}
public string[] LineNumberNotes
{
set
{
this.ctrlTextbox.LineNumberNotes = value;
}
}
public bool ShowSingleContentLineNotes
{
get { return this.ctrlTextbox.ShowSingleContentLineNotes; }
set { this.ctrlTextbox.ShowSingleContentLineNotes = value; }
}
public bool ShowContentNotes
{
get { return this.ctrlTextbox.ShowContentNotes; }
set { this.ctrlTextbox.ShowContentNotes = value; }
}
public bool ShowCompactPrgAddresses { get { return this.ctrlTextbox.ShowCompactPrgAddresses; } set { this.ctrlTextbox.ShowCompactPrgAddresses = value; } }
public bool ShowLineNumberNotes
{
get { return this.ctrlTextbox.ShowLineNumberNotes; }
set { this.ctrlTextbox.ShowLineNumberNotes = value; }
}
public bool ShowSingleLineLineNumberNotes
{
get { return this.ctrlTextbox.ShowSingleLineLineNumberNotes; }
set { this.ctrlTextbox.ShowSingleLineLineNumberNotes = value; }
}
public bool ShowMemoryValues
{
get { return this.ctrlTextbox.ShowMemoryValues; }
set { this.ctrlTextbox.ShowMemoryValues = value; }
}
public bool HideSelection
{
get { return this.ctrlTextbox.HideSelection; }
set { this.ctrlTextbox.HideSelection = value; }
}
public bool CodeHighlightingEnabled
{
get { return this.ctrlTextbox.CodeHighlightingEnabled; }
set { this.ctrlTextbox.CodeHighlightingEnabled = value; }
}
public int LineCount { get { return this.ctrlTextbox.LineCount; } }
public int SelectionStart { get { return this.ctrlTextbox.SelectionStart; } }
public int SelectionLength { get { return this.ctrlTextbox.SelectionLength; } }
public string Header
{
set
{
this.ctrlTextbox.Header = value;
}
}
public int MarginWidth { set { this.ctrlTextbox.MarginWidth = value; } }
public void OpenSearchBox(bool forceFocus = false)
{
bool focus = !this.panelSearch.Visible;
this.panelSearch.Visible = true;
if(focus || forceFocus) {
this.cboSearch.Focus();
this.cboSearch.SelectAll();
}
}
private void CloseSearchBox()
{
this.ctrlTextbox.Search(null, false, false);
this.panelSearch.Visible = false;
this.Focus();
}
public void FindNext()
{
this.OpenSearchBox();
this.ctrlTextbox.Search(this.cboSearch.Text, false, false);
}
public void FindPrevious()
{
this.OpenSearchBox();
this.ctrlTextbox.Search(this.cboSearch.Text, true, false);
}
private void picCloseSearch_Click(object sender, EventArgs e)
{
this.CloseSearchBox();
}
private void picSearchPrevious_MouseUp(object sender, MouseEventArgs e)
{
this.FindPrevious();
}
private void picSearchNext_MouseUp(object sender, MouseEventArgs e)
{
this.FindNext();
}
private void cboSearch_TextUpdate(object sender, EventArgs e)
{
if(!this.ctrlTextbox.Search(this.cboSearch.Text, false, true)) {
this.cboSearch.BackColor = Color.Coral;
} else {
this.cboSearch.BackColor = Color.Empty;
}
}
private void cboSearch_KeyDown(object sender, KeyEventArgs e)
{
if(e.KeyCode == Keys.Enter) {
this.FindNext();
if(this.cboSearch.Items.Contains(this.cboSearch.Text)) {
this.cboSearch.Items.Remove(this.cboSearch.Text);
}
this.cboSearch.Items.Insert(0, this.cboSearch.Text);
e.Handled = true;
e.SuppressKeyPress = true;
}
}
public string GetLineContent(int lineIndex)
{
return this.ctrlTextbox.GetFullWidthString(lineIndex);
}
public void NavigateForward()
{
this.ctrlTextbox.NavigateForward();
}
public void NavigateBackward()
{
this.ctrlTextbox.NavigateBackward();
}
public bool GetNoteRangeAtLocation(int yPos, out int rangeStart, out int rangeEnd)
{
rangeStart = -1;
rangeEnd = -1;
int lineIndex = GetLineIndexAtPosition(yPos);
while(lineIndex < LineCount - 2 && string.IsNullOrWhiteSpace(GetLineNoteAtLineIndex(lineIndex))) {
//Find the address of the next line with an address
lineIndex++;
}
if(Int32.TryParse(GetLineNoteAtLineIndex(lineIndex), NumberStyles.AllowHexSpecifier, null, out rangeStart)) {
while(lineIndex < LineCount - 2 && string.IsNullOrWhiteSpace(GetLineNoteAtLineIndex(lineIndex + 1))) {
//Find the next line with an address
lineIndex++;
}
if(Int32.TryParse(GetLineNoteAtLineIndex(lineIndex + 1), NumberStyles.AllowHexSpecifier, null, out rangeEnd)) {
rangeEnd--;
return true;
}
}
return false;
}
}
}