Skip to content

Commit e539bbb

Browse files
committed
add: 显示当前光标位置
1 parent 299acec commit e539bbb

File tree

2 files changed

+108
-53
lines changed

2 files changed

+108
-53
lines changed

llcomNext/LLCOM/Models/TerminalBlock.cs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ namespace LLCOM.Models;
88
/// <summary>
99
/// 一个终端块,包含各项信息
1010
/// </summary>
11-
public class TerminalBlock
11+
public class TerminalBlock : ICloneable
1212
{
13-
//颜色均只存储颜色值,30~37、90~97为颜色值,0为默认颜色
13+
//颜色均只存储颜色值,30~37、90~97为颜色值,0为默认颜色,-1表示反转
1414

1515
public int Background { get; set; }
1616
public int Foreground { get; set; }
@@ -19,6 +19,8 @@ public static string Color2BindingName(int color, bool isForeground)
1919
{
2020
if(color == 0)
2121
return isForeground ? "TerminalTheme.Foreground" : "TerminalTheme.Background";
22+
if (color == -1)
23+
return isForeground ? "TerminalTheme.Background" : "TerminalTheme.Foreground";
2224
return "TerminalTheme.Code" + color.ToString();
2325
}
2426
public string ForegroundBindingName => Color2BindingName(Foreground, true);
@@ -57,6 +59,8 @@ public string Text
5759
public TerminalBlock MakeNew(string text) =>
5860
new TerminalBlock(text, Background, Foreground, IsBold, IsUnderLine, IsItalic);
5961

62+
public object Clone() => new TerminalBlock(Text, Background, Foreground, IsBold, IsUnderLine, IsItalic);
63+
6064
//合并样式相同的数据块,优化性能
6165
public static void OptimizeBlocks(List<TerminalBlock> blocks)
6266
{
@@ -104,4 +108,5 @@ public TerminalBlock(string text,
104108
IsUnderLine = isUnderLine;
105109
IsItalic = isItalic;
106110
}
111+
107112
}

llcomNext/LLCOM/Models/TerminalObject.cs

Lines changed: 101 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,16 @@ private void TerminalChanged()
2626
}
2727

2828
//用于存放终端数据的缓存
29-
private readonly List<List<TerminalBlock>> _cacheLines = [];
29+
private List<List<TerminalBlock>> CacheLines { get; } = [];
3030

3131
//当前光标位置
3232
//X从0开始,最大可到达窗口宽度(再增加就需要换行了)
3333
//Y从0开始,最大可到达窗口高度-1
34-
private int _positionX = 0;
35-
private int _positionY = 0;
34+
private int PositionX { get; set; } = 0;
35+
private int PositionY { get; set; } = 0;
3636

3737
//当前的颜色、字体等信息,存到TerminalBlock中
38-
private TerminalBlock _currentState = new(String.Empty);
38+
private TerminalBlock CurrentState { get; set; } = new(String.Empty);
3939

4040
//MaxCacheLines表示终端缓存的行数,超过这个行数后会删除最上面的行
4141
private readonly int _maxCacheLines = Utils.Setting.TerminalBufferLines;
@@ -48,25 +48,25 @@ private void TerminalChanged()
4848
private void AddLine()
4949
{
5050
//添加行
51-
_cacheLines.Add([]);
51+
CacheLines.Add([]);
5252
//如果超过了最大行数,删除最上面的行
53-
if (_cacheLines.Count > _maxCacheLines)
54-
_cacheLines.RemoveAt(0);
55-
if (_currentLine != 0)
53+
if (CacheLines.Count > _maxCacheLines)
54+
CacheLines.RemoveAt(0);
55+
if (CurrentLine != 0)
5656
{
57-
_currentLine--;
57+
CurrentLine--;
5858
//如果当前行数超过了最大行数,设置为最大行数
59-
if (_currentLine > _cacheLines.Count - _windowHeight)
60-
_currentLine = _cacheLines.Count - _windowHeight;
61-
if (_currentLine < 0) _currentLine = 0;
59+
if (CurrentLine > CacheLines.Count - _windowHeight)
60+
CurrentLine = CacheLines.Count - _windowHeight;
61+
if (CurrentLine < 0) CurrentLine = 0;
6262
}
6363
}
6464

6565
/// <summary>
6666
/// 基于当前光标,往后追加文本
6767
/// 文本不得包含不可见字符
6868
/// </summary>
69-
/// <param name="text">待添加的文本</param>
69+
/// <param name="texts">待添加的文本</param>
7070
public void AddText(char[] texts)//TODO)) 保持private
7171
{
7272
//防止没有设置窗口大小的时候就添加数据
@@ -77,16 +77,16 @@ public void AddText(char[] texts)//TODO)) 保持private
7777
while (chars.Length > 0)
7878
{
7979
//当前光标位置后还有多少个字符的空间
80-
var space = _windowWidth - _positionX;
80+
var space = _windowWidth - PositionX;
8181
//剩余空间不足,添加新行
8282
if (space <= 0)
8383
{
84-
_positionX = 0;
85-
_positionY++;//超过高度后面再管
84+
PositionX = 0;
85+
PositionY++;//超过高度后面再管
8686
space = _windowWidth;
8787
}
8888
//记录一下修改前的X光标位置
89-
var oldX = _positionX;
89+
var oldX = PositionX;
9090

9191
//放置文本
9292
var sb = new StringBuilder();
@@ -103,45 +103,45 @@ public void AddText(char[] texts)//TODO)) 保持private
103103
//去除掉已经添加的字符
104104
chars = chars[1..];
105105
//光标位置往后挪动
106-
_positionX += length;
106+
PositionX += length;
107107
}
108108
if(space < 0)
109109
{
110110
//如果剩余空间不足,说明最后一格放不下这个宽字符
111111
//直接把X位置打到头,交够下一轮来处理
112-
_positionX = _windowWidth;
112+
PositionX = _windowWidth;
113113
}
114114
//添加文本
115115
var text = sb.ToString();
116-
var line = _currentState.MakeNew(text);
116+
var line = CurrentState.MakeNew(text);
117117

118118
//这一行数据要修改
119119
List<TerminalBlock> needChangeLine;
120120

121121
//超过了最大高度,说明要新开一行
122-
if (_positionY >= _windowHeight)
122+
if (PositionY >= _windowHeight)
123123
{
124-
_positionY = _windowHeight - 1;
124+
PositionY = _windowHeight - 1;
125125
AddLine();
126-
needChangeLine = _cacheLines[^1];
126+
needChangeLine = CacheLines[^1];
127127
}
128128
//当前缓存的行数还没有达到显示行高,也开新行
129-
else if (_cacheLines.Count - 1 < _positionY)
129+
else if (CacheLines.Count - 1 < PositionY)
130130
{
131-
var needLineCount = _positionY - _cacheLines.Count + 1;
131+
var needLineCount = PositionY - CacheLines.Count + 1;
132132
for (int i = 0; i < needLineCount; i++)
133133
AddLine();
134-
needChangeLine = _cacheLines[^1];
134+
needChangeLine = CacheLines[^1];
135135
}
136136
//不是新行,需要更改当前行的数据
137137
else
138138
{
139139
//计算开始行下标的偏移量
140-
var lineStartOffset = _cacheLines.Count - _windowHeight;
140+
var lineStartOffset = CacheLines.Count - _windowHeight;
141141
if(lineStartOffset < 0)
142142
lineStartOffset = 0;
143143
//使用当前行
144-
needChangeLine = _cacheLines[_positionY + lineStartOffset];
144+
needChangeLine = CacheLines[PositionY + lineStartOffset];
145145
}
146146

147147
var allLength = needChangeLine.Sum(l => l.Length);
@@ -259,8 +259,8 @@ public void AddText(char[] texts)//TODO)) 保持private
259259
//TODO)) 仅用于测试
260260
public void ChangePosition(int x, int y)
261261
{
262-
_positionX = x;
263-
_positionY = y;
262+
PositionX = x;
263+
PositionY = y;
264264
}
265265

266266
/// <summary>
@@ -272,9 +272,9 @@ public List<List<TerminalBlock>> GetShowLines()
272272
List<List<TerminalBlock>> cacheLines = new();
273273

274274
//计算出要显示的行数范围
275-
int allLines = _cacheLines.Count;
275+
int allLines = CacheLines.Count;
276276
//起始行和结束行,闭区间,从0开始,代表CacheLines的项目下标
277-
int startLine = allLines - _windowHeight - _currentLine;
277+
int startLine = allLines - _windowHeight - CurrentLine;
278278
if (startLine < 0)
279279
startLine = 0;
280280
int endLine = startLine + _windowHeight - 1;
@@ -285,7 +285,7 @@ public List<List<TerminalBlock>> GetShowLines()
285285
for (int i = startLine; i <= endLine; i++)
286286
{
287287
//添加行
288-
var line = _cacheLines[i];
288+
var line = CacheLines[i];
289289
cacheLines.Add(line);
290290
}
291291

@@ -296,10 +296,60 @@ public List<List<TerminalBlock>> GetShowLines()
296296
cacheLines.Add([]);
297297
}
298298
//把当前光标位置背景和前景色反色处理
299-
var posY = _positionY;
300-
if (posY < _cacheLines.Count)
299+
if (PositionY < cacheLines.Count)
301300
{
302-
//TODO)) 这里需要处理光标位置
301+
//这里需要处理光标位置
302+
//复制一个新的行来替换掉现有的行用来展示
303+
var tempLine = new List<TerminalBlock>();
304+
foreach (var block in cacheLines[PositionY])
305+
{
306+
tempLine.Add((TerminalBlock)block.Clone());
307+
}
308+
309+
var allLength = tempLine.Sum(l => l.Length);
310+
//光标没有重叠,说明光标位置在当前行的后面
311+
if (allLength <= PositionX)
312+
{
313+
//加几个空格,直到光标位置
314+
if(allLength < PositionX)
315+
tempLine.Add(new TerminalBlock(new string(' ', allLength - PositionX)));
316+
tempLine.Add(new TerminalBlock(new string(' ', 1),-1,-1));
317+
}
318+
else
319+
{
320+
var charLine = new List<TerminalBlock>();
321+
var count = 0;
322+
//把这一行按字符拆碎
323+
foreach (var block in tempLine)
324+
{
325+
//拆碎
326+
var tempChars = block.Text.ToCharArray();
327+
foreach (var c in tempChars)
328+
{
329+
var start = count;
330+
var length = UnicodeCalculator.GetWidth(c);
331+
var end = start + length - 1;
332+
//如果posx在当前字符范围内,说明光标在这个字符上
333+
if (PositionX >= start && PositionX <= end)
334+
charLine.Add(new TerminalBlock(c.ToString(), -1, -1));
335+
else
336+
charLine.Add(block.MakeNew(c.ToString()));
337+
count += length;
338+
//如果字符宽度超过1,加入空白填位
339+
length--;
340+
while (length > 0)
341+
{
342+
charLine.Add(block.MakeNew(string.Empty));
343+
length--;
344+
}
345+
}
346+
}
347+
tempLine = charLine;//替换掉当前行为拆字后的行
348+
}
349+
//优化当前这一行数据块
350+
TerminalBlock.OptimizeBlocks(tempLine);
351+
//替换掉当前行
352+
cacheLines[PositionY] = tempLine;
303353
}
304354

