mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-09 03:52:19 +02:00
Collapsible regions (aka outlining aka code folding)
This commit is contained in:
parent
3dd4212ccd
commit
90735e3bf8
21 changed files with 2518 additions and 277 deletions
|
@ -346,6 +346,7 @@ namespace Beefy
|
|||
return list;
|
||||
}*/
|
||||
|
||||
[DisableChecks]
|
||||
public static int64 DecodeInt64(ref uint8* ptr)
|
||||
{
|
||||
int64 value = 0;
|
||||
|
@ -364,6 +365,7 @@ namespace Beefy
|
|||
return value;
|
||||
}
|
||||
|
||||
[DisableChecks]
|
||||
public static int32 DecodeInt(uint8[] buf, ref int idx)
|
||||
{
|
||||
int32 value = 0;
|
||||
|
@ -383,6 +385,7 @@ namespace Beefy
|
|||
return value;
|
||||
}
|
||||
|
||||
[DisableChecks]
|
||||
public static void EncodeInt(uint8[] buf, ref int idx, int value)
|
||||
{
|
||||
int curValue = value;
|
||||
|
|
|
@ -5,11 +5,49 @@ using System.Text;
|
|||
using Beefy.widgets;
|
||||
using Beefy.gfx;
|
||||
using Beefy.utils;
|
||||
using Beefy.geom;
|
||||
|
||||
namespace Beefy.theme.dark
|
||||
{
|
||||
public class DarkEditWidgetContent : EditWidgetContent
|
||||
{
|
||||
public class Embed
|
||||
{
|
||||
public enum Kind
|
||||
{
|
||||
LineStart,
|
||||
HideLine,
|
||||
LineEnd,
|
||||
}
|
||||
|
||||
public Kind mKind;
|
||||
|
||||
public ~this()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void Draw(Graphics g, Rect rect, bool hideLine)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void MouseDown(float x, float y, int btn, int btnCount)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual float GetWidth(bool hideLine)
|
||||
{
|
||||
return GS!(24);
|
||||
}
|
||||
}
|
||||
|
||||
public class Data : EditWidgetContent.Data
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Font mFont;
|
||||
public uint32[] mTextColors = sDefaultColors;
|
||||
public uint32 mHiliteColor = 0xFF2f5c88;
|
||||
|
@ -23,6 +61,7 @@ namespace Beefy.theme.dark
|
|||
public uint32 mViewWhiteSpaceColor;
|
||||
public bool mScrollToStartOnLostFocus;
|
||||
public bool mHiliteCurrentLine;
|
||||
public Dictionary<int, Embed> mEmbeds = new .() ~ DeleteDictionaryAndValues!(_);
|
||||
|
||||
protected static uint32[] sDefaultColors = new uint32[] ( Color.White ) ~ delete _;
|
||||
|
||||
|
@ -39,6 +78,48 @@ namespace Beefy.theme.dark
|
|||
mFont = DarkTheme.sDarkTheme?.mSmallFont;
|
||||
}
|
||||
|
||||
protected override EditWidgetContent.Data CreateEditData()
|
||||
{
|
||||
return new Data();
|
||||
}
|
||||
|
||||
public virtual void CheckLineCoords()
|
||||
{
|
||||
if (mLineCoordTextVersionId == mData.mCurTextVersionId)
|
||||
return;
|
||||
|
||||
mLineCoordTextVersionId = mData.mCurTextVersionId;
|
||||
|
||||
if (mLineCoords == null)
|
||||
mLineCoords = new .();
|
||||
if (mLineCoordJumpTable == null)
|
||||
mLineCoordJumpTable = new .();
|
||||
|
||||
mLineCoords.Clear();
|
||||
mLineCoords.GrowUnitialized(mData.mLineStarts.Count);
|
||||
mLineCoordJumpTable.Clear();
|
||||
|
||||
float fontHeight = mFont.GetLineSpacing();
|
||||
int prevJumpIdx = -1;
|
||||
float jumpCoordSpacing = GetJumpCoordSpacing();
|
||||
|
||||
double curY = 0;
|
||||
for (int line < mData.mLineStarts.Count)
|
||||
{
|
||||
float lineHeight = fontHeight;
|
||||
mLineCoords[line] = (float)curY;
|
||||
|
||||
int jumpIdx = (.)(curY / jumpCoordSpacing);
|
||||
while (prevJumpIdx < jumpIdx)
|
||||
{
|
||||
mLineCoordJumpTable.Add(((int32)line, (int32)line + 1));
|
||||
prevJumpIdx++;
|
||||
}
|
||||
mLineCoordJumpTable[jumpIdx].max = (.)line + 1;
|
||||
curY += lineHeight;
|
||||
}
|
||||
}
|
||||
|
||||
public override void GetTextData()
|
||||
{
|
||||
// Generate text flags if we need to...
|
||||
|
@ -97,6 +178,54 @@ namespace Beefy.theme.dark
|
|||
}
|
||||
|
||||
base.GetTextData();
|
||||
|
||||
CheckLineCoords();
|
||||
}
|
||||
|
||||
public int32 mLineCoordTextVersionId = -1;
|
||||
public List<float> mLineCoords ~ delete _;
|
||||
public List<(int32 min, int32 max)> mLineCoordJumpTable ~ delete _;
|
||||
|
||||
public bool IsLineCollapsed(int line)
|
||||
{
|
||||
if (mLineCoords == null)
|
||||
return false;
|
||||
if ((line >= 0) && (line < mLineCoords.Count - 1))
|
||||
return (mLineCoords[line + 1] - mLineCoords[line]) < 0.1f;
|
||||
return false;
|
||||
}
|
||||
|
||||
public float GetLineHeight(int line, float defaultVal)
|
||||
{
|
||||
if ((line >= 0) && (line < mLineCoords.Count - 1))
|
||||
return mLineCoords[line + 1] - mLineCoords[line];
|
||||
return defaultVal;
|
||||
}
|
||||
|
||||
public float GetLineY(int line, float defaultVal)
|
||||
{
|
||||
if ((line >= 0) && (line < mLineCoords.Count))
|
||||
return mLineCoords[line];
|
||||
return defaultVal;
|
||||
}
|
||||
|
||||
public int FindUncollapsedLine(int line)
|
||||
{
|
||||
var line;
|
||||
while ((line > 0) && (IsLineCollapsed(line)))
|
||||
line--;
|
||||
return line;
|
||||
}
|
||||
|
||||
public bool IsInCollapseGroup(int anchorLine, int checkLine)
|
||||
{
|
||||
if (checkLine < anchorLine)
|
||||
return false;
|
||||
if (checkLine == anchorLine)
|
||||
return true;
|
||||
if (checkLine == anchorLine + 1)
|
||||
return IsLineCollapsed(checkLine);
|
||||
return mLineCoords[anchorLine + 1] == mLineCoords[checkLine + 1];
|
||||
}
|
||||
|
||||
protected override void AdjustCursorsAfterExternalEdit(int index, int ofs)
|
||||
|
@ -322,6 +451,8 @@ namespace Beefy.theme.dark
|
|||
Utils.RoundScale(ref mTabSize, newScale / oldScale);
|
||||
SetFont(mFont, mCharWidth != -1, mAllowVirtualCursor);
|
||||
mContentChanged = true; // Defer calling of RecalcSize
|
||||
GetTextData();
|
||||
LineStartsChanged();
|
||||
}
|
||||
|
||||
public virtual float DrawText(Graphics g, String str, float x, float y, uint16 typeIdAndFlags)
|
||||
|
@ -335,15 +466,52 @@ namespace Beefy.theme.dark
|
|||
return mEditWidget.mHasFocus ? mHiliteColor : mUnfocusedHiliteColor;
|
||||
}
|
||||
|
||||
protected Rect GetEmbedRect(int lineIdx, DarkEditWidgetContent.Embed embed)
|
||||
{
|
||||
GetLinePosition(lineIdx, var lineStart, var lineEnd);
|
||||
|
||||
bool hideLine = false;
|
||||
if ((embed.mKind == .HideLine) &&
|
||||
((!mEditWidget.mHasFocus) || (!IsInCollapseGroup(lineIdx, CursorLine))))
|
||||
hideLine = true;
|
||||
|
||||
int wsEnd = lineEnd;
|
||||
if ((hideLine) || (embed.mKind == .LineStart))
|
||||
{
|
||||
for (int i in lineStart..<lineEnd)
|
||||
{
|
||||
var checkEnd = ref mData.mText[i];
|
||||
if (!checkEnd.mChar.IsWhiteSpace)
|
||||
{
|
||||
wsEnd = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String str = scope .(256);
|
||||
ExtractString(lineStart, wsEnd - lineStart, str);
|
||||
|
||||
float selStartX = GetTabbedWidth(str, 0);
|
||||
|
||||
if ((embed.mKind == .LineEnd) ||
|
||||
((embed.mKind == .HideLine) && (!hideLine)))
|
||||
selStartX += GS!(4);
|
||||
|
||||
Rect rect = .(selStartX, mLineCoords[lineIdx] - GS!(2), embed.GetWidth(hideLine), mFont.GetLineSpacing() + GS!(4));
|
||||
if (rect.mY < 0)
|
||||
rect.mY = 0;
|
||||
return rect;
|
||||
}
|
||||
|
||||
public override void Draw(Graphics g)
|
||||
{
|
||||
base.Draw(g);
|
||||
|
||||
|
||||
#unwarn
|
||||
int lineCount = GetLineCount();
|
||||
float lineSpacing = GetLineHeight(0);
|
||||
|
||||
g.SetFont(mFont);
|
||||
float lineSpacing = mFont.GetLineSpacing();
|
||||
|
||||
float offsetY = mTextInsets.mTop;
|
||||
if (mHeight < lineSpacing)
|
||||
|
@ -377,6 +545,49 @@ namespace Beefy.theme.dark
|
|||
GetLineCharAtCoord(0, -mY + mEditWidget.mScrollContentContainer.mHeight, out lastLine, out lastCharIdx, out lastOverflowX);
|
||||
|
||||
bool drewCursor = false;
|
||||
|
||||
void DrawCursor(float x, float y)
|
||||
{
|
||||
if (mHiliteCurrentLine && selStartIdx == selEndIdx)
|
||||
{
|
||||
float thickness = 2 * (lineSpacing / 18);
|
||||
// This isn't quite the right value, but I'm not sure how to get this
|
||||
// to properly highlight the whole line without getting cut off - this works well for now.
|
||||
float totalLineWidth = mEditWidget.mScrollContentContainer.mWidth - thickness;
|
||||
|
||||
float hiliteX = (int)mEditWidget.mHorzPos.v; // If we don't round to int we get jitter while scrolling.
|
||||
using (g.PushColor(DarkTheme.COLOR_CURRENT_LINE_HILITE))
|
||||
g.OutlineRect(hiliteX, y, totalLineWidth, lineSpacing + thickness, thickness);
|
||||
}
|
||||
|
||||
float brightness = (float)Math.Cos(Math.Max(0.0f, mCursorBlinkTicks - 20) / 9.0f);
|
||||
brightness = Math.Clamp(brightness * 2.0f + 1.6f, 0, 1);
|
||||
if (mEditWidget.mVertPos.IsMoving)
|
||||
brightness = 0; // When we animate a pgup or pgdn, it's weird seeing the cursor scrolling around
|
||||
|
||||
Color cursorColor = mTextColors[0];
|
||||
|
||||
if (mOverTypeMode)
|
||||
{
|
||||
if (mCharWidth <= 2)
|
||||
{
|
||||
using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness * 0.75f))))
|
||||
g.FillRect(x, y, GS!(2), lineSpacing);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness * 0.30f))))
|
||||
g.FillRect(x, y, mCharWidth, lineSpacing);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness))))
|
||||
g.FillRect(x, y, Math.Max(1.0f, GS!(1)), lineSpacing);
|
||||
}
|
||||
drewCursor = true;
|
||||
}
|
||||
|
||||
String sectionText = scope String(256);
|
||||
for (int lineIdx = firstLine; lineIdx <= lastLine; lineIdx++)
|
||||
{
|
||||
|
@ -387,7 +598,26 @@ namespace Beefy.theme.dark
|
|||
|
||||
int lineDrawStart = lineStart;
|
||||
float curX = 0;
|
||||
float curY = lineIdx * lineSpacing;
|
||||
float curY = mLineCoords[lineIdx];
|
||||
float height = mLineCoords[lineIdx + 1] - curY;
|
||||
if (height <= 1.0f)
|
||||
continue;
|
||||
|
||||
DarkEditWidgetContent.Embed embed = null;
|
||||
if (mEmbeds.GetValue(lineIdx) case .Ok(out embed))
|
||||
{
|
||||
if ((embed.mKind == .HideLine) &&
|
||||
((!IsInCollapseGroup(lineIdx, CursorLine)) || (!mEditWidget.mHasFocus)))
|
||||
{
|
||||
var embedRect = GetEmbedRect(lineIdx, embed);
|
||||
embed.Draw(g, embedRect, true);
|
||||
g.SetFont(mFont);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
g.SetFont(mFont);
|
||||
|
||||
while (true)
|
||||
{
|
||||
int lineDrawEnd = lineDrawStart;
|
||||
|
@ -481,46 +711,7 @@ namespace Beefy.theme.dark
|
|||
}
|
||||
|
||||
if (aX != -1)
|
||||
{
|
||||
if (mHiliteCurrentLine && selStartIdx == selEndIdx)
|
||||
{
|
||||
float thickness = 2 * (lineSpacing / 18);
|
||||
// This isn't quite the right value, but I'm not sure how to get this
|
||||
// to properly highlight the whole line without getting cut off - this works well for now.
|
||||
float totalLineWidth = mEditWidget.mScrollContentContainer.mWidth - thickness;
|
||||
|
||||
float x = (int)mEditWidget.mHorzPos.v; // If we don't round to int we get jitter while scrolling.
|
||||
using (g.PushColor(DarkTheme.COLOR_CURRENT_LINE_HILITE))
|
||||
g.OutlineRect(x, curY, totalLineWidth, lineSpacing + thickness, thickness);
|
||||
}
|
||||
|
||||
float brightness = (float)Math.Cos(Math.Max(0.0f, mCursorBlinkTicks - 20) / 9.0f);
|
||||
brightness = Math.Clamp(brightness * 2.0f + 1.6f, 0, 1);
|
||||
if (mEditWidget.mVertPos.IsMoving)
|
||||
brightness = 0; // When we animate a pgup or pgdn, it's weird seeing the cursor scrolling around
|
||||
|
||||
Color cursorColor = mTextColors[0];
|
||||
|
||||
if (mOverTypeMode)
|
||||
{
|
||||
if (mCharWidth <= 2)
|
||||
{
|
||||
using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness * 0.75f))))
|
||||
g.FillRect(aX, curY, GS!(2), lineSpacing);
|
||||
}
|
||||
else
|
||||
{
|
||||
using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness * 0.30f))))
|
||||
g.FillRect(aX, curY, mCharWidth, lineSpacing);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
using (g.PushColor(Color.Mult(cursorColor, Color.Get(brightness))))
|
||||
g.FillRect(aX, curY, Math.Max(1.0f, GS!(1)), lineSpacing);
|
||||
}
|
||||
drewCursor = true;
|
||||
}
|
||||
DrawCursor(aX, curY);
|
||||
}
|
||||
|
||||
lineDrawStart = lineDrawEnd;
|
||||
|
@ -529,6 +720,17 @@ namespace Beefy.theme.dark
|
|||
if (lineDrawStart >= lineEnd)
|
||||
break;
|
||||
}
|
||||
|
||||
if (embed != null)
|
||||
{
|
||||
var embedRect = GetEmbedRect(lineIdx, embed);
|
||||
embed.Draw(g, embedRect, false);
|
||||
g.SetFont(mFont);
|
||||
|
||||
if ((!drewCursor) && (IsLineCollapsed(CursorLineAndColumn.mLine)) &&
|
||||
(GetLineY(CursorLineAndColumn.mLine, -1) == GetLineY(lineIdx + 1, -1)))
|
||||
DrawCursor(embedRect.Right + GS!(2), curY);
|
||||
}
|
||||
}
|
||||
|
||||
g.PopMatrix();
|
||||
|
@ -561,6 +763,8 @@ namespace Beefy.theme.dark
|
|||
|
||||
public override void GetTextCoordAtLineChar(int line, int lineChar, out float x, out float y)
|
||||
{
|
||||
GetTextData();
|
||||
|
||||
String lineText = scope String(256);
|
||||
GetLineText(line, lineText);
|
||||
if (lineChar > lineText.Length)
|
||||
|
@ -571,32 +775,63 @@ namespace Beefy.theme.dark
|
|||
subText.Append(lineText, 0, lineChar);
|
||||
x = GetTabbedWidth(subText, 0, true) + mTextInsets.mLeft;
|
||||
}
|
||||
y = mTextInsets.mTop + line * mFont.GetLineSpacing();
|
||||
y = mTextInsets.mTop + mLineCoords[line];
|
||||
}
|
||||
|
||||
public override void GetTextCoordAtLineAndColumn(int line, int column, out float x, out float y)
|
||||
{
|
||||
GetTextData();
|
||||
Debug.Assert((mCharWidth != -1) || (column == 0));
|
||||
String lineText = scope String(256);
|
||||
GetLineText(line, lineText);
|
||||
x = mTextInsets.mLeft + column * mCharWidth;
|
||||
y = mTextInsets.mTop + line * mFont.GetLineSpacing();
|
||||
y = mTextInsets.mTop + mLineCoords[line];
|
||||
}
|
||||
|
||||
public override bool GetLineCharAtCoord(float x, float y, out int line, out int char8Idx, out float overflowX)
|
||||
protected int GetLineAt(float y)
|
||||
{
|
||||
line = (int) ((y - mTextInsets.mTop) / mFont.GetLineSpacing() + 0.001f);
|
||||
if (y < 0)
|
||||
return 0;
|
||||
|
||||
GetTextData();
|
||||
|
||||
int lineCount = GetLineCount();
|
||||
var checkY = y - mTextInsets.mTop + 0.001f;
|
||||
var jumpEntry = mLineCoordJumpTable[Math.Clamp((int)(y / GetJumpCoordSpacing()), 0, mLineCoordJumpTable.Count - 1)];
|
||||
|
||||
int line = jumpEntry.min - 1;
|
||||
for (int checkLine in jumpEntry.min ..< jumpEntry.max)
|
||||
{
|
||||
if (checkY >= mLineCoords[checkLine])
|
||||
line = checkLine;
|
||||
}
|
||||
|
||||
if (line < 0)
|
||||
line = 0;
|
||||
if (line >= lineCount)
|
||||
line = lineCount - 1;
|
||||
return line;
|
||||
}
|
||||
|
||||
public override bool GetLineCharAtCoord(float x, float y, out int line, out int lineChar, out float overflowX)
|
||||
{
|
||||
line = GetLineAt(y);
|
||||
return GetLineCharAtCoord(line, x, out lineChar, out overflowX);
|
||||
}
|
||||
|
||||
public override bool GetLineAndColumnAtCoord(float x, float y, out int line, out int column)
|
||||
{
|
||||
line = GetLineAt(y);
|
||||
column = Math.Max(0, (int32)((x - mTextInsets.mLeft + 1) / mCharWidth + 0.6f));
|
||||
return mCharWidth != -1;
|
||||
}
|
||||
|
||||
public override bool GetLineCharAtCoord(int line, float x, out int lineChar, out float overflowX)
|
||||
{
|
||||
String lineText = scope String(256);
|
||||
GetLineText(line, lineText);
|
||||
int32 char8Count = GetTabbedCharCountToLength(lineText, x - mTextInsets.mLeft);
|
||||
char8Idx = char8Count;
|
||||
lineChar = char8Count;
|
||||
|
||||
if (char8Count < lineText.Length)
|
||||
{
|
||||
|
@ -617,7 +852,7 @@ namespace Beefy.theme.dark
|
|||
}
|
||||
|
||||
if (x >= subWidth + mTextInsets.mLeft + checkCharWidth)
|
||||
char8Idx = (int32)utf8enumerator.NextIndex;
|
||||
lineChar = (int32)utf8enumerator.NextIndex;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -630,16 +865,6 @@ namespace Beefy.theme.dark
|
|||
return true;
|
||||
}
|
||||
|
||||
public override bool GetLineAndColumnAtCoord(float x, float y, out int line, out int column)
|
||||
{
|
||||
line = (int32)((y - mTextInsets.mTop) / mFont.GetLineSpacing() + 0.001f);
|
||||
if (line >= GetLineCount())
|
||||
line = GetLineCount() - 1;
|
||||
line = Math.Max(0, line);
|
||||
column = Math.Max(0, (int32)((x - mTextInsets.mLeft + 1) / mCharWidth + 0.6f));
|
||||
return mCharWidth != -1;
|
||||
}
|
||||
|
||||
void RecalcSize(int32 startLineNum, int32 endLineNum, bool forceAccurate = false)
|
||||
{
|
||||
scope AutoBeefPerf("DEWC.RecalcSize");
|
||||
|
@ -670,6 +895,53 @@ namespace Beefy.theme.dark
|
|||
base.CursorToLineEnd();
|
||||
}
|
||||
|
||||
public override void GetTextCoordAtCursor(out float x, out float y)
|
||||
{
|
||||
int32 line = CursorLine;
|
||||
if (IsLineCollapsed(line))
|
||||
{
|
||||
line = (.)FindUncollapsedLine(line);
|
||||
GetTextCoordAtLineAndColumn(line, CursorLineAndColumn.mColumn, out x, out y);
|
||||
return;
|
||||
}
|
||||
|
||||
base.GetTextCoordAtCursor(out x, out y);
|
||||
}
|
||||
|
||||
public override void MoveCursorToCoord(float x, float y)
|
||||
{
|
||||
base.MoveCursorToCoord(x, y);
|
||||
|
||||
if ((!mEmbeds.IsEmpty) && (mEmbeds.GetValue(CursorLineAndColumn.mLine) case .Ok(let embed)))
|
||||
{
|
||||
var embedRect = GetEmbedRect(CursorLineAndColumn.mLine, embed);
|
||||
if (x > embedRect.Right)
|
||||
{
|
||||
int endLine = CursorLineAndColumn.mLine;
|
||||
while (true)
|
||||
{
|
||||
if (!IsLineCollapsed(endLine + 1))
|
||||
break;
|
||||
endLine++;
|
||||
}
|
||||
|
||||
if (endLine != CursorLineAndColumn.mLine)
|
||||
{
|
||||
GetLinePosition(endLine, var endLineStart, var endLineEnd);
|
||||
GetLineAndColumnAtLineChar(endLine, endLineEnd - endLineStart, var column);
|
||||
CursorLineAndColumn = .(endLine, column);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void CursorToLineStart(bool allowToScreenStart)
|
||||
{
|
||||
while (IsLineCollapsed(CursorLineAndColumn.mLine))
|
||||
CursorLineAndColumn = .(CursorLineAndColumn.mLine - 1, 1);
|
||||
base.CursorToLineStart(allowToScreenStart);
|
||||
}
|
||||
|
||||
public void RecalcSize(bool forceAccurate = false)
|
||||
{
|
||||
mMaximalScrollAddedHeight = 0;
|
||||
|
@ -707,7 +979,9 @@ namespace Beefy.theme.dark
|
|||
Debug.Assert(!mWidth.IsNaN);
|
||||
}
|
||||
|
||||
mHeight = GetLineCount() * mFont.GetLineSpacing() + mTextInsets.mTop + mTextInsets.mBottom;
|
||||
GetTextData();
|
||||
mHeight = mLineCoords.Back + mTextInsets.mTop + mTextInsets.mBottom;
|
||||
Debug.Assert(mHeight > 0);
|
||||
UpdateMaximalScroll();
|
||||
base.RecalcSize();
|
||||
}
|
||||
|
@ -721,6 +995,21 @@ namespace Beefy.theme.dark
|
|||
{
|
||||
base.ContentChanged();
|
||||
mRecalcSizeLineNum = -1;
|
||||
|
||||
mLineCoordTextVersionId = -1;
|
||||
DeleteAndNullify!(mLineCoords);
|
||||
DeleteAndNullify!(mLineCoordJumpTable);
|
||||
}
|
||||
|
||||
public float GetJumpCoordSpacing()
|
||||
{
|
||||
return mFont.GetLineSpacing() * 4;
|
||||
}
|
||||
|
||||
public override void LineStartsChanged()
|
||||
{
|
||||
base.LineStartsChanged();
|
||||
mLineCoordTextVersionId = -1;
|
||||
}
|
||||
|
||||
public override void TextAppended(String str)
|
||||
|
@ -734,7 +1023,7 @@ namespace Beefy.theme.dark
|
|||
base.TextAppended(str);
|
||||
}
|
||||
|
||||
void UpdateMaximalScroll()
|
||||
protected void UpdateMaximalScroll()
|
||||
{
|
||||
if (mAllowMaximalScroll)
|
||||
{
|
||||
|
@ -744,6 +1033,8 @@ namespace Beefy.theme.dark
|
|||
mMaximalScrollAddedHeight = mEditWidget.mScrollContentContainer.mHeight - mFont.GetLineSpacing();
|
||||
mHeight += mMaximalScrollAddedHeight;
|
||||
|
||||
Debug.Assert(mHeight >= 0);
|
||||
|
||||
if (mHeight != prevHeight)
|
||||
mEditWidget.UpdateScrollbars();
|
||||
}
|
||||
|
@ -757,7 +1048,9 @@ namespace Beefy.theme.dark
|
|||
|
||||
public override float GetLineHeight(int line)
|
||||
{
|
||||
return mFont.GetLineSpacing();
|
||||
if (mLineCoords == null)
|
||||
GetTextData();
|
||||
return mLineCoords[line + 1] - mLineCoords[line];
|
||||
}
|
||||
|
||||
public override float GetPageScrollTextHeight()
|
||||
|
@ -843,6 +1136,27 @@ namespace Beefy.theme.dark
|
|||
|
||||
CheckRecordScrollTop();
|
||||
}
|
||||
|
||||
public override void MouseMove(float x, float y)
|
||||
{
|
||||
base.MouseMove(x, y);
|
||||
|
||||
int line = GetLineAt(y);
|
||||
|
||||
bool isOverEmbed = false;
|
||||
|
||||
if (mEmbeds.GetValue(line) case .Ok(let embed))
|
||||
{
|
||||
Rect embedRect = GetEmbedRect(line, embed);
|
||||
if (embedRect.Contains(x, y))
|
||||
isOverEmbed = true;
|
||||
}
|
||||
|
||||
if (isOverEmbed)
|
||||
BFApp.sApp.SetCursor(Cursor.Pointer);
|
||||
else
|
||||
BFApp.sApp.SetCursor(Cursor.Text);
|
||||
}
|
||||
}
|
||||
|
||||
public class DarkEditWidget : EditWidget
|
||||
|
|
|
@ -181,6 +181,8 @@ namespace Beefy.theme.dark
|
|||
PanelHeader,
|
||||
|
||||
ExtMethod,
|
||||
CollapseClosed,
|
||||
CollapseOpened,
|
||||
|
||||
COUNT
|
||||
};
|
||||
|
|
|
@ -6,8 +6,129 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Beefy.utils
|
||||
{
|
||||
public struct IdSpan
|
||||
public struct IdSpan : IFormattable
|
||||
{
|
||||
public class LookupContext
|
||||
{
|
||||
public enum SortKind
|
||||
{
|
||||
None,
|
||||
Id,
|
||||
Index
|
||||
}
|
||||
|
||||
public struct Entry
|
||||
{
|
||||
public int32 mIdStart;
|
||||
public int32 mIndexStart;
|
||||
public int32 mLength;
|
||||
}
|
||||
|
||||
public List<Entry> mEntries = new .() ~ delete _;
|
||||
public SortKind mSortKind;
|
||||
|
||||
public this(IdSpan idSpan)
|
||||
{
|
||||
int encodeIdx = 0;
|
||||
int charId = 1;
|
||||
int charIdx = 0;
|
||||
while (true)
|
||||
{
|
||||
int cmd = Utils.DecodeInt(idSpan.mData, ref encodeIdx);
|
||||
if (cmd > 0)
|
||||
charId = cmd;
|
||||
else
|
||||
{
|
||||
int spanSize = -cmd;
|
||||
|
||||
Entry entry;
|
||||
entry.mIdStart = (.)charId;
|
||||
entry.mIndexStart = (.)charIdx;
|
||||
entry.mLength = (.)spanSize;
|
||||
mEntries.Add(entry);
|
||||
|
||||
charId += spanSize;
|
||||
charIdx += spanSize;
|
||||
|
||||
if (cmd == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int GetIndexFromId(int32 findCharId)
|
||||
{
|
||||
if (mSortKind != .Id)
|
||||
{
|
||||
mEntries.Sort(scope (lhs, rhs) => lhs.mIdStart <=> rhs.mIdStart);
|
||||
mSortKind = .Id;
|
||||
}
|
||||
|
||||
int lo = 0;
|
||||
int hi = mEntries.Count - 1;
|
||||
|
||||
while (lo <= hi)
|
||||
{
|
||||
int i = (lo + hi) / 2;
|
||||
var midVal = ref mEntries[i];
|
||||
if ((findCharId >= midVal.mIdStart) && (findCharId < midVal.mIdStart + midVal.mLength))
|
||||
return midVal.mIndexStart + (findCharId - midVal.mIdStart);
|
||||
|
||||
if (findCharId > midVal.mIdStart)
|
||||
lo = i + 1;
|
||||
else
|
||||
hi = i - 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int32 GetIdAtIndex(int32 findCharId)
|
||||
{
|
||||
if (mSortKind != .Index)
|
||||
{
|
||||
mEntries.Sort(scope (lhs, rhs) => lhs.mIndexStart <=> rhs.mIndexStart);
|
||||
mSortKind = .Index;
|
||||
}
|
||||
|
||||
int lo = 0;
|
||||
int hi = mEntries.Count - 1;
|
||||
|
||||
while (lo <= hi)
|
||||
{
|
||||
int i = (lo + hi) / 2;
|
||||
var midVal = ref mEntries[i];
|
||||
if ((findCharId >= midVal.mIndexStart) && (findCharId < midVal.mIndexStart + midVal.mLength))
|
||||
return midVal.mIdStart + (findCharId - midVal.mIndexStart);
|
||||
|
||||
if (findCharId > midVal.mIndexStart)
|
||||
lo = i + 1;
|
||||
else
|
||||
hi = i - 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public override void ToString(String strBuffer)
|
||||
{
|
||||
if (mSortKind != .Index)
|
||||
{
|
||||
mEntries.Sort(scope (lhs, rhs) => lhs.mIndexStart <=> rhs.mIndexStart);
|
||||
mSortKind = .Index;
|
||||
}
|
||||
|
||||
strBuffer.AppendF("IdSpan.LookupCtx(");
|
||||
for (var entry in mEntries)
|
||||
{
|
||||
if (@entry.Index > 0)
|
||||
strBuffer.Append(' ');
|
||||
strBuffer.AppendF($"{entry.mIndexStart}:{entry.mLength}={entry.mIdStart}");
|
||||
}
|
||||
strBuffer.AppendF(")");
|
||||
}
|
||||
}
|
||||
|
||||
enum Change
|
||||
{
|
||||
case Insert(int32 index, int32 id, int16 length);
|
||||
|
@ -671,7 +792,6 @@ namespace Beefy.utils
|
|||
|
||||
public IdSpan Duplicate()
|
||||
{
|
||||
Debug.Assert(!HasChangeList);
|
||||
IdSpan idSpan = IdSpan();
|
||||
if (mData != null)
|
||||
{
|
||||
|
@ -679,6 +799,12 @@ namespace Beefy.utils
|
|||
mData.CopyTo(idSpan.mData, 0, 0, mLength);
|
||||
idSpan.mLength = mLength;
|
||||
}
|
||||
if (mChangeList != null)
|
||||
{
|
||||
idSpan.mChangeList = new .();
|
||||
for (var change in mChangeList)
|
||||
idSpan.mChangeList.Add(change);
|
||||
}
|
||||
return idSpan;
|
||||
}
|
||||
|
||||
|
@ -866,6 +992,11 @@ namespace Beefy.utils
|
|||
return idSpan;
|
||||
}
|
||||
|
||||
public override void ToString(String strBuffer)
|
||||
{
|
||||
ToString(strBuffer, "", null);
|
||||
}
|
||||
|
||||
public void Dump() mut
|
||||
{
|
||||
Prepare();
|
||||
|
@ -895,5 +1026,49 @@ namespace Beefy.utils
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ToString(String outString, String format, IFormatProvider formatProvider)
|
||||
{
|
||||
if (HasChangeList)
|
||||
{
|
||||
IdSpan span = Duplicate();
|
||||
span.ToString(outString, format, formatProvider);
|
||||
return;
|
||||
}
|
||||
|
||||
outString.AppendF($"Span(Length:{mLength} ChangeList:{(mChangeList?.Count).GetValueOrDefault()})");
|
||||
|
||||
if (format == "D")
|
||||
{
|
||||
outString.Append("{");
|
||||
int encodeIdx = 0;
|
||||
int charId = 1;
|
||||
int charIdx = 0;
|
||||
while (true)
|
||||
{
|
||||
int32 cmd = Utils.DecodeInt(mData, ref encodeIdx);
|
||||
if (cmd > 0)
|
||||
{
|
||||
charId = cmd;
|
||||
outString.AppendF($" #{charId}");
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 spanSize = -cmd;
|
||||
|
||||
charId += spanSize;
|
||||
charIdx += spanSize;
|
||||
|
||||
if (cmd == 0)
|
||||
{
|
||||
outString.Append("}");
|
||||
return;
|
||||
}
|
||||
|
||||
outString.AppendF($":{spanSize}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -576,11 +576,11 @@ namespace Beefy.widgets
|
|||
float y;
|
||||
GetTextCoordAtLineAndColumn(mVirtualCursorPos.Value.mLine, mVirtualCursorPos.Value.mColumn, out x, out y);
|
||||
|
||||
int line;
|
||||
int lineChar;
|
||||
float overflowX;
|
||||
GetLineCharAtCoord(x, y, out line, out lineChar, out overflowX);
|
||||
mCursorTextPos = (int32)GetTextIdx(line, lineChar);
|
||||
GetLineCharAtCoord(mVirtualCursorPos.Value.mLine, x, out lineChar, out overflowX);
|
||||
|
||||
mCursorTextPos = (int32)GetTextIdx(mVirtualCursorPos.Value.mLine, lineChar);
|
||||
}
|
||||
|
||||
return mCursorTextPos;
|
||||
|
@ -606,14 +606,9 @@ namespace Beefy.widgets
|
|||
int lineChar;
|
||||
GetLineCharAtIdx(mCursorTextPos, out line, out lineChar);
|
||||
|
||||
float x;
|
||||
float y;
|
||||
GetTextCoordAtLineChar(line, lineChar, out x, out y);
|
||||
|
||||
int coordLine;
|
||||
int coordLineColumn;
|
||||
GetLineAndColumnAtCoord(x, y, out coordLine, out coordLineColumn);
|
||||
lineAndColumn.mLine = (int32)coordLine;
|
||||
GetLineAndColumnAtLineChar(line, lineChar, out coordLineColumn);
|
||||
lineAndColumn.mLine = (int32)line;
|
||||
lineAndColumn.mColumn = (int32)coordLineColumn;
|
||||
return lineAndColumn;
|
||||
}
|
||||
|
@ -627,6 +622,20 @@ namespace Beefy.widgets
|
|||
}
|
||||
}
|
||||
|
||||
public int32 CursorLine
|
||||
{
|
||||
get
|
||||
{
|
||||
if (mVirtualCursorPos.HasValue)
|
||||
return mVirtualCursorPos.Value.mLine;
|
||||
|
||||
int line;
|
||||
int lineChar;
|
||||
GetLineCharAtIdx(mCursorTextPos, out line, out lineChar);
|
||||
return (.)line;
|
||||
}
|
||||
}
|
||||
|
||||
public bool WantsUndo
|
||||
{
|
||||
get
|
||||
|
@ -645,6 +654,7 @@ namespace Beefy.widgets
|
|||
mContentChanged = true;
|
||||
}
|
||||
|
||||
|
||||
protected virtual Data CreateEditData()
|
||||
{
|
||||
return new Data();
|
||||
|
@ -661,13 +671,13 @@ namespace Beefy.widgets
|
|||
{
|
||||
if (mVirtualCursorPos.HasValue)
|
||||
{
|
||||
int32 line = mVirtualCursorPos.Value.mLine;
|
||||
float x;
|
||||
float y;
|
||||
GetTextCoordAtLineAndColumn(mVirtualCursorPos.Value.mLine, mVirtualCursorPos.Value.mColumn, out x, out y);
|
||||
GetTextCoordAtLineAndColumn(line, mVirtualCursorPos.Value.mColumn, out x, out y);
|
||||
|
||||
int line;
|
||||
int lineChar;
|
||||
bool success = GetLineCharAtCoord(x, y, out line, out lineChar, out overflowX);
|
||||
bool success = GetLineCharAtCoord(line, x, out lineChar, out overflowX);
|
||||
|
||||
textPos = GetTextIdx(line, lineChar);
|
||||
return success;
|
||||
|
@ -1342,6 +1352,11 @@ namespace Beefy.widgets
|
|||
mEditWidget.ContentChanged();
|
||||
|
||||
TextChanged();
|
||||
}
|
||||
|
||||
public virtual void LineStartsChanged()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void TextAppended(String str)
|
||||
|
@ -1366,6 +1381,7 @@ namespace Beefy.widgets
|
|||
}
|
||||
}
|
||||
mData.mLineStarts.Add(mData.mTextLength);
|
||||
LineStartsChanged();
|
||||
|
||||
mContentChanged = true;
|
||||
|
||||
|
@ -1385,8 +1401,9 @@ namespace Beefy.widgets
|
|||
{
|
||||
// Generate line starts and text flags if we need to
|
||||
|
||||
if (mData.mLineStarts == null)
|
||||
{
|
||||
if (mData.mLineStarts != null)
|
||||
return;
|
||||
|
||||
scope AutoBeefPerf("EWC.GetTextData");
|
||||
|
||||
CharData* char8DataPtr = mData.mText.CArray();
|
||||
|
@ -1447,7 +1464,7 @@ namespace Beefy.widgets
|
|||
}
|
||||
|
||||
mData.mLineStarts[lineIdx + 1] = mData.mTextLength;
|
||||
}
|
||||
LineStartsChanged();
|
||||
}
|
||||
|
||||
public virtual void Backspace()
|
||||
|
@ -1519,7 +1536,7 @@ namespace Beefy.widgets
|
|||
ContentChanged();
|
||||
if (offset != 0)
|
||||
{
|
||||
MoveCursorToIdx(textPos, false, .FromTyping);
|
||||
MoveCursorToIdx(textPos, false, .FromTyping_Deleting);
|
||||
EnsureCursorVisible();
|
||||
}
|
||||
}
|
||||
|
@ -1648,7 +1665,7 @@ namespace Beefy.widgets
|
|||
}
|
||||
else
|
||||
{
|
||||
int32 char8Count = 1;
|
||||
int32 charCount = 1;
|
||||
int checkIdx = textPos + 1;
|
||||
while (true)
|
||||
{
|
||||
|
@ -1660,12 +1677,12 @@ namespace Beefy.widgets
|
|||
if (!checkChar.IsCombiningMark)
|
||||
break;
|
||||
}
|
||||
char8Count++;
|
||||
charCount++;
|
||||
checkIdx++;
|
||||
}
|
||||
|
||||
mData.mUndoManager.Add(new DeleteCharAction(this, 0, char8Count));
|
||||
PhysDeleteChars(0, char8Count);
|
||||
mData.mUndoManager.Add(new DeleteCharAction(this, 0, charCount));
|
||||
PhysDeleteChars(0, charCount);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1934,7 +1951,7 @@ namespace Beefy.widgets
|
|||
return .Other;
|
||||
}
|
||||
|
||||
public void GetTextCoordAtCursor(out float x, out float y)
|
||||
public virtual void GetTextCoordAtCursor(out float x, out float y)
|
||||
{
|
||||
if (mVirtualCursorPos.HasValue)
|
||||
{
|
||||
|
@ -1963,8 +1980,9 @@ namespace Beefy.widgets
|
|||
float y;
|
||||
GetTextCoordAtLineAndColumn(mVirtualCursorPos.Value.mLine, mVirtualCursorPos.Value.mColumn, out x, out y);
|
||||
|
||||
|
||||
float overflowX;
|
||||
return GetLineCharAtCoord(x, y, out line, out lineChar, out overflowX);
|
||||
return GetLineCharAtCoord(line, x, out lineChar, out overflowX);
|
||||
}
|
||||
|
||||
public virtual bool PrepareForCursorMove(int dir = 0)
|
||||
|
@ -2064,6 +2082,7 @@ namespace Beefy.widgets
|
|||
if (var insertTextAction = mData.mUndoManager.GetLastUndoAction() as InsertTextAction)
|
||||
insertTextAction.mVirtualCursorPos = origPosition;
|
||||
CursorLineAndColumn = lineStartPosition;
|
||||
|
||||
CursorToLineStart(false);
|
||||
|
||||
// Adjust to requested column
|
||||
|
@ -2110,15 +2129,15 @@ namespace Beefy.widgets
|
|||
while (true)
|
||||
{
|
||||
if (lineChar > 0)
|
||||
MoveCursorTo(lineIdx, lineChar - 1);
|
||||
MoveCursorTo(lineIdx, lineChar - 1, false, 0, .SelectLeft);
|
||||
else if (lineIdx > 0)
|
||||
{
|
||||
int cursorIdx = mCursorTextPos;
|
||||
String lineText = scope String();
|
||||
GetLineText(lineIdx - 1, lineText);
|
||||
MoveCursorTo(lineIdx - 1, (int32)lineText.Length);
|
||||
MoveCursorTo(lineIdx - 1, (int32)lineText.Length, false, 0, .SelectLeft);
|
||||
if ((!mAllowVirtualCursor) && (cursorIdx == mCursorTextPos))
|
||||
MoveCursorTo(lineIdx - 1, (int32)lineText.Length - 1);
|
||||
MoveCursorTo(lineIdx - 1, (int32)lineText.Length - 1, false, 0, .SelectLeft);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2180,9 +2199,9 @@ namespace Beefy.widgets
|
|||
}
|
||||
|
||||
if (isWithinLine)
|
||||
MoveCursorTo(lineIdx, lineChar + 1, false, 1);
|
||||
MoveCursorTo(lineIdx, lineChar + 1, false, 1, .SelectRight);
|
||||
else if (lineIdx < GetLineCount() - 1)
|
||||
MoveCursorTo(lineIdx + 1, 0);
|
||||
MoveCursorTo(lineIdx + 1, 0, false, 0, .SelectRight);
|
||||
|
||||
if (!mWidgetWindow.IsKeyDown(KeyCode.Control))
|
||||
break;
|
||||
|
@ -2349,7 +2368,7 @@ namespace Beefy.widgets
|
|||
var lineAndColumn = CursorLineAndColumn;
|
||||
CursorLineAndColumn = LineAndColumn(lineAndColumn.mLine, lineAndColumn.mColumn + 1);
|
||||
EnsureCursorVisible(true, false, false);
|
||||
CursorMoved();
|
||||
PhysCursorMoved(.SelectRight);
|
||||
|
||||
ClampCursor();
|
||||
if (lineAndColumn != CursorLineAndColumn)
|
||||
|
@ -2393,22 +2412,40 @@ namespace Beefy.widgets
|
|||
wasMoveKey = true;
|
||||
if ((lineIdx + aDir >= 0) && (lineIdx + aDir < GetLineCount()))
|
||||
{
|
||||
float wantedX = mCursorWantX;
|
||||
float wantY = 0;
|
||||
|
||||
if (mAllowVirtualCursor)
|
||||
{
|
||||
float cursorX;
|
||||
float cursorY;
|
||||
GetTextCoordAtCursor(out cursorX, out cursorY);
|
||||
|
||||
GetLineAndColumnAtCoord(cursorX, cursorY, var virtLine, ?);
|
||||
|
||||
/*GetTextCoordAtLineAndColumn(lineIdx, 0, ?, var lineY);
|
||||
Debug.WriteLine($"Line:{lineIdx} LineY:{lineY} Cursor:{cursorX},{cursorY}");*/
|
||||
|
||||
if (aDir < 0)
|
||||
{
|
||||
wantY = cursorY - 0.1f;
|
||||
}
|
||||
else
|
||||
{
|
||||
wantY = cursorY + GetLineHeight(virtLine) + 0.1f;
|
||||
}
|
||||
//mCursorWantX = cursorX;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
lineIdx += aDir;
|
||||
|
||||
float wantedX = mCursorWantX;
|
||||
|
||||
float aX;
|
||||
float aY;
|
||||
GetTextCoordAtLineChar(lineIdx, 0, out aX, out aY);
|
||||
MoveCursorToCoord(mCursorWantX, aY);
|
||||
wantY = aY;
|
||||
}
|
||||
MoveCursorToCoord(mCursorWantX, wantY);
|
||||
|
||||
ClampCursor();
|
||||
|
||||
|
@ -2645,6 +2682,12 @@ namespace Beefy.widgets
|
|||
return false;
|
||||
}
|
||||
|
||||
public virtual bool GetLineCharAtCoord(int line, float x, out int theChar, out float overflowX)
|
||||
{
|
||||
GetTextCoordAtLineAndColumn(line, 0, ?, var y);
|
||||
return GetLineCharAtCoord(x, y, ?, out theChar, out overflowX);
|
||||
}
|
||||
|
||||
public virtual bool GetLineAndColumnAtCoord(float x, float y, out int line, out int column)
|
||||
{
|
||||
line = -1;
|
||||
|
@ -2818,11 +2861,11 @@ namespace Beefy.widgets
|
|||
ExtractString(lineStart, lineEnd - lineStart, outStr); // Full line
|
||||
}
|
||||
|
||||
public int GetTextIdx(int line, int char8Idx)
|
||||
public int GetTextIdx(int line, int charIdx)
|
||||
{
|
||||
GetTextData();
|
||||
int useLine = Math.Min(line, mData.mLineStarts.Count - 1);
|
||||
return mData.mLineStarts[useLine] + char8Idx;
|
||||
return mData.mLineStarts[useLine] + charIdx;
|
||||
}
|
||||
|
||||
public int GetCharIdIdx(int32 findCharId)
|
||||
|
@ -2839,7 +2882,7 @@ namespace Beefy.widgets
|
|||
|
||||
int curLine = 0;
|
||||
int curColumn = 0;
|
||||
int char8Idx = 0;
|
||||
int charIdx = 0;
|
||||
mData.mTextIdData.Prepare();
|
||||
while (true)
|
||||
{
|
||||
|
@ -2863,7 +2906,7 @@ namespace Beefy.widgets
|
|||
if ((curLine == line) && (curColumn == column))
|
||||
return char8Id;
|
||||
|
||||
char8 c = (char8)mData.mText[char8Idx++].mChar;
|
||||
char8 c = (char8)mData.mText[charIdx++].mChar;
|
||||
if (c == '\n')
|
||||
{
|
||||
if (curLine == line)
|
||||
|
@ -2878,7 +2921,7 @@ namespace Beefy.widgets
|
|||
}
|
||||
}
|
||||
|
||||
public virtual void GetTextCoordAtLineChar(int line, int char8Idx, out float x, out float y)
|
||||
public virtual void GetTextCoordAtLineChar(int line, int charIdx, out float x, out float y)
|
||||
{
|
||||
x = 0;
|
||||
y = 0;
|
||||
|
@ -2892,8 +2935,13 @@ namespace Beefy.widgets
|
|||
|
||||
public enum CursorMoveKind
|
||||
{
|
||||
FromTyping,
|
||||
Unknown
|
||||
case FromTyping;
|
||||
case FromTyping_Deleting;
|
||||
case Unknown;
|
||||
case SelectRight;
|
||||
case SelectLeft;
|
||||
|
||||
public bool IsFromTyping => (this == FromTyping) || (this == FromTyping_Deleting);
|
||||
}
|
||||
|
||||
// We used to have a split between PhysCursorMoved and CursorMoved. CursorMoved has a "ResetWantX" and was non-virtual... uh-
|
||||
|
@ -3379,14 +3427,22 @@ namespace Beefy.widgets
|
|||
Debug.Assert(mSelection.Value.mEndPos <= mData.mTextLength);
|
||||
}
|
||||
|
||||
//public void MoveCursorTo
|
||||
|
||||
public void MoveCursorTo(int line, int char8Idx, bool centerCursor = false, int movingDir = 0, CursorMoveKind cursorMoveKind = .Unknown)
|
||||
public virtual void GetLineAndColumnAtLineChar(int line, int lineChar, out int lineColumn)
|
||||
{
|
||||
int useCharIdx = char8Idx;
|
||||
float x;
|
||||
float y;
|
||||
GetTextCoordAtLineChar(line, lineChar, out x, out y);
|
||||
|
||||
int coordLine;
|
||||
GetLineAndColumnAtCoord(x, y, out coordLine, out lineColumn);
|
||||
}
|
||||
|
||||
public virtual void MoveCursorTo(int line, int charIdx, bool centerCursor = false, int movingDir = 0, CursorMoveKind cursorMoveKind = .Unknown)
|
||||
{
|
||||
int useCharIdx = charIdx;
|
||||
|
||||
mShowCursorAtLineEnd = false;
|
||||
CursorTextPos = GetTextIdx(line, char8Idx);
|
||||
CursorTextPos = GetTextIdx(line, charIdx);
|
||||
|
||||
// Skip over UTF8 parts AND unicode combining marks (ie: when we have a letter with an accent mark following it)
|
||||
while (true)
|
||||
|
@ -3433,13 +3489,13 @@ namespace Beefy.widgets
|
|||
|
||||
public void MoveCursorToIdx(int index, bool centerCursor = false, CursorMoveKind cursorMoveKind = .Unknown)
|
||||
{
|
||||
int aLine;
|
||||
int aCharIdx;
|
||||
GetLineCharAtIdx(index, out aLine, out aCharIdx);
|
||||
MoveCursorTo(aLine, aCharIdx, centerCursor, 0, cursorMoveKind);
|
||||
int line;
|
||||
int charIdx;
|
||||
GetLineCharAtIdx(index, out line, out charIdx);
|
||||
MoveCursorTo(line, charIdx, centerCursor, 0, cursorMoveKind);
|
||||
}
|
||||
|
||||
public void MoveCursorToCoord(float x, float y)
|
||||
public virtual void MoveCursorToCoord(float x, float y)
|
||||
{
|
||||
bool failed = false;
|
||||
|
||||
|
|
|
@ -822,6 +822,20 @@ namespace System.Collections
|
|||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetRef(TKey key, out TKey* matchKey, out TValue* value)
|
||||
{
|
||||
int_cosize i = (int_cosize)FindEntry(key);
|
||||
if (i >= 0)
|
||||
{
|
||||
matchKey = &mEntries[i].mKey;
|
||||
value = &mEntries[i].mValue;
|
||||
return true;
|
||||
}
|
||||
matchKey = null;
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetAlt<TAltKey>(TAltKey key, out TKey matchKey, out TValue value) where TAltKey : IHashable where bool : operator TKey == TAltKey
|
||||
{
|
||||
int_cosize i = (int_cosize)FindEntryAlt(key);
|
||||
|
@ -836,6 +850,20 @@ namespace System.Collections
|
|||
return false;
|
||||
}
|
||||
|
||||
public bool TryGetRefAlt<TAltKey>(TAltKey key, out TKey* matchKey, out TValue* value) where TAltKey : IHashable where bool : operator TKey == TAltKey
|
||||
{
|
||||
int_cosize i = (int_cosize)FindEntryAlt(key);
|
||||
if (i >= 0)
|
||||
{
|
||||
matchKey = &mEntries[i].mKey;
|
||||
value = &mEntries[i].mValue;
|
||||
return true;
|
||||
}
|
||||
matchKey = null;
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
public TValue GetValueOrDefault(TKey key)
|
||||
{
|
||||
int_cosize i = (int_cosize)FindEntry(key);
|
||||
|
@ -1024,7 +1052,7 @@ namespace System.Collections
|
|||
private int_cosize mVersion;
|
||||
#endif
|
||||
private int_cosize mIndex;
|
||||
private TValue mCurrent;
|
||||
private TValue* mCurrent;
|
||||
|
||||
const int_cosize cDictEntry = 1;
|
||||
const int_cosize cKeyValuePair = 2;
|
||||
|
@ -1051,7 +1079,7 @@ namespace System.Collections
|
|||
{
|
||||
if (mDictionary.mEntries[mIndex].mHashCode >= 0)
|
||||
{
|
||||
mCurrent = mDictionary.mEntries[mIndex].mValue;
|
||||
mCurrent = &mDictionary.mEntries[mIndex].mValue;
|
||||
mIndex++;
|
||||
return true;
|
||||
}
|
||||
|
@ -1065,12 +1093,12 @@ namespace System.Collections
|
|||
|
||||
public TValue Current
|
||||
{
|
||||
get { return mCurrent; }
|
||||
get { return *mCurrent; }
|
||||
}
|
||||
|
||||
public ref TValue CurrentRef
|
||||
{
|
||||
get mut { return ref mCurrent; }
|
||||
get mut { return ref *mCurrent; }
|
||||
}
|
||||
|
||||
public ref TKey Key
|
||||
|
@ -1128,7 +1156,7 @@ namespace System.Collections
|
|||
}
|
||||
}
|
||||
|
||||
public struct KeyEnumerator : IEnumerator<TKey>, IResettable
|
||||
public struct KeyEnumerator : IEnumerator<TKey>, IRefEnumerator<TKey*>, IResettable
|
||||
{
|
||||
private Dictionary<TKey, TValue> mDictionary;
|
||||
#if VERSION_DICTIONARY
|
||||
|
@ -1187,6 +1215,11 @@ namespace System.Collections
|
|||
get { return *mCurrent; }
|
||||
}
|
||||
|
||||
public ref TKey CurrentRef
|
||||
{
|
||||
get { return ref *mCurrent; }
|
||||
}
|
||||
|
||||
public ref TValue Value
|
||||
{
|
||||
get
|
||||
|
@ -1224,6 +1257,13 @@ namespace System.Collections
|
|||
return .Err;
|
||||
return Current;
|
||||
}
|
||||
|
||||
public Result<TKey*> GetNextRef() mut
|
||||
{
|
||||
if (!MoveNext())
|
||||
return .Err;
|
||||
return &CurrentRef;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -536,6 +536,15 @@ namespace System.Collections
|
|||
EnsureCapacity(size, true);
|
||||
}
|
||||
|
||||
public void Resize(int size)
|
||||
{
|
||||
EnsureCapacity(size, true);
|
||||
int addSize = size - mSize;
|
||||
if (addSize > 0)
|
||||
Internal.MemSet(Ptr + mSize, 0, addSize * alignof(T));
|
||||
mSize = (.)size;
|
||||
}
|
||||
|
||||
public Enumerator GetEnumerator()
|
||||
{
|
||||
return Enumerator(this);
|
||||
|
@ -716,6 +725,13 @@ namespace System.Collections
|
|||
sorter.[Friend]Sort(0, mSize);
|
||||
}
|
||||
|
||||
public void Sort(Comparison<T> comp, int index, int count)
|
||||
{
|
||||
Debug.Assert((uint)index + (uint)count <= (uint)mSize);
|
||||
var sorter = Sorter<T, void>(mItems, null, mSize, comp);
|
||||
sorter.[Friend]Sort(index, count);
|
||||
}
|
||||
|
||||
public int RemoveAll(Predicate<T> match)
|
||||
{
|
||||
int_cosize freeIndex = 0; // the first free slot in items array
|
||||
|
|
BIN
IDE/dist/images/DarkUI.png
vendored
BIN
IDE/dist/images/DarkUI.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
BIN
IDE/dist/images/DarkUI.psd
vendored
BIN
IDE/dist/images/DarkUI.psd
vendored
Binary file not shown.
BIN
IDE/dist/images/DarkUI_2.png
vendored
BIN
IDE/dist/images/DarkUI_2.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
BIN
IDE/dist/images/DarkUI_4.png
vendored
BIN
IDE/dist/images/DarkUI_4.png
vendored
Binary file not shown.
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 89 KiB |
|
@ -214,6 +214,12 @@ namespace IDE
|
|||
Add("Close Document", new () => { gApp.[Friend]TryCloseCurrentDocument(); });
|
||||
Add("Close Panel", new () => { gApp.[Friend]TryCloseCurrentPanel(); });
|
||||
Add("Close Workspace", new => gApp.[Friend]Cmd_CloseWorkspaceAndSetupNew);
|
||||
Add("Collapse All", new => gApp.[Friend]CollapseAll);
|
||||
Add("Collapse To Definition", new => gApp.[Friend]CollapseToDefinition);
|
||||
Add("Collapse Redo", new => gApp.[Friend]CollapseRedo);
|
||||
Add("Collapse Toggle", new => gApp.[Friend]CollapseToggle);
|
||||
Add("Collapse Toggle All", new => gApp.[Friend]CollapseToggleAll);
|
||||
Add("Collapse Undo", new => gApp.[Friend]CollapseUndo);
|
||||
Add("Comment Block", new => gApp.[Friend]CommentBlock, .Editor);
|
||||
Add("Comment Lines", new => gApp.[Friend]CommentLines, .Editor);
|
||||
Add("Comment Toggle", new => gApp.[Friend]CommentToggle, .Editor);
|
||||
|
|
|
@ -60,6 +60,9 @@ namespace IDE.Compiler
|
|||
[CallingConvention(.Stdcall), CLink]
|
||||
static extern bool BfCompiler_ClassifySource(void* bfCompiler, void* bfPassInstance, void* bfParser, void* bfResolvePassData, void* char8Data);
|
||||
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
static extern char8* BfCompiler_GetCollapseRegions(void* bfCompiler, void* bfParser);
|
||||
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
static extern char8* BfCompiler_GetAutocompleteInfo(void* bfCompiler);
|
||||
|
||||
|
@ -266,6 +269,11 @@ namespace IDE.Compiler
|
|||
return BfCompiler_ClassifySource(mNativeBfCompiler, bfPassInstance.mNativeBfPassInstance, (parser != null) ? parser.mNativeBfParser : null, nativeResolvePassData, char8DataPtr);
|
||||
}
|
||||
|
||||
public void GetCollapseRegions(BfParser parser, String outData)
|
||||
{
|
||||
outData.Append(BfCompiler_GetCollapseRegions(mNativeBfCompiler, (parser != null) ? parser.mNativeBfParser : null));
|
||||
}
|
||||
|
||||
public bool VerifyTypeName(String typeName, int cursorPos)
|
||||
{
|
||||
return BfCompiler_VerifyTypeName(mNativeBfCompiler, typeName, (.)cursorPos);
|
||||
|
|
|
@ -2439,6 +2439,42 @@ namespace IDE
|
|||
//FinishShowingNewWorkspace();
|
||||
}
|
||||
|
||||
[IDECommand]
|
||||
void CollapseAll()
|
||||
{
|
||||
GetActiveSourceEditWidgetContent()?.CollapseAll();
|
||||
}
|
||||
|
||||
[IDECommand]
|
||||
void CollapseToDefinition()
|
||||
{
|
||||
GetActiveSourceEditWidgetContent()?.CollapseToDefinition();
|
||||
}
|
||||
|
||||
[IDECommand]
|
||||
void CollapseRedo()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[IDECommand]
|
||||
void CollapseToggle()
|
||||
{
|
||||
GetActiveSourceEditWidgetContent()?.CollapseToggle();
|
||||
}
|
||||
|
||||
[IDECommand]
|
||||
void CollapseToggleAll()
|
||||
{
|
||||
GetActiveSourceEditWidgetContent()?.CollapseToggleAll();
|
||||
}
|
||||
|
||||
[IDECommand]
|
||||
void CollapseUndo()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[IDECommand]
|
||||
void DeleteAllRight()
|
||||
{
|
||||
|
@ -2485,6 +2521,73 @@ namespace IDE
|
|||
sewc.ToggleComment(false);
|
||||
}
|
||||
|
||||
[IDECommand]
|
||||
void ComplexIdSpan()
|
||||
{
|
||||
if (var sourceViewPanel = GetLastActiveDocumentPanel() as SourceViewPanel)
|
||||
{
|
||||
var sewc = sourceViewPanel.mEditWidget.mEditWidgetContent as SourceEditWidgetContent;
|
||||
uint8[] newData = new uint8[sewc.mData.mTextLength*4];
|
||||
|
||||
var idData = ref sewc.mData.mTextIdData;
|
||||
/*idData.Prepare();
|
||||
|
||||
int encodeIdx = 0;
|
||||
int decodeIdx = 0;
|
||||
int charId = 1;
|
||||
int charIdx = 0;
|
||||
while (true)
|
||||
{
|
||||
int32 cmd = Utils.DecodeInt(idData.mData, ref decodeIdx);
|
||||
if (cmd > 0)
|
||||
{
|
||||
charId = cmd;
|
||||
Utils.EncodeInt(newData, ref encodeIdx, charId);
|
||||
}
|
||||
else
|
||||
{
|
||||
int32 spanSize = -cmd;
|
||||
|
||||
charId += spanSize;
|
||||
charIdx += spanSize;
|
||||
|
||||
if (cmd == 0)
|
||||
{
|
||||
Utils.EncodeInt(newData, ref encodeIdx, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
while (spanSize > 65)
|
||||
{
|
||||
Utils.EncodeInt(newData, ref encodeIdx, -64);
|
||||
spanSize -= 64;
|
||||
}
|
||||
Utils.EncodeInt(newData, ref encodeIdx, -spanSize);
|
||||
}
|
||||
}*/
|
||||
|
||||
int encodeIdx = 0;
|
||||
int sizeLeft = sewc.mData.mTextLength;
|
||||
while (sizeLeft > 0)
|
||||
{
|
||||
int writeLength = Math.Min(sizeLeft, 64);
|
||||
Utils.EncodeInt(newData, ref encodeIdx, sewc.mData.mNextCharId);
|
||||
Utils.EncodeInt(newData, ref encodeIdx, -writeLength);
|
||||
sewc.mData.mNextCharId += (.)writeLength;
|
||||
sewc.mData.mNextCharId++;
|
||||
sizeLeft -= writeLength;
|
||||
}
|
||||
Utils.EncodeInt(newData, ref encodeIdx, 0);
|
||||
|
||||
IdSpan newSpan = .(newData, (.)encodeIdx);
|
||||
|
||||
//Runtime.Assert(newSpan.Equals(idData));
|
||||
|
||||
idData.Dispose();
|
||||
idData = newSpan;
|
||||
}
|
||||
}
|
||||
|
||||
public Result<void, StructuredData.Error> StructuredLoad(StructuredData data, StringView filePath)
|
||||
{
|
||||
if (mWorkspace.IsSingleFileWorkspace)
|
||||
|
|
|
@ -2583,6 +2583,30 @@ namespace IDE
|
|||
#endif
|
||||
}
|
||||
|
||||
[IDECommand]
|
||||
public void UndoFill()
|
||||
{
|
||||
var documentPanel = gApp.GetLastActiveDocumentPanel();
|
||||
if (var sourceViewPanel = documentPanel as SourceViewPanel)
|
||||
{
|
||||
int count = 0;
|
||||
for (int i < 400)
|
||||
{
|
||||
for (char8 c = 'A'; c <= 'Z'; c++)
|
||||
{
|
||||
String str = scope .(32);
|
||||
if (count++ % 131 == 0)
|
||||
str.Append("\n//");
|
||||
str.Append(c);
|
||||
|
||||
sourceViewPanel.mEditWidget.mEditWidgetContent.mData.mUndoManager.[Friend]mSkipNextMerge = true;
|
||||
sourceViewPanel.mEditWidget.mEditWidgetContent.InsertAtCursor(str);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[IDECommand]
|
||||
public void SetVal(String valName, String value)
|
||||
{
|
||||
|
|
|
@ -774,6 +774,12 @@ namespace IDE
|
|||
Add("Build Workspace", "F7");
|
||||
Add("Cancel Build", "Ctrl+Break");
|
||||
Add("Close Document", "Ctrl+W");
|
||||
Add("Collapse All", "Ctrl+M, Ctrl+A");
|
||||
Add("Collapse To Definition", "Ctrl+M, Ctrl+O");
|
||||
Add("Collapse Redo", "Ctrl+M, Ctrl+Y");
|
||||
Add("Collapse Toggle", "Ctrl+M, Ctrl+M");
|
||||
Add("Collapse Toggle All", "Ctrl+M, Ctrl+L");
|
||||
Add("Collapse Undo", "Ctrl+M, Ctrl+Z");
|
||||
Add("Compile File", "Ctrl+F7");
|
||||
Add("Comment Block", "Ctrl+K, Ctrl+C");
|
||||
Add("Comment Lines", "Ctrl+K, Ctrl+/");
|
||||
|
|
|
@ -85,7 +85,7 @@ namespace IDE.ui
|
|||
public bool mIsReplace;
|
||||
public int32 mLastTextVersion;
|
||||
bool mFoundMatches;
|
||||
bool mIsShowingMatches = false;
|
||||
public bool mIsShowingMatches = false;
|
||||
static String sLastSearchString = new String() ~ delete _;
|
||||
|
||||
public bool mOwnsSelection;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -165,7 +165,7 @@ namespace IDE.ui
|
|||
|
||||
public ~this()
|
||||
{
|
||||
NOP!();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -300,6 +300,35 @@ namespace IDE.ui
|
|||
public int32 mDebuggerContinueIdx;
|
||||
}
|
||||
|
||||
class CollapseRegionView
|
||||
{
|
||||
public const uint32 cStartFlag = 0x8000'0000;
|
||||
public const uint32 cMidFlag = 0x4000'0000;
|
||||
public const uint32 cEndFlag = 0x2000'0000;
|
||||
public const uint32 cIdMask = 0x0FFF'FFFF;
|
||||
|
||||
public List<uint32> mCollapseIndices = new .() ~ delete _;
|
||||
public int32 mLineStart;
|
||||
public int32 mCollapseRevision;
|
||||
public int32 mTextVersionId;
|
||||
|
||||
public uint32 GetCollapseValue(int param)
|
||||
{
|
||||
if (param < mLineStart)
|
||||
return 0;
|
||||
if (param - mLineStart < mCollapseIndices.Count)
|
||||
return mCollapseIndices[param - mLineStart];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
class QueuedCollapseData
|
||||
{
|
||||
public String mData = new .() ~ delete _;
|
||||
public int32 mTextVersion;
|
||||
public IdSpan mCharIdSpan ~ _.Dispose();
|
||||
}
|
||||
|
||||
public class SourceViewPanel : TextPanel
|
||||
{
|
||||
enum SourceDisplayId
|
||||
|
@ -349,9 +378,12 @@ namespace IDE.ui
|
|||
int32 mTicksSinceTextChanged;
|
||||
int32 mErrorLookupTextIdx = -1;
|
||||
LinePointerDrawData mLinePointerDrawData;
|
||||
Point? mMousePos;
|
||||
#if IDE_C_SUPPORT
|
||||
public String mClangHoverErrorData ~ delete mClangHoverErrorData;
|
||||
#endif
|
||||
CollapseRegionView mCollapseRegionView = new .() ~ delete _;
|
||||
QueuedCollapseData mQueuedCollapseData ~ delete _;
|
||||
|
||||
public EditWidgetContent.CharData[] mProcessSpellCheckCharData ~ delete _;
|
||||
public IdSpan mProcessSpellCheckCharIdSpan ~ _.Dispose();
|
||||
|
@ -1785,18 +1817,18 @@ namespace IDE.ui
|
|||
parser = bfSystem.CreateEmptyParser((BfProject)null);
|
||||
}
|
||||
|
||||
EditWidgetContent.CharData[] char8Data = null;
|
||||
int char8Len = 0;
|
||||
EditWidgetContent.CharData[] charData = null;
|
||||
int charLen = 0;
|
||||
if ((resolveParams != null) && (resolveParams.mCharData != null))
|
||||
{
|
||||
char8Data = resolveParams.mCharData;
|
||||
char8Len = resolveParams.mCharData.Count;
|
||||
charData = resolveParams.mCharData;
|
||||
charLen = resolveParams.mCharData.Count;
|
||||
}
|
||||
if (char8Data == null)
|
||||
if (charData == null)
|
||||
{
|
||||
Debug.Assert(!isBackground);
|
||||
char8Data = mEditWidget.Content.mData.mText;
|
||||
char8Len = mEditWidget.Content.mData.mTextLength;
|
||||
charData = mEditWidget.Content.mData.mText;
|
||||
charLen = mEditWidget.Content.mData.mTextLength;
|
||||
}
|
||||
|
||||
/*var char8Data = (!isBackground) ? mEditWidget.Content.mData.mText : mProcessResolveCharData;
|
||||
|
@ -1818,12 +1850,12 @@ namespace IDE.ui
|
|||
|
||||
if (!isBackground)
|
||||
bfSystem.PerfZoneStart("DoClassify.CreateChars");
|
||||
char8[] chars = new char8[char8Len];
|
||||
char8[] chars = new char8[charLen];
|
||||
defer delete chars;
|
||||
for (int32 i = 0; i < char8Len; i++)
|
||||
for (int32 i = 0; i < charLen; i++)
|
||||
{
|
||||
char8Data[i].mDisplayPassId = (int32)SourceDisplayId.Cleared;
|
||||
chars[i] = (char8)char8Data[i].mChar;
|
||||
charData[i].mDisplayPassId = (int32)SourceDisplayId.Cleared;
|
||||
chars[i] = (char8)charData[i].mChar;
|
||||
}
|
||||
|
||||
String text = scope String();
|
||||
|
@ -1933,7 +1965,7 @@ namespace IDE.ui
|
|||
|
||||
if ((!isFastClassify) && (bfCompiler != null))
|
||||
{
|
||||
if (!bfCompiler.ClassifySource(passInstance, parser, resolvePassData, char8Data))
|
||||
if (!bfCompiler.ClassifySource(passInstance, parser, resolvePassData, charData))
|
||||
{
|
||||
//DeleteAndNullify!(mProcessResolveCharData);
|
||||
//mProcessResolveCharIdSpan.Dispose();
|
||||
|
@ -1945,10 +1977,23 @@ namespace IDE.ui
|
|||
}
|
||||
bfCompiler.QueueDeferredResolveAll();
|
||||
}
|
||||
|
||||
if ((resolveType == ResolveType.Classify) || (resolveType == ResolveType.ClassifyFullRefresh))
|
||||
{
|
||||
var collapseData = bfCompiler.GetCollapseRegions(parser, .. scope .());
|
||||
using (mMonitor.Enter())
|
||||
{
|
||||
DeleteAndNullify!(mQueuedCollapseData);
|
||||
mQueuedCollapseData = new .();
|
||||
mQueuedCollapseData.mData.Set(collapseData);
|
||||
mQueuedCollapseData.mTextVersion = resolveParams.mTextVersion;
|
||||
mQueuedCollapseData.mCharIdSpan = resolveParams.mCharIdSpan.Duplicate();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
parser.ClassifySource(char8Data, !mIsBeefSource);
|
||||
parser.ClassifySource(charData, !mIsBeefSource);
|
||||
}
|
||||
|
||||
if (!isBackground)
|
||||
|
@ -3637,6 +3682,18 @@ namespace IDE.ui
|
|||
|
||||
AddWidget(mSplitTopPanel);
|
||||
|
||||
var ewc = (SourceEditWidgetContent)mEditWidget.mEditWidgetContent;
|
||||
var topEWC = (SourceEditWidgetContent)mSplitTopPanel.mEditWidget.mEditWidgetContent;
|
||||
|
||||
for (var entry in ewc.mOrderedCollapseEntries)
|
||||
{
|
||||
if (!entry.mIsOpen)
|
||||
{
|
||||
topEWC.SetCollapseOpen(@entry.Index, false, true);
|
||||
}
|
||||
}
|
||||
topEWC.RehupLineCoords();
|
||||
|
||||
ResizeComponents();
|
||||
|
||||
// Match scroll positions
|
||||
|
@ -4106,7 +4163,8 @@ namespace IDE.ui
|
|||
if (mLoadFailed)
|
||||
return;
|
||||
|
||||
DarkEditWidgetContent darkEditWidgetContent = (DarkEditWidgetContent)mEditWidget.Content;
|
||||
var ewc = (SourceEditWidgetContent)mEditWidget.Content;
|
||||
ewc.GetTextData();
|
||||
|
||||
g.SetFont(IDEApp.sApp.mTinyCodeFont);
|
||||
|
||||
|
@ -4115,13 +4173,93 @@ namespace IDE.ui
|
|||
using (g.PushTranslate(0, mEditWidget.mY + mEditWidget.Content.Y + GS!(2)))
|
||||
{
|
||||
float editX = GetEditX();
|
||||
float lineSpacing = darkEditWidgetContent.mFont.GetLineSpacing();
|
||||
int cursorLineNumber = mEditWidget.mEditWidgetContent.CursorLineAndColumn.mLine;
|
||||
using (g.PushColor(gApp.mSettings.mUISettings.mColors.mCurrentLineNumberHilite))
|
||||
g.FillRect(0, GS!(2) + cursorLineNumber * lineSpacing, editX - GS!(2), lineSpacing);
|
||||
float leftAdjust = GS!(12);
|
||||
|
||||
float lineSpacing = ewc.mFont.GetLineSpacing();
|
||||
int cursorLineNumber = mEditWidget.mEditWidgetContent.CursorLineAndColumn.mLine;
|
||||
bool hiliteCurrentLine = true;
|
||||
|
||||
var jumpEntry = ewc.mLineCoordJumpTable[Math.Clamp((int)(-mEditWidget.Content.Y / ewc.GetJumpCoordSpacing()), 0, ewc.mLineCoordJumpTable.Count - 1)];
|
||||
int lineStart = jumpEntry.min;
|
||||
jumpEntry = ewc.mLineCoordJumpTable[Math.Clamp((int)((-mEditWidget.Content.Y + mHeight) / ewc.GetJumpCoordSpacing()), 0, ewc.mLineCoordJumpTable.Count - 1)];
|
||||
int lineEnd = jumpEntry.max - 1;
|
||||
|
||||
int drawLineCount = lineEnd - lineStart + 1;
|
||||
|
||||
ewc.RefreshCollapseRegions();
|
||||
if ((mCollapseRegionView.mLineStart != lineStart) || (mCollapseRegionView.mCollapseIndices.Count != drawLineCount) ||
|
||||
(mCollapseRegionView.mCollapseRevision != ewc.mCollapseParseRevision) || (mCollapseRegionView.mTextVersionId != ewc.mCollapseTextVersionId))
|
||||
{
|
||||
mCollapseRegionView.mLineStart = (.)lineStart;
|
||||
mCollapseRegionView.mCollapseIndices.Clear();
|
||||
Internal.MemSet(mCollapseRegionView.mCollapseIndices.GrowUnitialized(drawLineCount), 0, drawLineCount * sizeof(int32));
|
||||
mCollapseRegionView.mCollapseRevision = ewc.mCollapseParseRevision;
|
||||
mCollapseRegionView.mTextVersionId = ewc.mCollapseTextVersionId;
|
||||
|
||||
List<int32> collapseStack = scope .(16);
|
||||
int32 curIdx = 0;
|
||||
for (int line in lineStart...lineEnd)
|
||||
{
|
||||
uint32 indexVal = 0;
|
||||
|
||||
while (curIdx < ewc.mOrderedCollapseEntries.Count)
|
||||
{
|
||||
var entry = ewc.mOrderedCollapseEntries[curIdx];
|
||||
if (entry.mAnchorLine > line)
|
||||
break;
|
||||
if (!entry.mDeleted)
|
||||
{
|
||||
indexVal = (uint32)curIdx | CollapseRegionView.cStartFlag;
|
||||
collapseStack.Add(curIdx);
|
||||
}
|
||||
curIdx++;
|
||||
}
|
||||
|
||||
while (!collapseStack.IsEmpty)
|
||||
{
|
||||
var entry = ewc.mOrderedCollapseEntries[collapseStack.Back];
|
||||
if (line < entry.mEndLine)
|
||||
break;
|
||||
if (indexVal == 0)
|
||||
indexVal = (uint32)collapseStack.Back | CollapseRegionView.cEndFlag;
|
||||
collapseStack.PopBack();
|
||||
}
|
||||
|
||||
if ((indexVal == 0) && (!collapseStack.IsEmpty))
|
||||
indexVal = (uint32)collapseStack.Back | CollapseRegionView.cMidFlag;
|
||||
mCollapseRegionView.mCollapseIndices[line - lineStart] = indexVal;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ((mMousePos != null) && (mMousePos.Value.x >= mEditWidget.mX - GS!(13)) && (mMousePos.Value.x < mEditWidget.mX - GS!(0)))
|
||||
{
|
||||
int lineClick = GetLineAt(0, mMousePos.Value.y);
|
||||
uint32 collapseVal = mCollapseRegionView.GetCollapseValue(lineClick);
|
||||
if (collapseVal != 0)
|
||||
{
|
||||
var entry = ewc.mOrderedCollapseEntries[collapseVal & CollapseRegionView.cIdMask];
|
||||
float startY = ewc.mLineCoords[entry.mAnchorLine];
|
||||
float endY = ewc.mLineCoords[entry.mEndLine + 1];
|
||||
|
||||
using (g.PushColor(gApp.mSettings.mUISettings.mColors.mCurrentLineNumberHilite))
|
||||
g.FillRect(0, GS!(2) + startY, editX - GS!(10), endY - startY);
|
||||
|
||||
hiliteCurrentLine = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (hiliteCurrentLine)
|
||||
{
|
||||
using (g.PushColor(gApp.mSettings.mUISettings.mColors.mCurrentLineNumberHilite))
|
||||
{
|
||||
int hiliteLineNum = cursorLineNumber;
|
||||
while (ewc.IsLineCollapsed(hiliteLineNum))
|
||||
hiliteLineNum--;
|
||||
g.FillRect(0, GS!(2) + ewc.mLineCoords[hiliteLineNum], editX - GS!(10), lineSpacing);
|
||||
}
|
||||
}
|
||||
|
||||
int lineStart = (int)((-mEditWidget.Content.Y) / lineSpacing) - 1;
|
||||
int lineEnd = Math.Min(darkEditWidgetContent.GetLineCount(), lineStart + (int)(mHeight / lineSpacing) + 3);
|
||||
if (lineEnd <= lineStart)
|
||||
{
|
||||
return;
|
||||
|
@ -4144,8 +4282,8 @@ namespace IDE.ui
|
|||
int breakpointCount = (.)(curLineFlags & .BreakpointCountMask);
|
||||
curLineFlags++;
|
||||
|
||||
float iconX = Math.Max(GS!(-2), mEditWidget.mX - GS!(24)) + breakpointCount*-GS!(2);
|
||||
float iconY = 0 + drawLineNum * lineSpacing + (lineSpacing - DarkTheme.sUnitSize + GS!(5)) / 2;
|
||||
float iconX = Math.Max(GS!(-2), mEditWidget.mX - GS!(24) - leftAdjust) + breakpointCount*-GS!(2);
|
||||
float iconY = 0 + ewc.mLineCoords[drawLineNum] + (lineSpacing - DarkTheme.sUnitSize + GS!(5)) / 2;
|
||||
|
||||
// Just leave last digit visible
|
||||
/*using (g.PushColor(0xFF595959))
|
||||
|
@ -4166,7 +4304,7 @@ namespace IDE.ui
|
|||
if ((drawLineNum < lineStart) || (drawLineNum >= lineEnd))
|
||||
continue;
|
||||
//hadLineIcon[drawLineNum - lineStart] = true;
|
||||
g.Draw(DarkTheme.sDarkTheme.GetImage(.IconBookmark), Math.Max(GS!(-5), mEditWidget.mX - GS!(30)),
|
||||
g.Draw(DarkTheme.sDarkTheme.GetImage(.IconBookmark), Math.Max(GS!(-5), mEditWidget.mX - GS!(30) - leftAdjust),
|
||||
0 + bookmark.mLineNum * lineSpacing);
|
||||
|
||||
var curLineFlags = ref lineFlags[drawLineNum - lineStart];
|
||||
|
@ -4199,6 +4337,10 @@ namespace IDE.ui
|
|||
{
|
||||
for (int lineIdx = lineStart; lineIdx < lineEnd; lineIdx++)
|
||||
{
|
||||
float drawHeight = ewc.mLineCoords[lineIdx + 1] - ewc.mLineCoords[lineIdx];
|
||||
if (drawHeight < lineSpacing * 0.25f)
|
||||
continue;
|
||||
|
||||
lineStr.Clear();
|
||||
|
||||
int maxLineChars = Int32.MaxValue;
|
||||
|
@ -4216,7 +4358,43 @@ namespace IDE.ui
|
|||
case 2: lineStr.AppendF("{0}", (lineIdx + 1) % 100);
|
||||
default: lineStr.AppendF("{0}", lineIdx + 1);
|
||||
}
|
||||
g.DrawString(lineStr, 0, GS!(2) + lineIdx * lineSpacing, FontAlign.Right, editX - GS!(2));
|
||||
g.DrawString(lineStr, 0, GS!(2) + ewc.mLineCoords[lineIdx], FontAlign.Right, editX - GS!(14));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int lineIdx = lineStart; lineIdx < lineEnd; lineIdx++)
|
||||
{
|
||||
int collapseLookup = lineIdx - mCollapseRegionView.mLineStart;
|
||||
if ((collapseLookup >= 0) && (collapseLookup < mCollapseRegionView.mCollapseIndices.Count))
|
||||
{
|
||||
float drawHeight = ewc.mLineCoords[lineIdx + 1] - ewc.mLineCoords[lineIdx];
|
||||
if (drawHeight < lineSpacing * 0.25f)
|
||||
continue;
|
||||
|
||||
float boxAdjustTop = Math.Floor((lineSpacing - DarkTheme.sUnitSize)/2);
|
||||
float boxAdjustBot = Math.Ceiling((lineSpacing - DarkTheme.sUnitSize)/2);
|
||||
|
||||
uint32 collapseIdx = mCollapseRegionView.mCollapseIndices[lineIdx - mCollapseRegionView.mLineStart];
|
||||
if ((collapseIdx & CollapseRegionView.cStartFlag) != 0)
|
||||
{
|
||||
var entry = ewc.mOrderedCollapseEntries[collapseIdx & CollapseRegionView.cIdMask];
|
||||
g.Draw(DarkTheme.sDarkTheme.GetImage(entry.mIsOpen ? .CollapseOpened : .CollapseClosed), editX - GS!(16), ewc.mLineCoords[lineIdx] + boxAdjustTop + GS!(2));
|
||||
}
|
||||
else if ((collapseIdx & CollapseRegionView.cEndFlag) != 0)
|
||||
{
|
||||
using (g.PushColor(0xFFA5A5A5))
|
||||
{
|
||||
g.FillRect(editX - (int)GS!(7.5f), ewc.mLineCoords[lineIdx] - (int)GS!(0.5f), (int)GS!(1.5f), lineSpacing);
|
||||
g.FillRect(editX - (int)GS!(7.5f), ewc.mLineCoords[lineIdx] + lineSpacing - (int)GS!(1.5f), GS!(5), (int)GS!(1.5f));
|
||||
}
|
||||
}
|
||||
else if (collapseIdx != 0)
|
||||
{
|
||||
using (g.PushColor(0xFFA5A5A5))
|
||||
{
|
||||
g.FillRect(editX - (int)GS!(7.5f), ewc.mLineCoords[lineIdx] - boxAdjustBot - GS!(5), (int)GS!(1.5f), lineSpacing + boxAdjustBot + boxAdjustTop + (int)GS!(12f));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5255,6 +5433,11 @@ namespace IDE.ui
|
|||
Point mousePos;
|
||||
bool mouseoverFired = DarkTooltipManager.CheckMouseover(editWidgetContent, 10, out mousePos);
|
||||
|
||||
if (mouseoverFired)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#unwarn
|
||||
CompilerBase compiler = ResolveCompiler;
|
||||
|
||||
|
@ -5571,6 +5754,8 @@ namespace IDE.ui
|
|||
if (checkIdx >= mDeferredResolveResults.Count)
|
||||
break;
|
||||
resolveResult = mDeferredResolveResults[checkIdx];
|
||||
}
|
||||
|
||||
if ((autocompleteOnly) && (resolveResult.mResolveType != .Autocomplete))
|
||||
{
|
||||
checkIdx++;
|
||||
|
@ -5588,8 +5773,9 @@ namespace IDE.ui
|
|||
checkIdx++;
|
||||
continue;
|
||||
}
|
||||
|
||||
using (mMonitor.Enter())
|
||||
mDeferredResolveResults.RemoveAt(checkIdx);
|
||||
}
|
||||
|
||||
//Debug.WriteLine($"HandleResolveResult {resolveResult}");
|
||||
|
||||
|
@ -6127,8 +6313,6 @@ namespace IDE.ui
|
|||
DeleteAndNullify!(mQueuedAutoComplete);
|
||||
}
|
||||
|
||||
ProcessDeferredResolveResults(0);
|
||||
|
||||
if (mLockFlashPct != 0)
|
||||
{
|
||||
mLockFlashPct += 0.02f;
|
||||
|
@ -6139,6 +6323,20 @@ namespace IDE.ui
|
|||
|
||||
if ((mEmitRevision >= 0) && ((mUpdateCnt % 30) == 0))
|
||||
CheckEmitRevision();
|
||||
|
||||
var ewc = (SourceEditWidgetContent)mEditWidget.Content;
|
||||
using (mMonitor.Enter())
|
||||
{
|
||||
if (mQueuedCollapseData != null)
|
||||
ewc.ParseCollapseRegions(mQueuedCollapseData.mData, mQueuedCollapseData.mTextVersion, ref mQueuedCollapseData.mCharIdSpan);
|
||||
DeleteAndNullify!(mQueuedCollapseData);
|
||||
}
|
||||
|
||||
if (ewc.mCollapseNeedsUpdate)
|
||||
ewc.UpdateCollapse();
|
||||
|
||||
// Process after mQueuedCollapseData so mCharIdSpan is still valid
|
||||
ProcessDeferredResolveResults(0);
|
||||
}
|
||||
|
||||
void InjectErrors(BfPassInstance processingPassInstance, EditWidgetContent.CharData[] processResolveCharData, IdSpan processCharIdSpan, bool keepPersistentErrors)
|
||||
|
@ -6267,7 +6465,7 @@ namespace IDE.ui
|
|||
|
||||
var font = IDEApp.sApp.mTinyCodeFont;
|
||||
|
||||
float lineWidth = Math.Max(font.GetWidth(ToStackString!(mEditWidget.Content.GetLineCount())) + GS!(8), GS!(32));
|
||||
float lineWidth = Math.Max(font.GetWidth(ToStackString!(mEditWidget.Content.GetLineCount())) + GS!(24), GS!(32));
|
||||
return Math.Max(GS!(24), lineWidth);
|
||||
}
|
||||
|
||||
|
@ -6285,7 +6483,7 @@ namespace IDE.ui
|
|||
}
|
||||
|
||||
// Always leave enough to read the first 3 lines
|
||||
if (mHeight < GS!(88))
|
||||
if ((mHeight < GS!(88)) && (mSplitBottomPanel == null))
|
||||
mHeight = GS!(88);
|
||||
|
||||
float splitterHeight = GS!(3);
|
||||
|
@ -6367,6 +6565,30 @@ namespace IDE.ui
|
|||
{
|
||||
base.MouseDown(x, y, btn, btnCount);
|
||||
|
||||
var ewc = (SourceEditWidgetContent)mEditWidget.Content;
|
||||
|
||||
if ((btn == 0) && (x >= mEditWidget.mX - GS!(13)) && (x < mEditWidget.mX - GS!(0)))
|
||||
{
|
||||
int lineClick = GetLineAt(0, y);
|
||||
if (lineClick >= mCollapseRegionView.mLineStart)
|
||||
{
|
||||
int relLine = lineClick - mCollapseRegionView.mLineStart;
|
||||
if (relLine < mCollapseRegionView.mCollapseIndices.Count)
|
||||
{
|
||||
uint32 collapseVal = mCollapseRegionView.mCollapseIndices[relLine];
|
||||
if ((((collapseVal & CollapseRegionView.cStartFlag) != 0) && (btnCount == 1)) ||
|
||||
(btnCount > 1))
|
||||
{
|
||||
int collapseIndex = collapseVal & CollapseRegionView.cIdMask;
|
||||
|
||||
var entry = ewc.mOrderedCollapseEntries[collapseIndex];
|
||||
ewc.SetCollapseOpen(collapseIndex, !entry.mIsOpen);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mSplitBottomPanel != null)
|
||||
{
|
||||
return;
|
||||
|
@ -6438,12 +6660,15 @@ namespace IDE.ui
|
|||
if (x > mEditWidget.mX - GS!(4))
|
||||
return -1;
|
||||
|
||||
DarkEditWidgetContent darkEditWidgetContent = (DarkEditWidgetContent)mEditWidget.Content;
|
||||
float lineSpacing = darkEditWidgetContent.mFont.GetLineSpacing();
|
||||
var ewc = (SourceEditWidgetContent)mEditWidget.Content;
|
||||
|
||||
float relY = y - mEditWidget.mY - mEditWidget.Content.Y - GS!(3);
|
||||
if (relY < 0)
|
||||
return -1;
|
||||
return (int)(relY / lineSpacing);
|
||||
int resultIdx = ewc.mLineCoords.BinarySearch(relY);
|
||||
if (resultIdx < 0)
|
||||
return ~resultIdx - 1;
|
||||
return resultIdx;
|
||||
}
|
||||
|
||||
public bool SelectBreakpointsAtLine(int selectLine)
|
||||
|
@ -6481,7 +6706,7 @@ namespace IDE.ui
|
|||
|
||||
if (btn == 0)
|
||||
{
|
||||
if ((x >= GS!(3)) && (x < mEditWidget.mX - GS!(8)))
|
||||
if ((x >= GS!(3)) && (x < mEditWidget.mX - GS!(14)))
|
||||
{
|
||||
int lineClick = GetLineAt(x, y);
|
||||
if (lineClick >= 0)
|
||||
|
@ -6503,6 +6728,18 @@ namespace IDE.ui
|
|||
}
|
||||
}
|
||||
|
||||
public override void MouseLeave()
|
||||
{
|
||||
base.MouseLeave();
|
||||
mMousePos = null;
|
||||
}
|
||||
|
||||
public override void MouseMove(float x, float y)
|
||||
{
|
||||
base.MouseMove(x, y);
|
||||
mMousePos = .(x, y);
|
||||
}
|
||||
|
||||
public override void DrawAll(Graphics g)
|
||||
{
|
||||
DarkEditWidgetContent darkEditWidgetContent = (DarkEditWidgetContent)mEditWidget.Content;
|
||||
|
@ -6623,5 +6860,6 @@ namespace IDE.ui
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9151,6 +9151,272 @@ BF_EXPORT bool BF_CALLTYPE BfCompiler_ClassifySource(BfCompiler* bfCompiler, BfP
|
|||
return !canceled;
|
||||
}
|
||||
|
||||
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetCollapseRegions(BfCompiler* bfCompiler, BfParser* bfParser)
|
||||
{
|
||||
String& outString = *gTLStrReturn.Get();
|
||||
outString.Clear();
|
||||
|
||||
class CollapseVisitor : public BfElementVisitor
|
||||
{
|
||||
public:
|
||||
BfParser* mParser;
|
||||
String& mOutString;
|
||||
HashSet<int> mStartsFound;
|
||||
char mSeriesKind;
|
||||
int mStartSeriesIdx;
|
||||
int mEndSeriesIdx;
|
||||
|
||||
public:
|
||||
CollapseVisitor(BfParser* parser, String& string) : mOutString(string)
|
||||
{
|
||||
mParser = parser;
|
||||
|
||||
mSeriesKind = 0;
|
||||
mStartSeriesIdx = -1;
|
||||
mEndSeriesIdx = -1;
|
||||
}
|
||||
|
||||
void UpdateSeries(BfAstNode* node, char kind)
|
||||
{
|
||||
if (mStartSeriesIdx != -1)
|
||||
{
|
||||
if ((node->mTriviaStart != mEndSeriesIdx + 1) || (kind != mSeriesKind))
|
||||
{
|
||||
// Flush
|
||||
ConditionalAdd(mStartSeriesIdx, mStartSeriesIdx, mEndSeriesIdx, mSeriesKind);
|
||||
mStartSeriesIdx = node->mSrcStart;
|
||||
}
|
||||
}
|
||||
else
|
||||
mStartSeriesIdx = node->mSrcStart;
|
||||
|
||||
mSeriesKind = kind;
|
||||
mEndSeriesIdx = node->mSrcEnd - 1;
|
||||
}
|
||||
|
||||
void FlushSeries()
|
||||
{
|
||||
if (mStartSeriesIdx != -1)
|
||||
ConditionalAdd(mStartSeriesIdx, mStartSeriesIdx, mEndSeriesIdx, mSeriesKind);
|
||||
mStartSeriesIdx = -1;
|
||||
}
|
||||
|
||||
void ConditionalAdd(int anchor, int start, int end, char kind = '?')
|
||||
{
|
||||
bool isMultiline = false;
|
||||
for (int i = start; i < end; i++)
|
||||
{
|
||||
if (mParser->mSrc[i] == '\n')
|
||||
{
|
||||
isMultiline = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isMultiline)
|
||||
return;
|
||||
char str[1024];
|
||||
sprintf(str, "%c%d,%d,%d\n", kind, anchor, start, end);
|
||||
mOutString.Append(str);
|
||||
}
|
||||
|
||||
void Add(BfAstNode* anchor, BfAstNode* start, BfAstNode* end, char kind = '?')
|
||||
{
|
||||
if ((anchor == NULL) || (start == NULL) || (end == NULL))
|
||||
return;
|
||||
if (!mStartsFound.Add(start->mSrcStart))
|
||||
return;
|
||||
char str[1024];
|
||||
sprintf(str, "%c%d,%d,%d\n", kind, anchor->mSrcStart, start->mSrcStart, end->mSrcStart);
|
||||
mOutString.Append(str);
|
||||
}
|
||||
|
||||
void Add(BfAstNode* anchor, BfAstNode* body, char kind = '?')
|
||||
{
|
||||
if (auto block = BfNodeDynCast<BfBlock>(body))
|
||||
{
|
||||
Add(anchor, block->mOpenBrace, block->mCloseBrace, kind);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Visit(BfMethodDeclaration* methodDeclaration) override
|
||||
{
|
||||
BfAstNode* anchorNode = methodDeclaration->mNameNode;
|
||||
if (auto ctorDeclaration = BfNodeDynCast<BfConstructorDeclaration>(methodDeclaration))
|
||||
anchorNode = ctorDeclaration->mThisToken;
|
||||
if (auto dtorDeclaration = BfNodeDynCast<BfDestructorDeclaration>(methodDeclaration))
|
||||
anchorNode = dtorDeclaration->mThisToken;
|
||||
if (auto propertyDeclaration = BfNodeDynCast<BfOperatorDeclaration>(methodDeclaration))
|
||||
anchorNode = propertyDeclaration->mOperatorToken;
|
||||
Add(anchorNode, methodDeclaration->mBody, 'M');
|
||||
|
||||
BfElementVisitor::Visit(methodDeclaration);
|
||||
}
|
||||
|
||||
virtual void Visit(BfNamespaceDeclaration* namespaceDeclaration) override
|
||||
{
|
||||
Add(namespaceDeclaration->mNamespaceNode, namespaceDeclaration->mBlock, 'N');
|
||||
|
||||
BfElementVisitor::Visit(namespaceDeclaration);
|
||||
}
|
||||
|
||||
virtual void Visit(BfUsingDirective* usingDirective) override
|
||||
{
|
||||
UpdateSeries(usingDirective, 'U');
|
||||
|
||||
BfElementVisitor::Visit(usingDirective);
|
||||
}
|
||||
|
||||
virtual void Visit(BfTypeDeclaration* typeDeclaration) override
|
||||
{
|
||||
BfAstNode* anchor = typeDeclaration->mNameNode;
|
||||
if (anchor == NULL)
|
||||
anchor = typeDeclaration->mStaticSpecifier;
|
||||
Add(anchor, typeDeclaration->mDefineNode, 'T');
|
||||
|
||||
BfElementVisitor::Visit(typeDeclaration);
|
||||
}
|
||||
|
||||
virtual void Visit(BfPropertyDeclaration* properyDeclaration) override
|
||||
{
|
||||
Add(properyDeclaration->mNameNode, properyDeclaration->mDefinitionBlock, 'P');
|
||||
|
||||
BfElementVisitor::Visit(properyDeclaration);
|
||||
}
|
||||
|
||||
virtual void Visit(BfIndexerDeclaration* indexerDeclaration) override
|
||||
{
|
||||
Add(indexerDeclaration->mThisToken, indexerDeclaration->mDefinitionBlock, 'P');
|
||||
|
||||
BfElementVisitor::Visit(indexerDeclaration);
|
||||
}
|
||||
|
||||
virtual void Visit(BfPropertyMethodDeclaration* methodDeclaration) override
|
||||
{
|
||||
Add(methodDeclaration->mNameNode, methodDeclaration->mBody);
|
||||
|
||||
BfElementVisitor::Visit(methodDeclaration);
|
||||
}
|
||||
|
||||
virtual void Visit(BfIfStatement* ifStatement) override
|
||||
{
|
||||
Add(ifStatement->mIfToken, ifStatement->mTrueStatement);
|
||||
Add(ifStatement->mElseToken, ifStatement->mFalseStatement);
|
||||
|
||||
BfElementVisitor::Visit(ifStatement);
|
||||
}
|
||||
|
||||
virtual void Visit(BfRepeatStatement* repeatStatement) override
|
||||
{
|
||||
Add(repeatStatement->mRepeatToken, repeatStatement->mEmbeddedStatement);
|
||||
|
||||
BfElementVisitor::Visit(repeatStatement);
|
||||
}
|
||||
|
||||
virtual void Visit(BfDoStatement* doStatement) override
|
||||
{
|
||||
Add(doStatement->mDoToken, doStatement->mEmbeddedStatement);
|
||||
|
||||
BfElementVisitor::Visit(doStatement);
|
||||
}
|
||||
|
||||
virtual void Visit(BfForStatement* forStatement) override
|
||||
{
|
||||
Add(forStatement->mForToken, forStatement->mEmbeddedStatement);
|
||||
|
||||
BfElementVisitor::Visit(forStatement);
|
||||
}
|
||||
|
||||
virtual void Visit(BfForEachStatement* forStatement) override
|
||||
{
|
||||
Add(forStatement->mForToken, forStatement->mEmbeddedStatement);
|
||||
|
||||
BfElementVisitor::Visit(forStatement);
|
||||
}
|
||||
|
||||
virtual void Visit(BfUsingStatement* usingStatement) override
|
||||
{
|
||||
Add(usingStatement->mUsingToken, usingStatement->mEmbeddedStatement);
|
||||
|
||||
BfElementVisitor::Visit(usingStatement);
|
||||
}
|
||||
|
||||
virtual void Visit(BfSwitchStatement* switchStatement) override
|
||||
{
|
||||
Add(switchStatement->mSwitchToken, switchStatement->mOpenBrace, switchStatement->mCloseBrace);
|
||||
|
||||
BfElementVisitor::Visit(switchStatement);
|
||||
}
|
||||
|
||||
virtual void Visit(BfLambdaBindExpression* lambdaExpression) override
|
||||
{
|
||||
Add(lambdaExpression->mFatArrowToken, lambdaExpression->mBody);
|
||||
|
||||
BfElementVisitor::Visit(lambdaExpression);
|
||||
}
|
||||
|
||||
virtual void Visit(BfBlock* block) override
|
||||
{
|
||||
Add(block->mOpenBrace, block->mOpenBrace, block->mCloseBrace);
|
||||
|
||||
BfElementVisitor::Visit(block);
|
||||
}
|
||||
};
|
||||
|
||||
CollapseVisitor collapseVisitor(bfParser, outString);
|
||||
collapseVisitor.VisitChild(bfParser->mRootNode);
|
||||
|
||||
BfAstNode* regionStart = NULL;
|
||||
BfPreprocessorNode* prevPreprocessorNode = NULL;
|
||||
int ignoredSectionStart = -1;
|
||||
|
||||
for (auto element : bfParser->mSidechannelRootNode->mChildArr)
|
||||
{
|
||||
if (auto preprocessorNode = BfNodeDynCast<BfPreprocessorNode>(element))
|
||||
{
|
||||
if ((ignoredSectionStart != -1) && (prevPreprocessorNode != NULL) && (prevPreprocessorNode->mCommand != NULL))
|
||||
{
|
||||
collapseVisitor.ConditionalAdd(prevPreprocessorNode->mCommand->mSrcStart, ignoredSectionStart, preprocessorNode->mSrcEnd - 1);
|
||||
ignoredSectionStart = -1;
|
||||
}
|
||||
|
||||
StringView sv = preprocessorNode->mCommand->ToStringView();
|
||||
if (sv == "region")
|
||||
regionStart = preprocessorNode->mCommand;
|
||||
else if (sv == "endregion")
|
||||
{
|
||||
collapseVisitor.Add(regionStart, regionStart, preprocessorNode->mCommand, 'R');
|
||||
regionStart = NULL;
|
||||
}
|
||||
|
||||
prevPreprocessorNode = preprocessorNode;
|
||||
}
|
||||
|
||||
if (auto preprocessorNode = BfNodeDynCast<BfPreprocesorIgnoredSectionNode>(element))
|
||||
{
|
||||
if (ignoredSectionStart == -1)
|
||||
{
|
||||
for (int i = preprocessorNode->mSrcStart; i < preprocessorNode->mSrcEnd - 1; i++)
|
||||
{
|
||||
if (bfParser->mSrc[i] == '\n')
|
||||
{
|
||||
ignoredSectionStart = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char kind = 0;
|
||||
if (auto commentNode = BfNodeDynCast<BfCommentNode>(element))
|
||||
collapseVisitor.UpdateSeries(commentNode, 'C');
|
||||
}
|
||||
|
||||
collapseVisitor.FlushSeries();
|
||||
|
||||
|
||||
return outString.c_str();
|
||||
}
|
||||
|
||||
BF_EXPORT bool BF_CALLTYPE BfCompiler_VerifyTypeName(BfCompiler* bfCompiler, char* name, int cursorPos)
|
||||
{
|
||||
String typeName = name;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue