SuperDesign/Source/RySmartEditor/Controls/Highlight/HighlightEditor.cs
zilinsoft 993f1ca1a9 ### 2024-12-20 星期五更新
------
#### SuperDesign    V3.0.2412.2001
- *.[新增]新增程序更新日志设置和自动发布功能。
- *.[修复]修复Post数据格式不正确时双击文本框会导致软件闪退的BUG。
2024-12-20 08:15:19 +08:00

801 lines
29 KiB
C#

using ScintillaNET;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static ScintillaNET.Style;
using VPKSoft.ScintillaLexers;
using ScintillaNET_FindReplaceDialog.FindAllResults;
using ScintillaNET_FindReplaceDialog;
using System.Windows.Forms;
using ryCommon;
using static VPKSoft.ScintillaLexers.LexerEnumerations;
using Newtonsoft.Json.Linq;
using DiffPlex.Model;
using IfacesEnumsStructsClasses;
namespace ryControls
{
public partial class HighlightEditor : Control
{
public HighlightEditor() : base()
{
if(!this.DesignMode)
{
this.Controls.Add(Editor);
Editor.Parent = this;
Editor.Dock= DockStyle.Fill;
}
Editor.CaretLineBackColor = Color.FromArgb(255, 255, 192);
Editor.AutoCAutoHide = true;
Editor.TextChanged += Scintilla_TextChanged;
Editor.ContextMenuStrip = contextMenuStripHighlightText21;
Editor.CharAdded += HighlightEditor_CharAdded;
Editor.UpdateUI += HighlightEditor_UpdateUI;
Editor.EolMode = Eol.CrLf;
//Editor.AdditionalCaretForeColor=Color.Red;
//Editor
//base.HandleCreated += HighlightEditor_HandleCreated;
//base.InternalFocusFlag = true;
MyFindReplace = new FindReplace
{
Scintilla = Editor
};
AutoComplete.TargetControlWrapper = new ScintillaWrapper(Editor);
Editor.DoubleClick += Editor_DoubleClick;
var ind_17= Editor.Indicators[17];
ind_17.ForeColor = Color.FromArgb(232, 232, 255);
ind_17.Alpha = 100;
ind_17.Style = IndicatorStyle.RoundBox;
ind_17.Under = true;
_indicator = Editor.Indicators[16];
_indicator.ForeColor = Color.Red;
//_indicator.ForeColor = Color.LawnGreen; //Smart highlight
_indicator.Alpha = 100;
_indicator.Style = IndicatorStyle.RoundBox;
_indicator.Under = true;
Editor.IndicatorCurrent = _indicator.Index;
this.LostFocus += HighlightEditor_LostFocus;
Editor.LostFocus += HighlightEditor_LostFocus;
Editor.InternalFocusFlag = true;
Editor.CaretLineBackColorAlpha = 60;
Editor.CaretPeriod = 0;
}
private void HighlightEditor_LostFocus(object sender, EventArgs e)
{
//Editor.AdditionalCaretForeColor
}
#region
/// <summary>
/// 读取或设置只读模式
/// </summary>
[Description("是否开启只读模式")]
public bool ReadOnly
{
get { return Editor.ReadOnly; }
set { Editor.ReadOnly = value; }
}
[DefaultValue(ScintillaNET.BorderStyle.Fixed3D)]
[Category("Appearance")]
[Description("编辑器边框.")]
public ScintillaNET.BorderStyle BorderStyle
{
get { return Editor.BorderStyle; }
set { Editor.BorderStyle = value; }
}
/// <summary>
/// 是否开启行号
/// </summary>
[Description("是否开启行号")]
public bool LineNumberOn { get; set; } = true;
/// <summary>
/// 是否使用自定义搜索功能
/// </summary>
[Description("是否使用自定义搜索功能")]
public bool UseCustomShowFindReplace { get; set; } = false;
/// <summary>
/// 是否使用自定义定位行功能
/// </summary>
[Description("是否使用自定义定位行功能")]
public bool UseCustomGotoLine { get; set; } = false;
/// <summary>
/// 当前高亮语言
/// </summary>
public LexerType CurHighliteLang
{
get; set;
} = LexerType.Text;
/// <summary>
/// 获取或设置是否开启自动标记功能
/// </summary>
[Description("开启自动标记功能")]
public bool AutoMark { get; set; } = true;
/// <summary>
/// 获取或设置编辑器字体
/// </summary>
[EditorBrowsable(EditorBrowsableState.Always)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[DefaultValue(typeof(Font), "Consolas, 14pt")]
public override Font Font
{
get => base.Font;
set
{
base.Font = value;
Editor.Font = value;
for (int i = 0; i < Editor.Styles.Count; i++)
{
if (i != CallTip) SetStyleFont(i, value);
}
}
}
/// <summary>
/// Sets font style properties
/// </summary>
/// <param name="index"></param>
/// <param name="font"></param>
private void SetStyleFont(int index, Font font)
{
Editor.Styles[index].Font = font.Name;
Editor.Styles[index].SizeF = font.SizeInPoints;
Editor.Styles[index].Bold = font.Bold;
Editor.Styles[index].Italic = font.Italic;
Editor.Styles[index].Underline = font.Underline;
}
/// <summary>
/// 获取或设置当前选中的文字
/// </summary>
public string SelectedText
{
get {
var text= Editor.SelectedText.TrimEnd('\0');
if (text == "\0") { text = ""; }
return text;
}
set { Editor.ReplaceSelection(value); }
}
/// <summary>
/// 设置或获取文本
/// </summary>
public override string Text
{
get { return Editor.Text; }
set
{
bool Readonly = Editor.ReadOnly;
if (Readonly)
{
Editor.ReadOnly = false;
}
Editor.Text = value;
if (Readonly)
{
Editor.ReadOnly = true;
}
}
}
#endregion
#region
/// <summary>
/// 在自带菜单弹出前激发
/// </summary>
[Description("在自带菜单弹出前激发")]
public event CancelEventHandler OnMenuOpening;
/// <summary>
/// 保存热键发生时
/// </summary>
[Description("保存热键发生时")]
public event EventHandler OnSaveKeyHappen;
/// <summary>
/// 打开自定义查找窗口时发生
/// </summary>
[Description("打开自定义查找窗口时发生")]
public event EventHandler OnCustomShowFind;
/// <summary>
/// 打开自定义替换窗口时发生
/// </summary>
[Description("打开自定义替换窗口时发生")]
public event EventHandler OnCustomShowReplace;
/// <summary>
/// 打开自定义定位行窗口时发生
/// </summary>
[Description("打开自定义定位行窗口时发生")]
public event EventHandler OnCustomShowGotoLine;
/// <summary>
/// 选定内容发生变化
/// </summary>
[Description("选定内容发生变化")]
public event EventHandler OnSelectedChanged;
#endregion
#region
private void Editor_DoubleClick(object sender, DoubleClickEventArgs e)
{
base.OnDoubleClick(new EventArgs());
}
private void ContextMenuStripRichText1_Opening(object sender, CancelEventArgs e)
{
OnMenuOpening?.Invoke(sender, e);
}
private string Indent(int len)
{
var str = "";
for (int i = 0; i < len; i++)
{
str += " ";
}
return str;
}
private string last_selected = "";
private void HighlightEditor_UpdateUI(object sender,UpdateUIEventArgs e)
{
if (e.Change != UpdateChange.Content)
{
var selected_text = SelectedText;
var sel_start = Editor.SelectionStart;
var sel_id= sel_start + "|" + selected_text.Length;
if (sel_id != last_selected)
{
ClearAllMark();
last_selected = sel_id;
if (AutoMark)
{
MarkText(selected_text);
}
OnSelectedChanged?.Invoke(this, EventArgs.Empty);
}
if (selected_text.Length == 0)
{
var a = Editor.BraceMatch(sel_start);
if (a >= 0)
{
Editor.IndicatorCurrent = _indicator.Index;
Editor.IndicatorFillRange(a, 1);
Editor.IndicatorFillRange(sel_start, 1);
}
else
{
if (sel_start - 1 >= 0)
{
a = Editor.BraceMatch(sel_start - 1);
if (a >= 0)
{
Editor.IndicatorCurrent = _indicator.Index;
Editor.IndicatorFillRange(a, 1);
Editor.IndicatorFillRange(sel_start - 1, 1);
}
}
}
}
var pos = Editor.CurrentPosition;
var line = Editor.LineFromPosition(pos);
Editor.IndicatorCurrent = 17;
Editor.IndicatorFillRange(Editor.Lines[line].Position, Editor.Lines[line].Length);
}
if (LastProcessedChar != 0)
{
var pos = Editor.CurrentPosition;
var line = Editor.LineFromPosition(pos);
if (line >= 1)
{
if (LastProcessedChar == 10)
{
//Editor.Lines[line].Indentation = Editor.Lines[line - 1].Indentation;
var nPrevLineText = Editor.Lines[line - 1].Text.Trim();//获取上一行文本
if (nPrevLineText.Length >= 1)
{
if ("{(<[".IndexOfEx(nPrevLineText.Substring(nPrevLineText.Length - 1, 1)) >= 0)
{
if (Editor.Lines[line].Text.Trim().StartsWith("}")) {
Editor.ReplaceSelection(Indent(Editor.Lines[line - 1].Indentation));
}
else {
Editor.ReplaceSelection(Indent(Editor.Lines[line - 1].Indentation + 4));
}
}
else
{
Editor.ReplaceSelection(Indent(Editor.Lines[line - 1].Indentation));
}
}
else
{
for (int i = line - 2; i >0; i--)
{
nPrevLineText = Editor.Lines[i].Text.Trim();
if (nPrevLineText.Length >= 1)
{
if ("{(<[".IndexOfEx(nPrevLineText.Substring(nPrevLineText.Length - 1, 1)) >= 0)
{
if (Editor.Lines[line].Text.Trim().StartsWith("}"))
{
Editor.ReplaceSelection(Indent(Editor.Lines[i].Indentation));
}
else
{
Editor.ReplaceSelection(Indent(Editor.Lines[i].Indentation + 4));
}
}
else
{
Editor.ReplaceSelection(Indent(Editor.Lines[i].Indentation));
}
break;
}
}
}
}
}
LastProcessedChar = 0;
// if(LastProcessedChar=='}' && this.GetCharAt(pos-2)==' ' && LastProcessedChar!=0)
//{
// var startpos = this.WordStartPosition(pos - 1, false);
// var linepos = this.Lines[line].Indentation;
// if(startpos== linepos)
// {
// var othpos = this.BraceMatch(pos - 1);
// var othline = this.LineFromPosition(othpos);
// int nIndent = this.Lines[othline].Indentation;
// this.TargetStart = startpos;
// this.TargetEnd = pos - 1;
// this.ReplaceTarget("xxxxxxx");
// }
//}
}
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == (Keys.Control | Keys.S))
{
OnSaveKeyHappen?.Invoke(this, new EventArgs());
return true;
}
else if (keyData == (Keys.Control | Keys.F))
{
ShowFind();
return true;
}
else if (keyData == (Keys.Control | Keys.B))
{
return true;
}
else if (keyData == (Keys.Control | Keys.M))
{
return true;
}
else if (keyData == (Keys.Control | Keys.N))
{
return true;
}
else if (keyData == (Keys.Control | Keys.J))
{
return true;
}
else if (keyData == (Keys.Control | Keys.Q))
{
return true;
}
else if (keyData == (Keys.Control | Keys.U))
{
return true;
}
else if (keyData == (Keys.Control | Keys.I))
{
return true;
}
else if (keyData == (Keys.Control | Keys.P))
{
return true;
}
else if (keyData == (Keys.Control | Keys.W))
{
return true;
}
else if (keyData == (Keys.Control | Keys.E))
{
return true;
}
return base.ProcessCmdKey(ref msg, keyData);//这里就是返回没有重写的键位,也就是这个函数原本的处理方式 //其余键位默认处理
}
private void HighlightEditor_CharAdded(object sender, CharAddedEventArgs e)
{
LastProcessedChar = e.Char;
}
private void Scintilla_TextChanged(object sender, EventArgs e)
{
base.OnTextChanged(new EventArgs());
if (LineNumberOn)
{
Scintilla scintilla = (Scintilla)sender;
int maxLineNumberCharLengthFromTag = mark;
// Did the number of characters in the line number display change?
// i.e. nnn VS nn, or nnnn VS nn, etc...
var maxLineNumberCharLength = scintilla.Lines.Count.ToString().Length;
if (maxLineNumberCharLength == maxLineNumberCharLengthFromTag)
return;
// Calculate the width required to display the last line number
// and include some padding for good measure.
const int padding = 2;
scintilla.Margins[0].Width = scintilla.TextWidth(ScintillaNET.Style.LineNumber, new string('9', maxLineNumberCharLength + 1)) + padding;
mark = maxLineNumberCharLength;
}
}
/// <summary>
/// 判断改行为函数开头行
/// </summary>
/// <param name="line"></param>
/// <returns></returns>
private bool IsFunLine(string line)
{
if (line.StartsWith("public", StringComparison.OrdinalIgnoreCase) ||
line.StartsWith("private", StringComparison.OrdinalIgnoreCase) ||
line.StartsWith("protected", StringComparison.OrdinalIgnoreCase) ||
line.StartsWith("const", StringComparison.OrdinalIgnoreCase))
{
return true;
}
else
{
if (line.IndexOfEx("(") > 0 && line.IndexOfEx(")") > 0 && line.IndexOfEx("function")>=0)
{
return true;
}
}
return false;
}
#endregion
#region
public void FindText(string FindText)
{
Editor.TargetStart = 0;
Editor.TargetEnd = Editor.TextLength;
var pos = Editor.SearchInTarget(FindText);
if (pos >= 0)
{
Editor.FirstVisibleLine = Editor.LineFromPosition(pos);
}
}
/// <summary>
/// 获取最近的函数名称所在行内容
/// </summary>
/// <param name="high_editor"></param>
/// <param name="fun_line_num"></param>
/// <returns></returns>
public string GetNearestFunLineStr(HighlightEditor high_editor,out int fun_line_num)
{
var line_num = high_editor.Editor.LineFromPosition(high_editor.Editor.CurrentPosition == 0 ? high_editor.Editor.FirstVisibleLine : high_editor.Editor.CurrentPosition);
var lines = high_editor.Editor.Lines;
var pre_fun_line = "";
var pre_fun_line_num = -1;
var next_fun_line = "";
var next_fun_line_num = -1;
string fun_line;
for (int i = line_num; i >= 0; i--)
{
var line = lines[i].Text.Trim();
if (IsFunLine(line))
{
pre_fun_line = line;
pre_fun_line_num = i;
break;
}
}
if (pre_fun_line_num == -1 || (line_num - pre_fun_line_num) > 3)
{
for (int i = line_num + 1; i < lines.Count; i++)
{
var line = lines[i].Text.Trim();
if (IsFunLine(line))
{
next_fun_line = line;
next_fun_line_num = i;
break;
}
}
}
if (next_fun_line_num == -1)
{
fun_line = pre_fun_line;
fun_line_num = pre_fun_line_num;
}
else if (pre_fun_line_num == -1)
{
fun_line = next_fun_line;
fun_line_num = next_fun_line_num;
}
else if ((line_num - pre_fun_line_num) > (next_fun_line_num - line_num))
{
fun_line = next_fun_line;
fun_line_num = next_fun_line_num;
}
else
{
fun_line = pre_fun_line;
fun_line_num = pre_fun_line_num;
}
return fun_line;
}
/// <summary>
/// 到达与指定编辑器同样的位置
/// </summary>
/// <param name="high_editor"></param>
public int GotoSameLocation(HighlightEditor high_editor)
{
if (high_editor.Editor.CurrentPosition == 0 && high_editor.Editor.FirstVisibleLine==0) { return 0; }
var result = 0;
var line_num=high_editor.Editor.LineFromPosition(high_editor.Editor.CurrentPosition==0? high_editor.Editor.FirstVisibleLine: high_editor.Editor.CurrentPosition);
var lines = high_editor.Editor.Lines;
string fun_line= GetNearestFunLineStr(high_editor,out var fun_line_num);
if (fun_line_num >= 0)
{
Editor.TargetStart = 0;
Editor.TargetEnd = Editor.TextLength;
var pos= Editor.SearchInTarget(fun_line);
if(pos>=0)
{
Editor.FirstVisibleLine = Editor.LineFromPosition(pos);
result = Editor.FirstVisibleLine;
}
else
{
var str = fun_line.GetStr("", "(");
if(str.Length>0)
{
pos = Editor.SearchInTarget(str);
if (pos >= 0)
{
Editor.FirstVisibleLine = Editor.LineFromPosition(pos);
result = Editor.FirstVisibleLine;
}
}
}
}
return result;
//var kk = Editor.Lines.FirstOrDefault(f => f.Text == high_editor.Editor.Lines[line_num].Text);
}
/// <summary>
/// 标记文本
/// </summary>
/// <param name="search_text"></param>
public void MarkText(string search_text)
{
if (search_text.Length == 0)
{
ClearAllMark();
return;
}
if (search_text.IndexOfEx("\n") >= 0 || !search_text.Replace("_","").IsEngOrNum())
{
ClearAllMark();
if (search_text.Length == 1)
{
var a= Editor.BraceMatch(Editor.SelectionStart);
if (a >= 0)
{
Editor.IndicatorCurrent = _indicator.Index;
Editor.IndicatorFillRange(a, 1);
Editor.IndicatorFillRange(Editor.SelectionStart, 1);
}
return;
}
return;
}
var find_count = 0;
//Editor.IndicatorCurrent = _indicator.Index;
var _text = Editor.Text;
var search_len = search_text.Length;
var total_len = _text.Length;
var pos = _text.IndexOf(search_text);
while (pos != -1)
{
if (pos > 0 && pos < total_len - 1)
{
var word = _text.Substring(pos - 1, 1)[0];
if ((word >= 'a' && word <= 'z') || (word >= 'A' && word <= 'Z') || (word >= '0' && word <= '9') || word=='_')
{
//是数字字母不处理
pos = _text.IndexOf(search_text, pos + search_len);
continue;
}
if ((pos + search_len) <= total_len - 1)
{
word = _text.Substring(pos + search_len, 1)[0];
if ((word >= 'a' && word <= 'z') || (word >= 'A' && word <= 'Z') || (word >= '0' && word <= '9') || word == '_')
{
//是数字字母不处理
pos = _text.IndexOf(search_text, pos + search_len);
continue;
}
}
}
find_count++;
Editor.IndicatorCurrent = _indicator.Index;
Editor.IndicatorFillRange(pos, search_len);
pos = _text.IndexOf(search_text, pos + search_len);
}
if (find_count == 1)
{
ClearAllMark();
return;
}
}
/// <summary>
/// 清除所有标记
/// </summary>
public void ClearAllMark()
{
int currentIndicator = Editor.IndicatorCurrent;
Editor.IndicatorCurrent = 17;
Editor.IndicatorClearRange(0, Editor.TextLength);
Editor.IndicatorCurrent = _indicator.Index;
Editor.IndicatorClearRange(0, Editor.TextLength);
Editor.IndicatorCurrent = currentIndicator;
}
/// <summary>
/// 设置高亮文本
/// </summary>
/// <param name="format"></param>
public void SetHightlightText(string format)
{
SetHightlightText(this.Text, format);
}
/// <summary>
/// 设置高亮文本
/// </summary>
/// <param name="text"></param>
/// <param name="format"></param>
public void SetHightlightText(string text, string format)
{
bool Readonly = Editor.ReadOnly;
if (Readonly)
{
Editor.ReadOnly = false;
}
Editor.Text = text;
var _formart = format;
if (_formart == "c#") { _formart = "cs"; }
try
{
var LexerType = VPKSoft.ScintillaLexers.HelperClasses.LexerFileExtensions.LexerTypeFromFileName(@"1." + _formart);
CurHighliteLang = LexerType;
ScintillaLexers.CreateLexer(Editor, LexerType);
}
catch { CurHighliteLang = LexerType.Unknown; }
if (Readonly)
{
Editor.ReadOnly = true;
}
Editor.Font = this.Font;
for (int i = 0; i < Editor.Styles.Count; i++)
{
if (i != CallTip) SetStyleFont(i, this.Font);
}
}
/// <summary>
/// 设置文本
/// </summary>
/// <param name="text"></param>
/// <param name="format"></param>
public void SetText(string text)
{
bool Readonly = Editor.ReadOnly;
if (Readonly)
{
Editor.ReadOnly = false;
}
Editor.Text = text;
if (Readonly)
{
Editor.ReadOnly = true;
}
}
/// <summary>
/// 显示查找对话框
/// </summary>
public void ShowFind()
{
if (UseCustomShowFindReplace)
{
OnCustomShowFind?.Invoke(this, new EventArgs());
}
else
{
MyFindReplace.ShowFind();
}
}
/// <summary>
/// 显示替换对话框
/// </summary>
public void ShowReplace()
{
if (UseCustomShowFindReplace)
{
OnCustomShowReplace?.Invoke(this, new EventArgs());
}
else
{
MyFindReplace.ShowFind(1);
}
}
/// <summary>
/// 显示行定位对话框
/// </summary>
public void ShowGotoLine()
{
if (UseCustomGotoLine)
{
OnCustomShowGotoLine?.Invoke(this, new EventArgs());
}
else
{
GoTo MyGoTo = new GoTo(Editor);
MyGoTo.ShowGoToDialog();
}
}
/// <summary>
/// 根据标签获得菜单项
/// </summary>
/// <param name="tag"></param>
/// <returns></returns>
public ToolStripItem GetMenuItem(string tag)
{
for (int i = 0; i < contextMenuStripHighlightText21.Items.Count; i++)
{
var item = contextMenuStripHighlightText21.Items[i];
if (item.Tag == null) { continue; }
if (tag == item.Tag.ToString())
{
return item;
}
}
return null;
}
/// <summary>
/// 设置自动完成列表
/// </summary>
/// <param name="list"></param>
public void SetAutoCompleteList(List<string> list)
{
AutoComplete.SetAutocompleteItems(list);
}
/// <summary>
/// 添加菜单分隔线
/// </summary>
/// <returns></returns>
public ToolStripSeparator AddSeparatorMenu()
{
return contextMenuStripHighlightText21.AddSeparatorMenu();
}
/// <summary>
/// 添加菜单
/// </summary>
/// <param name="name"></param>
/// <param name="tag"></param>
/// <returns></returns>
public ToolStripMenuItem AddMenu(string name, string tag)
{
return contextMenuStripHighlightText21.AddMenu(name, tag);
}
#endregion
#region
int mark = -1;
private string lastSelectedText = "";
private int LastProcessedChar;
private Indicator _indicator;
public override ContextMenuStrip ContextMenuStrip { get => Editor.ContextMenuStrip; set => Editor.ContextMenuStrip = value; }
private readonly FindReplace MyFindReplace;
public ScintillaNET.Scintilla Editor { get; set; } = new Scintilla();
private readonly AutocompleteMenuNS.AutocompleteMenu AutoComplete = new AutocompleteMenuNS.AutocompleteMenu();
private readonly ryControls.ContextMenuStripHighlightText2 contextMenuStripHighlightText21 = new ContextMenuStripHighlightText2();
#endregion
}
}