305355
return cacheLines;
@@ -314,37 +364,37 @@ public void ChangeWindowSize(int width, int height)
314364
}
315365

316366
//当前所在的行数相比较于终端最底部的行数,0表示在最底部,其余数字表示向上挪动的行数
317-
private int _currentLine = 0;
367+
private int CurrentLine { get; set; } = 0;
318368

319369
private double CurrentLine2ScrollValue =>
320-
(_currentLine == 0 || _cacheLines.Count < _windowHeight)
370+
(CurrentLine == 0 || CacheLines.Count < _windowHeight)
321371
? 100
322-
: 100.0 - (double)_currentLine / (_cacheLines.Count - _windowHeight) * 100.0;
372+
: 100.0 - (double)CurrentLine / (CacheLines.Count - _windowHeight) * 100.0;
323373
//向上移动的行数
324374
public double CurrentLineMoveUp(int delta)
325375
{
326-
var lastCurrentLine = _currentLine;
327-
_currentLine += delta;
328-
if(_currentLine > _cacheLines.Count - _windowHeight)
329-
_currentLine = _cacheLines.Count - _windowHeight;
330-
if(_currentLine < 0)
331-
_currentLine = 0;
376+
var lastCurrentLine = CurrentLine;
377+
CurrentLine += delta;
378+
if(CurrentLine > CacheLines.Count - _windowHeight)
379+
CurrentLine = CacheLines.Count - _windowHeight;
380+
if(CurrentLine < 0)
381+
CurrentLine = 0;
332382

333-
if(lastCurrentLine != _currentLine)
383+
if(lastCurrentLine != CurrentLine)
334384
TerminalChanged();
335385

336386
return CurrentLine2ScrollValue;
337387
}
338388
//滚轮事件
339389
public void ScrollBarChanged(double value)
340390
{
341-
var lastCurrentLine = _currentLine;
342-
if(Math.Abs(value - 100.0) < 0.001 || _cacheLines.Count < _windowHeight)
343-
_currentLine = 0;
391+
var lastCurrentLine = CurrentLine;
392+
if(Math.Abs(value - 100.0) < 0.001 || CacheLines.Count < _windowHeight)
393+
CurrentLine = 0;
344394
else
345-
_currentLine = (int)(_cacheLines.Count - _windowHeight - value * (_cacheLines.Count - _windowHeight) / 100.0);
395+
CurrentLine = (int)(CacheLines.Count - _windowHeight - value * (CacheLines.Count - _windowHeight) / 100.0);
346396

347-
if(lastCurrentLine != _currentLine)
397+
if(lastCurrentLine != CurrentLine)
348398
TerminalChanged();
349399
}
350400
}

0 commit comments

Comments
 (0)