mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-09 20:12:21 +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;
|
return list;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
[DisableChecks]
|
||||||
public static int64 DecodeInt64(ref uint8* ptr)
|
public static int64 DecodeInt64(ref uint8* ptr)
|
||||||
{
|
{
|
||||||
int64 value = 0;
|
int64 value = 0;
|
||||||
|
@ -364,6 +365,7 @@ namespace Beefy
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[DisableChecks]
|
||||||
public static int32 DecodeInt(uint8[] buf, ref int idx)
|
public static int32 DecodeInt(uint8[] buf, ref int idx)
|
||||||
{
|
{
|
||||||
int32 value = 0;
|
int32 value = 0;
|
||||||
|
@ -383,6 +385,7 @@ namespace Beefy
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[DisableChecks]
|
||||||
public static void EncodeInt(uint8[] buf, ref int idx, int value)
|
public static void EncodeInt(uint8[] buf, ref int idx, int value)
|
||||||
{
|
{
|
||||||
int curValue = value;
|
int curValue = value;
|
||||||
|
|
|
@ -5,11 +5,49 @@ using System.Text;
|
||||||
using Beefy.widgets;
|
using Beefy.widgets;
|
||||||
using Beefy.gfx;
|
using Beefy.gfx;
|
||||||
using Beefy.utils;
|
using Beefy.utils;
|
||||||
|
using Beefy.geom;
|
||||||
|
|
||||||
namespace Beefy.theme.dark
|
namespace Beefy.theme.dark
|
||||||
{
|
{
|
||||||
public class DarkEditWidgetContent : EditWidgetContent
|
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 Font mFont;
|
||||||
public uint32[] mTextColors = sDefaultColors;
|
public uint32[] mTextColors = sDefaultColors;
|
||||||
public uint32 mHiliteColor = 0xFF2f5c88;
|
public uint32 mHiliteColor = 0xFF2f5c88;
|
||||||
|
@ -23,6 +61,7 @@ namespace Beefy.theme.dark
|
||||||
public uint32 mViewWhiteSpaceColor;
|
public uint32 mViewWhiteSpaceColor;
|
||||||
public bool mScrollToStartOnLostFocus;
|
public bool mScrollToStartOnLostFocus;
|
||||||
public bool mHiliteCurrentLine;
|
public bool mHiliteCurrentLine;
|
||||||
|
public Dictionary<int, Embed> mEmbeds = new .() ~ DeleteDictionaryAndValues!(_);
|
||||||
|
|
||||||
protected static uint32[] sDefaultColors = new uint32[] ( Color.White ) ~ delete _;
|
protected static uint32[] sDefaultColors = new uint32[] ( Color.White ) ~ delete _;
|
||||||
|
|
||||||
|
@ -39,6 +78,48 @@ namespace Beefy.theme.dark
|
||||||
mFont = DarkTheme.sDarkTheme?.mSmallFont;
|
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()
|
public override void GetTextData()
|
||||||
{
|
{
|
||||||
// Generate text flags if we need to...
|
// Generate text flags if we need to...
|
||||||
|
@ -97,6 +178,54 @@ namespace Beefy.theme.dark
|
||||||
}
|
}
|
||||||
|
|
||||||
base.GetTextData();
|
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)
|
protected override void AdjustCursorsAfterExternalEdit(int index, int ofs)
|
||||||
|
@ -322,6 +451,8 @@ namespace Beefy.theme.dark
|
||||||
Utils.RoundScale(ref mTabSize, newScale / oldScale);
|
Utils.RoundScale(ref mTabSize, newScale / oldScale);
|
||||||
SetFont(mFont, mCharWidth != -1, mAllowVirtualCursor);
|
SetFont(mFont, mCharWidth != -1, mAllowVirtualCursor);
|
||||||
mContentChanged = true; // Defer calling of RecalcSize
|
mContentChanged = true; // Defer calling of RecalcSize
|
||||||
|
GetTextData();
|
||||||
|
LineStartsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual float DrawText(Graphics g, String str, float x, float y, uint16 typeIdAndFlags)
|
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;
|
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)
|
public override void Draw(Graphics g)
|
||||||
{
|
{
|
||||||
base.Draw(g);
|
base.Draw(g);
|
||||||
|
|
||||||
|
|
||||||
#unwarn
|
#unwarn
|
||||||
int lineCount = GetLineCount();
|
int lineCount = GetLineCount();
|
||||||
float lineSpacing = GetLineHeight(0);
|
float lineSpacing = mFont.GetLineSpacing();
|
||||||
|
|
||||||
g.SetFont(mFont);
|
|
||||||
|
|
||||||
float offsetY = mTextInsets.mTop;
|
float offsetY = mTextInsets.mTop;
|
||||||
if (mHeight < lineSpacing)
|
if (mHeight < lineSpacing)
|
||||||
|
@ -377,6 +545,49 @@ namespace Beefy.theme.dark
|
||||||
GetLineCharAtCoord(0, -mY + mEditWidget.mScrollContentContainer.mHeight, out lastLine, out lastCharIdx, out lastOverflowX);
|
GetLineCharAtCoord(0, -mY + mEditWidget.mScrollContentContainer.mHeight, out lastLine, out lastCharIdx, out lastOverflowX);
|
||||||
|
|
||||||
bool drewCursor = false;
|
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);
|
String sectionText = scope String(256);
|
||||||
for (int lineIdx = firstLine; lineIdx <= lastLine; lineIdx++)
|
for (int lineIdx = firstLine; lineIdx <= lastLine; lineIdx++)
|
||||||
{
|
{
|
||||||
|
@ -387,7 +598,26 @@ namespace Beefy.theme.dark
|
||||||
|
|
||||||
int lineDrawStart = lineStart;
|
int lineDrawStart = lineStart;
|
||||||
float curX = 0;
|
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)
|
while (true)
|
||||||
{
|
{
|
||||||
int lineDrawEnd = lineDrawStart;
|
int lineDrawEnd = lineDrawStart;
|
||||||
|
@ -481,46 +711,7 @@ namespace Beefy.theme.dark
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aX != -1)
|
if (aX != -1)
|
||||||
{
|
DrawCursor(aX, curY);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lineDrawStart = lineDrawEnd;
|
lineDrawStart = lineDrawEnd;
|
||||||
|
@ -529,6 +720,17 @@ namespace Beefy.theme.dark
|
||||||
if (lineDrawStart >= lineEnd)
|
if (lineDrawStart >= lineEnd)
|
||||||
break;
|
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();
|
g.PopMatrix();
|
||||||
|
@ -561,6 +763,8 @@ namespace Beefy.theme.dark
|
||||||
|
|
||||||
public override void GetTextCoordAtLineChar(int line, int lineChar, out float x, out float y)
|
public override void GetTextCoordAtLineChar(int line, int lineChar, out float x, out float y)
|
||||||
{
|
{
|
||||||
|
GetTextData();
|
||||||
|
|
||||||
String lineText = scope String(256);
|
String lineText = scope String(256);
|
||||||
GetLineText(line, lineText);
|
GetLineText(line, lineText);
|
||||||
if (lineChar > lineText.Length)
|
if (lineChar > lineText.Length)
|
||||||
|
@ -571,32 +775,63 @@ namespace Beefy.theme.dark
|
||||||
subText.Append(lineText, 0, lineChar);
|
subText.Append(lineText, 0, lineChar);
|
||||||
x = GetTabbedWidth(subText, 0, true) + mTextInsets.mLeft;
|
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)
|
public override void GetTextCoordAtLineAndColumn(int line, int column, out float x, out float y)
|
||||||
{
|
{
|
||||||
|
GetTextData();
|
||||||
Debug.Assert((mCharWidth != -1) || (column == 0));
|
Debug.Assert((mCharWidth != -1) || (column == 0));
|
||||||
String lineText = scope String(256);
|
String lineText = scope String(256);
|
||||||
GetLineText(line, lineText);
|
GetLineText(line, lineText);
|
||||||
x = mTextInsets.mLeft + column * mCharWidth;
|
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();
|
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)
|
if (line < 0)
|
||||||
line = 0;
|
line = 0;
|
||||||
if (line >= lineCount)
|
if (line >= lineCount)
|
||||||
line = lineCount - 1;
|
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);
|
String lineText = scope String(256);
|
||||||
GetLineText(line, lineText);
|
GetLineText(line, lineText);
|
||||||
int32 char8Count = GetTabbedCharCountToLength(lineText, x - mTextInsets.mLeft);
|
int32 char8Count = GetTabbedCharCountToLength(lineText, x - mTextInsets.mLeft);
|
||||||
char8Idx = char8Count;
|
lineChar = char8Count;
|
||||||
|
|
||||||
if (char8Count < lineText.Length)
|
if (char8Count < lineText.Length)
|
||||||
{
|
{
|
||||||
|
@ -617,7 +852,7 @@ namespace Beefy.theme.dark
|
||||||
}
|
}
|
||||||
|
|
||||||
if (x >= subWidth + mTextInsets.mLeft + checkCharWidth)
|
if (x >= subWidth + mTextInsets.mLeft + checkCharWidth)
|
||||||
char8Idx = (int32)utf8enumerator.NextIndex;
|
lineChar = (int32)utf8enumerator.NextIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -630,16 +865,6 @@ namespace Beefy.theme.dark
|
||||||
return true;
|
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)
|
void RecalcSize(int32 startLineNum, int32 endLineNum, bool forceAccurate = false)
|
||||||
{
|
{
|
||||||
scope AutoBeefPerf("DEWC.RecalcSize");
|
scope AutoBeefPerf("DEWC.RecalcSize");
|
||||||
|
@ -670,6 +895,53 @@ namespace Beefy.theme.dark
|
||||||
base.CursorToLineEnd();
|
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)
|
public void RecalcSize(bool forceAccurate = false)
|
||||||
{
|
{
|
||||||
mMaximalScrollAddedHeight = 0;
|
mMaximalScrollAddedHeight = 0;
|
||||||
|
@ -707,7 +979,9 @@ namespace Beefy.theme.dark
|
||||||
Debug.Assert(!mWidth.IsNaN);
|
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();
|
UpdateMaximalScroll();
|
||||||
base.RecalcSize();
|
base.RecalcSize();
|
||||||
}
|
}
|
||||||
|
@ -721,6 +995,21 @@ namespace Beefy.theme.dark
|
||||||
{
|
{
|
||||||
base.ContentChanged();
|
base.ContentChanged();
|
||||||
mRecalcSizeLineNum = -1;
|
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)
|
public override void TextAppended(String str)
|
||||||
|
@ -734,7 +1023,7 @@ namespace Beefy.theme.dark
|
||||||
base.TextAppended(str);
|
base.TextAppended(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateMaximalScroll()
|
protected void UpdateMaximalScroll()
|
||||||
{
|
{
|
||||||
if (mAllowMaximalScroll)
|
if (mAllowMaximalScroll)
|
||||||
{
|
{
|
||||||
|
@ -744,6 +1033,8 @@ namespace Beefy.theme.dark
|
||||||
mMaximalScrollAddedHeight = mEditWidget.mScrollContentContainer.mHeight - mFont.GetLineSpacing();
|
mMaximalScrollAddedHeight = mEditWidget.mScrollContentContainer.mHeight - mFont.GetLineSpacing();
|
||||||
mHeight += mMaximalScrollAddedHeight;
|
mHeight += mMaximalScrollAddedHeight;
|
||||||
|
|
||||||
|
Debug.Assert(mHeight >= 0);
|
||||||
|
|
||||||
if (mHeight != prevHeight)
|
if (mHeight != prevHeight)
|
||||||
mEditWidget.UpdateScrollbars();
|
mEditWidget.UpdateScrollbars();
|
||||||
}
|
}
|
||||||
|
@ -757,7 +1048,9 @@ namespace Beefy.theme.dark
|
||||||
|
|
||||||
public override float GetLineHeight(int line)
|
public override float GetLineHeight(int line)
|
||||||
{
|
{
|
||||||
return mFont.GetLineSpacing();
|
if (mLineCoords == null)
|
||||||
|
GetTextData();
|
||||||
|
return mLineCoords[line + 1] - mLineCoords[line];
|
||||||
}
|
}
|
||||||
|
|
||||||
public override float GetPageScrollTextHeight()
|
public override float GetPageScrollTextHeight()
|
||||||
|
@ -843,6 +1136,27 @@ namespace Beefy.theme.dark
|
||||||
|
|
||||||
CheckRecordScrollTop();
|
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
|
public class DarkEditWidget : EditWidget
|
||||||
|
|
|
@ -181,6 +181,8 @@ namespace Beefy.theme.dark
|
||||||
PanelHeader,
|
PanelHeader,
|
||||||
|
|
||||||
ExtMethod,
|
ExtMethod,
|
||||||
|
CollapseClosed,
|
||||||
|
CollapseOpened,
|
||||||
|
|
||||||
COUNT
|
COUNT
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,8 +6,129 @@ using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Beefy.utils
|
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
|
enum Change
|
||||||
{
|
{
|
||||||
case Insert(int32 index, int32 id, int16 length);
|
case Insert(int32 index, int32 id, int16 length);
|
||||||
|
@ -671,7 +792,6 @@ namespace Beefy.utils
|
||||||
|
|
||||||
public IdSpan Duplicate()
|
public IdSpan Duplicate()
|
||||||
{
|
{
|
||||||
Debug.Assert(!HasChangeList);
|
|
||||||
IdSpan idSpan = IdSpan();
|
IdSpan idSpan = IdSpan();
|
||||||
if (mData != null)
|
if (mData != null)
|
||||||
{
|
{
|
||||||
|
@ -679,6 +799,12 @@ namespace Beefy.utils
|
||||||
mData.CopyTo(idSpan.mData, 0, 0, mLength);
|
mData.CopyTo(idSpan.mData, 0, 0, mLength);
|
||||||
idSpan.mLength = mLength;
|
idSpan.mLength = mLength;
|
||||||
}
|
}
|
||||||
|
if (mChangeList != null)
|
||||||
|
{
|
||||||
|
idSpan.mChangeList = new .();
|
||||||
|
for (var change in mChangeList)
|
||||||
|
idSpan.mChangeList.Add(change);
|
||||||
|
}
|
||||||
return idSpan;
|
return idSpan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -866,6 +992,11 @@ namespace Beefy.utils
|
||||||
return idSpan;
|
return idSpan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void ToString(String strBuffer)
|
||||||
|
{
|
||||||
|
ToString(strBuffer, "", null);
|
||||||
|
}
|
||||||
|
|
||||||
public void Dump() mut
|
public void Dump() mut
|
||||||
{
|
{
|
||||||
Prepare();
|
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;
|
float y;
|
||||||
GetTextCoordAtLineAndColumn(mVirtualCursorPos.Value.mLine, mVirtualCursorPos.Value.mColumn, out x, out y);
|
GetTextCoordAtLineAndColumn(mVirtualCursorPos.Value.mLine, mVirtualCursorPos.Value.mColumn, out x, out y);
|
||||||
|
|
||||||
int line;
|
|
||||||
int lineChar;
|
int lineChar;
|
||||||
float overflowX;
|
float overflowX;
|
||||||
GetLineCharAtCoord(x, y, out line, out lineChar, out overflowX);
|
GetLineCharAtCoord(mVirtualCursorPos.Value.mLine, x, out lineChar, out overflowX);
|
||||||
mCursorTextPos = (int32)GetTextIdx(line, lineChar);
|
|
||||||
|
mCursorTextPos = (int32)GetTextIdx(mVirtualCursorPos.Value.mLine, lineChar);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mCursorTextPos;
|
return mCursorTextPos;
|
||||||
|
@ -606,14 +606,9 @@ namespace Beefy.widgets
|
||||||
int lineChar;
|
int lineChar;
|
||||||
GetLineCharAtIdx(mCursorTextPos, out line, out lineChar);
|
GetLineCharAtIdx(mCursorTextPos, out line, out lineChar);
|
||||||
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
GetTextCoordAtLineChar(line, lineChar, out x, out y);
|
|
||||||
|
|
||||||
int coordLine;
|
|
||||||
int coordLineColumn;
|
int coordLineColumn;
|
||||||
GetLineAndColumnAtCoord(x, y, out coordLine, out coordLineColumn);
|
GetLineAndColumnAtLineChar(line, lineChar, out coordLineColumn);
|
||||||
lineAndColumn.mLine = (int32)coordLine;
|
lineAndColumn.mLine = (int32)line;
|
||||||
lineAndColumn.mColumn = (int32)coordLineColumn;
|
lineAndColumn.mColumn = (int32)coordLineColumn;
|
||||||
return lineAndColumn;
|
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
|
public bool WantsUndo
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -645,6 +654,7 @@ namespace Beefy.widgets
|
||||||
mContentChanged = true;
|
mContentChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected virtual Data CreateEditData()
|
protected virtual Data CreateEditData()
|
||||||
{
|
{
|
||||||
return new Data();
|
return new Data();
|
||||||
|
@ -661,13 +671,13 @@ namespace Beefy.widgets
|
||||||
{
|
{
|
||||||
if (mVirtualCursorPos.HasValue)
|
if (mVirtualCursorPos.HasValue)
|
||||||
{
|
{
|
||||||
|
int32 line = mVirtualCursorPos.Value.mLine;
|
||||||
float x;
|
float x;
|
||||||
float y;
|
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;
|
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);
|
textPos = GetTextIdx(line, lineChar);
|
||||||
return success;
|
return success;
|
||||||
|
@ -1342,6 +1352,11 @@ namespace Beefy.widgets
|
||||||
mEditWidget.ContentChanged();
|
mEditWidget.ContentChanged();
|
||||||
|
|
||||||
TextChanged();
|
TextChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void LineStartsChanged()
|
||||||
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void TextAppended(String str)
|
public virtual void TextAppended(String str)
|
||||||
|
@ -1366,6 +1381,7 @@ namespace Beefy.widgets
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mData.mLineStarts.Add(mData.mTextLength);
|
mData.mLineStarts.Add(mData.mTextLength);
|
||||||
|
LineStartsChanged();
|
||||||
|
|
||||||
mContentChanged = true;
|
mContentChanged = true;
|
||||||
|
|
||||||
|
@ -1385,8 +1401,9 @@ namespace Beefy.widgets
|
||||||
{
|
{
|
||||||
// Generate line starts and text flags if we need to
|
// Generate line starts and text flags if we need to
|
||||||
|
|
||||||
if (mData.mLineStarts == null)
|
if (mData.mLineStarts != null)
|
||||||
{
|
return;
|
||||||
|
|
||||||
scope AutoBeefPerf("EWC.GetTextData");
|
scope AutoBeefPerf("EWC.GetTextData");
|
||||||
|
|
||||||
CharData* char8DataPtr = mData.mText.CArray();
|
CharData* char8DataPtr = mData.mText.CArray();
|
||||||
|
@ -1447,7 +1464,7 @@ namespace Beefy.widgets
|
||||||
}
|
}
|
||||||
|
|
||||||
mData.mLineStarts[lineIdx + 1] = mData.mTextLength;
|
mData.mLineStarts[lineIdx + 1] = mData.mTextLength;
|
||||||
}
|
LineStartsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Backspace()
|
public virtual void Backspace()
|
||||||
|
@ -1519,7 +1536,7 @@ namespace Beefy.widgets
|
||||||
ContentChanged();
|
ContentChanged();
|
||||||
if (offset != 0)
|
if (offset != 0)
|
||||||
{
|
{
|
||||||
MoveCursorToIdx(textPos, false, .FromTyping);
|
MoveCursorToIdx(textPos, false, .FromTyping_Deleting);
|
||||||
EnsureCursorVisible();
|
EnsureCursorVisible();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1648,7 +1665,7 @@ namespace Beefy.widgets
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int32 char8Count = 1;
|
int32 charCount = 1;
|
||||||
int checkIdx = textPos + 1;
|
int checkIdx = textPos + 1;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -1660,12 +1677,12 @@ namespace Beefy.widgets
|
||||||
if (!checkChar.IsCombiningMark)
|
if (!checkChar.IsCombiningMark)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
char8Count++;
|
charCount++;
|
||||||
checkIdx++;
|
checkIdx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
mData.mUndoManager.Add(new DeleteCharAction(this, 0, char8Count));
|
mData.mUndoManager.Add(new DeleteCharAction(this, 0, charCount));
|
||||||
PhysDeleteChars(0, char8Count);
|
PhysDeleteChars(0, charCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1934,7 +1951,7 @@ namespace Beefy.widgets
|
||||||
return .Other;
|
return .Other;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetTextCoordAtCursor(out float x, out float y)
|
public virtual void GetTextCoordAtCursor(out float x, out float y)
|
||||||
{
|
{
|
||||||
if (mVirtualCursorPos.HasValue)
|
if (mVirtualCursorPos.HasValue)
|
||||||
{
|
{
|
||||||
|
@ -1963,8 +1980,9 @@ namespace Beefy.widgets
|
||||||
float y;
|
float y;
|
||||||
GetTextCoordAtLineAndColumn(mVirtualCursorPos.Value.mLine, mVirtualCursorPos.Value.mColumn, out x, out y);
|
GetTextCoordAtLineAndColumn(mVirtualCursorPos.Value.mLine, mVirtualCursorPos.Value.mColumn, out x, out y);
|
||||||
|
|
||||||
|
|
||||||
float overflowX;
|
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)
|
public virtual bool PrepareForCursorMove(int dir = 0)
|
||||||
|
@ -2064,6 +2082,7 @@ namespace Beefy.widgets
|
||||||
if (var insertTextAction = mData.mUndoManager.GetLastUndoAction() as InsertTextAction)
|
if (var insertTextAction = mData.mUndoManager.GetLastUndoAction() as InsertTextAction)
|
||||||
insertTextAction.mVirtualCursorPos = origPosition;
|
insertTextAction.mVirtualCursorPos = origPosition;
|
||||||
CursorLineAndColumn = lineStartPosition;
|
CursorLineAndColumn = lineStartPosition;
|
||||||
|
|
||||||
CursorToLineStart(false);
|
CursorToLineStart(false);
|
||||||
|
|
||||||
// Adjust to requested column
|
// Adjust to requested column
|
||||||
|
@ -2110,15 +2129,15 @@ namespace Beefy.widgets
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (lineChar > 0)
|
if (lineChar > 0)
|
||||||
MoveCursorTo(lineIdx, lineChar - 1);
|
MoveCursorTo(lineIdx, lineChar - 1, false, 0, .SelectLeft);
|
||||||
else if (lineIdx > 0)
|
else if (lineIdx > 0)
|
||||||
{
|
{
|
||||||
int cursorIdx = mCursorTextPos;
|
int cursorIdx = mCursorTextPos;
|
||||||
String lineText = scope String();
|
String lineText = scope String();
|
||||||
GetLineText(lineIdx - 1, lineText);
|
GetLineText(lineIdx - 1, lineText);
|
||||||
MoveCursorTo(lineIdx - 1, (int32)lineText.Length);
|
MoveCursorTo(lineIdx - 1, (int32)lineText.Length, false, 0, .SelectLeft);
|
||||||
if ((!mAllowVirtualCursor) && (cursorIdx == mCursorTextPos))
|
if ((!mAllowVirtualCursor) && (cursorIdx == mCursorTextPos))
|
||||||
MoveCursorTo(lineIdx - 1, (int32)lineText.Length - 1);
|
MoveCursorTo(lineIdx - 1, (int32)lineText.Length - 1, false, 0, .SelectLeft);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2180,9 +2199,9 @@ namespace Beefy.widgets
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isWithinLine)
|
if (isWithinLine)
|
||||||
MoveCursorTo(lineIdx, lineChar + 1, false, 1);
|
MoveCursorTo(lineIdx, lineChar + 1, false, 1, .SelectRight);
|
||||||
else if (lineIdx < GetLineCount() - 1)
|
else if (lineIdx < GetLineCount() - 1)
|
||||||
MoveCursorTo(lineIdx + 1, 0);
|
MoveCursorTo(lineIdx + 1, 0, false, 0, .SelectRight);
|
||||||
|
|
||||||
if (!mWidgetWindow.IsKeyDown(KeyCode.Control))
|
if (!mWidgetWindow.IsKeyDown(KeyCode.Control))
|
||||||
break;
|
break;
|
||||||
|
@ -2349,7 +2368,7 @@ namespace Beefy.widgets
|
||||||
var lineAndColumn = CursorLineAndColumn;
|
var lineAndColumn = CursorLineAndColumn;
|
||||||
CursorLineAndColumn = LineAndColumn(lineAndColumn.mLine, lineAndColumn.mColumn + 1);
|
CursorLineAndColumn = LineAndColumn(lineAndColumn.mLine, lineAndColumn.mColumn + 1);
|
||||||
EnsureCursorVisible(true, false, false);
|
EnsureCursorVisible(true, false, false);
|
||||||
CursorMoved();
|
PhysCursorMoved(.SelectRight);
|
||||||
|
|
||||||
ClampCursor();
|
ClampCursor();
|
||||||
if (lineAndColumn != CursorLineAndColumn)
|
if (lineAndColumn != CursorLineAndColumn)
|
||||||
|
@ -2393,22 +2412,40 @@ namespace Beefy.widgets
|
||||||
wasMoveKey = true;
|
wasMoveKey = true;
|
||||||
if ((lineIdx + aDir >= 0) && (lineIdx + aDir < GetLineCount()))
|
if ((lineIdx + aDir >= 0) && (lineIdx + aDir < GetLineCount()))
|
||||||
{
|
{
|
||||||
|
float wantedX = mCursorWantX;
|
||||||
|
float wantY = 0;
|
||||||
|
|
||||||
if (mAllowVirtualCursor)
|
if (mAllowVirtualCursor)
|
||||||
{
|
{
|
||||||
float cursorX;
|
float cursorX;
|
||||||
float cursorY;
|
float cursorY;
|
||||||
GetTextCoordAtCursor(out cursorX, out 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;
|
//mCursorWantX = cursorX;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
lineIdx += aDir;
|
lineIdx += aDir;
|
||||||
|
|
||||||
float wantedX = mCursorWantX;
|
|
||||||
|
|
||||||
float aX;
|
float aX;
|
||||||
float aY;
|
float aY;
|
||||||
GetTextCoordAtLineChar(lineIdx, 0, out aX, out aY);
|
GetTextCoordAtLineChar(lineIdx, 0, out aX, out aY);
|
||||||
MoveCursorToCoord(mCursorWantX, aY);
|
wantY = aY;
|
||||||
|
}
|
||||||
|
MoveCursorToCoord(mCursorWantX, wantY);
|
||||||
|
|
||||||
ClampCursor();
|
ClampCursor();
|
||||||
|
|
||||||
|
@ -2645,6 +2682,12 @@ namespace Beefy.widgets
|
||||||
return false;
|
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)
|
public virtual bool GetLineAndColumnAtCoord(float x, float y, out int line, out int column)
|
||||||
{
|
{
|
||||||
line = -1;
|
line = -1;
|
||||||
|
@ -2818,11 +2861,11 @@ namespace Beefy.widgets
|
||||||
ExtractString(lineStart, lineEnd - lineStart, outStr); // Full line
|
ExtractString(lineStart, lineEnd - lineStart, outStr); // Full line
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetTextIdx(int line, int char8Idx)
|
public int GetTextIdx(int line, int charIdx)
|
||||||
{
|
{
|
||||||
GetTextData();
|
GetTextData();
|
||||||
int useLine = Math.Min(line, mData.mLineStarts.Count - 1);
|
int useLine = Math.Min(line, mData.mLineStarts.Count - 1);
|
||||||
return mData.mLineStarts[useLine] + char8Idx;
|
return mData.mLineStarts[useLine] + charIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetCharIdIdx(int32 findCharId)
|
public int GetCharIdIdx(int32 findCharId)
|
||||||
|
@ -2839,7 +2882,7 @@ namespace Beefy.widgets
|
||||||
|
|
||||||
int curLine = 0;
|
int curLine = 0;
|
||||||
int curColumn = 0;
|
int curColumn = 0;
|
||||||
int char8Idx = 0;
|
int charIdx = 0;
|
||||||
mData.mTextIdData.Prepare();
|
mData.mTextIdData.Prepare();
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -2863,7 +2906,7 @@ namespace Beefy.widgets
|
||||||
if ((curLine == line) && (curColumn == column))
|
if ((curLine == line) && (curColumn == column))
|
||||||
return char8Id;
|
return char8Id;
|
||||||
|
|
||||||
char8 c = (char8)mData.mText[char8Idx++].mChar;
|
char8 c = (char8)mData.mText[charIdx++].mChar;
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
{
|
{
|
||||||
if (curLine == line)
|
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;
|
x = 0;
|
||||||
y = 0;
|
y = 0;
|
||||||
|
@ -2892,8 +2935,13 @@ namespace Beefy.widgets
|
||||||
|
|
||||||
public enum CursorMoveKind
|
public enum CursorMoveKind
|
||||||
{
|
{
|
||||||
FromTyping,
|
case FromTyping;
|
||||||
Unknown
|
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-
|
// 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);
|
Debug.Assert(mSelection.Value.mEndPos <= mData.mTextLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
//public void MoveCursorTo
|
public virtual void GetLineAndColumnAtLineChar(int line, int lineChar, out int lineColumn)
|
||||||
|
|
||||||
public void MoveCursorTo(int line, int char8Idx, bool centerCursor = false, int movingDir = 0, CursorMoveKind cursorMoveKind = .Unknown)
|
|
||||||
{
|
{
|
||||||
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;
|
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)
|
// Skip over UTF8 parts AND unicode combining marks (ie: when we have a letter with an accent mark following it)
|
||||||
while (true)
|
while (true)
|
||||||
|
@ -3433,13 +3489,13 @@ namespace Beefy.widgets
|
||||||
|
|
||||||
public void MoveCursorToIdx(int index, bool centerCursor = false, CursorMoveKind cursorMoveKind = .Unknown)
|
public void MoveCursorToIdx(int index, bool centerCursor = false, CursorMoveKind cursorMoveKind = .Unknown)
|
||||||
{
|
{
|
||||||
int aLine;
|
int line;
|
||||||
int aCharIdx;
|
int charIdx;
|
||||||
GetLineCharAtIdx(index, out aLine, out aCharIdx);
|
GetLineCharAtIdx(index, out line, out charIdx);
|
||||||
MoveCursorTo(aLine, aCharIdx, centerCursor, 0, cursorMoveKind);
|
MoveCursorTo(line, charIdx, centerCursor, 0, cursorMoveKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MoveCursorToCoord(float x, float y)
|
public virtual void MoveCursorToCoord(float x, float y)
|
||||||
{
|
{
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
|
|
||||||
|
|
|
@ -822,6 +822,20 @@ namespace System.Collections
|
||||||
return false;
|
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
|
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);
|
int_cosize i = (int_cosize)FindEntryAlt(key);
|
||||||
|
@ -836,6 +850,20 @@ namespace System.Collections
|
||||||
return false;
|
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)
|
public TValue GetValueOrDefault(TKey key)
|
||||||
{
|
{
|
||||||
int_cosize i = (int_cosize)FindEntry(key);
|
int_cosize i = (int_cosize)FindEntry(key);
|
||||||
|
@ -1024,7 +1052,7 @@ namespace System.Collections
|
||||||
private int_cosize mVersion;
|
private int_cosize mVersion;
|
||||||
#endif
|
#endif
|
||||||
private int_cosize mIndex;
|
private int_cosize mIndex;
|
||||||
private TValue mCurrent;
|
private TValue* mCurrent;
|
||||||
|
|
||||||
const int_cosize cDictEntry = 1;
|
const int_cosize cDictEntry = 1;
|
||||||
const int_cosize cKeyValuePair = 2;
|
const int_cosize cKeyValuePair = 2;
|
||||||
|
@ -1051,7 +1079,7 @@ namespace System.Collections
|
||||||
{
|
{
|
||||||
if (mDictionary.mEntries[mIndex].mHashCode >= 0)
|
if (mDictionary.mEntries[mIndex].mHashCode >= 0)
|
||||||
{
|
{
|
||||||
mCurrent = mDictionary.mEntries[mIndex].mValue;
|
mCurrent = &mDictionary.mEntries[mIndex].mValue;
|
||||||
mIndex++;
|
mIndex++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1065,12 +1093,12 @@ namespace System.Collections
|
||||||
|
|
||||||
public TValue Current
|
public TValue Current
|
||||||
{
|
{
|
||||||
get { return mCurrent; }
|
get { return *mCurrent; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref TValue CurrentRef
|
public ref TValue CurrentRef
|
||||||
{
|
{
|
||||||
get mut { return ref mCurrent; }
|
get mut { return ref *mCurrent; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public ref TKey Key
|
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;
|
private Dictionary<TKey, TValue> mDictionary;
|
||||||
#if VERSION_DICTIONARY
|
#if VERSION_DICTIONARY
|
||||||
|
@ -1187,6 +1215,11 @@ namespace System.Collections
|
||||||
get { return *mCurrent; }
|
get { return *mCurrent; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ref TKey CurrentRef
|
||||||
|
{
|
||||||
|
get { return ref *mCurrent; }
|
||||||
|
}
|
||||||
|
|
||||||
public ref TValue Value
|
public ref TValue Value
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -1224,6 +1257,13 @@ namespace System.Collections
|
||||||
return .Err;
|
return .Err;
|
||||||
return Current;
|
return Current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Result<TKey*> GetNextRef() mut
|
||||||
|
{
|
||||||
|
if (!MoveNext())
|
||||||
|
return .Err;
|
||||||
|
return &CurrentRef;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -536,6 +536,15 @@ namespace System.Collections
|
||||||
EnsureCapacity(size, true);
|
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()
|
public Enumerator GetEnumerator()
|
||||||
{
|
{
|
||||||
return Enumerator(this);
|
return Enumerator(this);
|
||||||
|
@ -716,6 +725,13 @@ namespace System.Collections
|
||||||
sorter.[Friend]Sort(0, mSize);
|
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)
|
public int RemoveAll(Predicate<T> match)
|
||||||
{
|
{
|
||||||
int_cosize freeIndex = 0; // the first free slot in items array
|
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 Document", new () => { gApp.[Friend]TryCloseCurrentDocument(); });
|
||||||
Add("Close Panel", new () => { gApp.[Friend]TryCloseCurrentPanel(); });
|
Add("Close Panel", new () => { gApp.[Friend]TryCloseCurrentPanel(); });
|
||||||
Add("Close Workspace", new => gApp.[Friend]Cmd_CloseWorkspaceAndSetupNew);
|
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 Block", new => gApp.[Friend]CommentBlock, .Editor);
|
||||||
Add("Comment Lines", new => gApp.[Friend]CommentLines, .Editor);
|
Add("Comment Lines", new => gApp.[Friend]CommentLines, .Editor);
|
||||||
Add("Comment Toggle", new => gApp.[Friend]CommentToggle, .Editor);
|
Add("Comment Toggle", new => gApp.[Friend]CommentToggle, .Editor);
|
||||||
|
|
|
@ -60,6 +60,9 @@ namespace IDE.Compiler
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
static extern bool BfCompiler_ClassifySource(void* bfCompiler, void* bfPassInstance, void* bfParser, void* bfResolvePassData, void* char8Data);
|
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]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
static extern char8* BfCompiler_GetAutocompleteInfo(void* bfCompiler);
|
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);
|
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)
|
public bool VerifyTypeName(String typeName, int cursorPos)
|
||||||
{
|
{
|
||||||
return BfCompiler_VerifyTypeName(mNativeBfCompiler, typeName, (.)cursorPos);
|
return BfCompiler_VerifyTypeName(mNativeBfCompiler, typeName, (.)cursorPos);
|
||||||
|
|
|
@ -2439,6 +2439,42 @@ namespace IDE
|
||||||
//FinishShowingNewWorkspace();
|
//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]
|
[IDECommand]
|
||||||
void DeleteAllRight()
|
void DeleteAllRight()
|
||||||
{
|
{
|
||||||
|
@ -2485,6 +2521,73 @@ namespace IDE
|
||||||
sewc.ToggleComment(false);
|
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)
|
public Result<void, StructuredData.Error> StructuredLoad(StructuredData data, StringView filePath)
|
||||||
{
|
{
|
||||||
if (mWorkspace.IsSingleFileWorkspace)
|
if (mWorkspace.IsSingleFileWorkspace)
|
||||||
|
|
|
@ -2583,6 +2583,30 @@ namespace IDE
|
||||||
#endif
|
#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]
|
[IDECommand]
|
||||||
public void SetVal(String valName, String value)
|
public void SetVal(String valName, String value)
|
||||||
{
|
{
|
||||||
|
|
|
@ -774,6 +774,12 @@ namespace IDE
|
||||||
Add("Build Workspace", "F7");
|
Add("Build Workspace", "F7");
|
||||||
Add("Cancel Build", "Ctrl+Break");
|
Add("Cancel Build", "Ctrl+Break");
|
||||||
Add("Close Document", "Ctrl+W");
|
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("Compile File", "Ctrl+F7");
|
||||||
Add("Comment Block", "Ctrl+K, Ctrl+C");
|
Add("Comment Block", "Ctrl+K, Ctrl+C");
|
||||||
Add("Comment Lines", "Ctrl+K, Ctrl+/");
|
Add("Comment Lines", "Ctrl+K, Ctrl+/");
|
||||||
|
|
|
@ -85,7 +85,7 @@ namespace IDE.ui
|
||||||
public bool mIsReplace;
|
public bool mIsReplace;
|
||||||
public int32 mLastTextVersion;
|
public int32 mLastTextVersion;
|
||||||
bool mFoundMatches;
|
bool mFoundMatches;
|
||||||
bool mIsShowingMatches = false;
|
public bool mIsShowingMatches = false;
|
||||||
static String sLastSearchString = new String() ~ delete _;
|
static String sLastSearchString = new String() ~ delete _;
|
||||||
|
|
||||||
public bool mOwnsSelection;
|
public bool mOwnsSelection;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -165,7 +165,7 @@ namespace IDE.ui
|
||||||
|
|
||||||
public ~this()
|
public ~this()
|
||||||
{
|
{
|
||||||
NOP!();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,6 +300,35 @@ namespace IDE.ui
|
||||||
public int32 mDebuggerContinueIdx;
|
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
|
public class SourceViewPanel : TextPanel
|
||||||
{
|
{
|
||||||
enum SourceDisplayId
|
enum SourceDisplayId
|
||||||
|
@ -349,9 +378,12 @@ namespace IDE.ui
|
||||||
int32 mTicksSinceTextChanged;
|
int32 mTicksSinceTextChanged;
|
||||||
int32 mErrorLookupTextIdx = -1;
|
int32 mErrorLookupTextIdx = -1;
|
||||||
LinePointerDrawData mLinePointerDrawData;
|
LinePointerDrawData mLinePointerDrawData;
|
||||||
|
Point? mMousePos;
|
||||||
#if IDE_C_SUPPORT
|
#if IDE_C_SUPPORT
|
||||||
public String mClangHoverErrorData ~ delete mClangHoverErrorData;
|
public String mClangHoverErrorData ~ delete mClangHoverErrorData;
|
||||||
#endif
|
#endif
|
||||||
|
CollapseRegionView mCollapseRegionView = new .() ~ delete _;
|
||||||
|
QueuedCollapseData mQueuedCollapseData ~ delete _;
|
||||||
|
|
||||||
public EditWidgetContent.CharData[] mProcessSpellCheckCharData ~ delete _;
|
public EditWidgetContent.CharData[] mProcessSpellCheckCharData ~ delete _;
|
||||||
public IdSpan mProcessSpellCheckCharIdSpan ~ _.Dispose();
|
public IdSpan mProcessSpellCheckCharIdSpan ~ _.Dispose();
|
||||||
|
@ -1785,18 +1817,18 @@ namespace IDE.ui
|
||||||
parser = bfSystem.CreateEmptyParser((BfProject)null);
|
parser = bfSystem.CreateEmptyParser((BfProject)null);
|
||||||
}
|
}
|
||||||
|
|
||||||
EditWidgetContent.CharData[] char8Data = null;
|
EditWidgetContent.CharData[] charData = null;
|
||||||
int char8Len = 0;
|
int charLen = 0;
|
||||||
if ((resolveParams != null) && (resolveParams.mCharData != null))
|
if ((resolveParams != null) && (resolveParams.mCharData != null))
|
||||||
{
|
{
|
||||||
char8Data = resolveParams.mCharData;
|
charData = resolveParams.mCharData;
|
||||||
char8Len = resolveParams.mCharData.Count;
|
charLen = resolveParams.mCharData.Count;
|
||||||
}
|
}
|
||||||
if (char8Data == null)
|
if (charData == null)
|
||||||
{
|
{
|
||||||
Debug.Assert(!isBackground);
|
Debug.Assert(!isBackground);
|
||||||
char8Data = mEditWidget.Content.mData.mText;
|
charData = mEditWidget.Content.mData.mText;
|
||||||
char8Len = mEditWidget.Content.mData.mTextLength;
|
charLen = mEditWidget.Content.mData.mTextLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*var char8Data = (!isBackground) ? mEditWidget.Content.mData.mText : mProcessResolveCharData;
|
/*var char8Data = (!isBackground) ? mEditWidget.Content.mData.mText : mProcessResolveCharData;
|
||||||
|
@ -1818,12 +1850,12 @@ namespace IDE.ui
|
||||||
|
|
||||||
if (!isBackground)
|
if (!isBackground)
|
||||||
bfSystem.PerfZoneStart("DoClassify.CreateChars");
|
bfSystem.PerfZoneStart("DoClassify.CreateChars");
|
||||||
char8[] chars = new char8[char8Len];
|
char8[] chars = new char8[charLen];
|
||||||
defer delete chars;
|
defer delete chars;
|
||||||
for (int32 i = 0; i < char8Len; i++)
|
for (int32 i = 0; i < charLen; i++)
|
||||||
{
|
{
|
||||||
char8Data[i].mDisplayPassId = (int32)SourceDisplayId.Cleared;
|
charData[i].mDisplayPassId = (int32)SourceDisplayId.Cleared;
|
||||||
chars[i] = (char8)char8Data[i].mChar;
|
chars[i] = (char8)charData[i].mChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
String text = scope String();
|
String text = scope String();
|
||||||
|
@ -1933,7 +1965,7 @@ namespace IDE.ui
|
||||||
|
|
||||||
if ((!isFastClassify) && (bfCompiler != null))
|
if ((!isFastClassify) && (bfCompiler != null))
|
||||||
{
|
{
|
||||||
if (!bfCompiler.ClassifySource(passInstance, parser, resolvePassData, char8Data))
|
if (!bfCompiler.ClassifySource(passInstance, parser, resolvePassData, charData))
|
||||||
{
|
{
|
||||||
//DeleteAndNullify!(mProcessResolveCharData);
|
//DeleteAndNullify!(mProcessResolveCharData);
|
||||||
//mProcessResolveCharIdSpan.Dispose();
|
//mProcessResolveCharIdSpan.Dispose();
|
||||||
|
@ -1945,10 +1977,23 @@ namespace IDE.ui
|
||||||
}
|
}
|
||||||
bfCompiler.QueueDeferredResolveAll();
|
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
|
else
|
||||||
{
|
{
|
||||||
parser.ClassifySource(char8Data, !mIsBeefSource);
|
parser.ClassifySource(charData, !mIsBeefSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isBackground)
|
if (!isBackground)
|
||||||
|
@ -3637,6 +3682,18 @@ namespace IDE.ui
|
||||||
|
|
||||||
AddWidget(mSplitTopPanel);
|
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();
|
ResizeComponents();
|
||||||
|
|
||||||
// Match scroll positions
|
// Match scroll positions
|
||||||
|
@ -4106,7 +4163,8 @@ namespace IDE.ui
|
||||||
if (mLoadFailed)
|
if (mLoadFailed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DarkEditWidgetContent darkEditWidgetContent = (DarkEditWidgetContent)mEditWidget.Content;
|
var ewc = (SourceEditWidgetContent)mEditWidget.Content;
|
||||||
|
ewc.GetTextData();
|
||||||
|
|
||||||
g.SetFont(IDEApp.sApp.mTinyCodeFont);
|
g.SetFont(IDEApp.sApp.mTinyCodeFont);
|
||||||
|
|
||||||
|
@ -4115,13 +4173,93 @@ namespace IDE.ui
|
||||||
using (g.PushTranslate(0, mEditWidget.mY + mEditWidget.Content.Y + GS!(2)))
|
using (g.PushTranslate(0, mEditWidget.mY + mEditWidget.Content.Y + GS!(2)))
|
||||||
{
|
{
|
||||||
float editX = GetEditX();
|
float editX = GetEditX();
|
||||||
float lineSpacing = darkEditWidgetContent.mFont.GetLineSpacing();
|
float leftAdjust = GS!(12);
|
||||||
int cursorLineNumber = mEditWidget.mEditWidgetContent.CursorLineAndColumn.mLine;
|
|
||||||
using (g.PushColor(gApp.mSettings.mUISettings.mColors.mCurrentLineNumberHilite))
|
float lineSpacing = ewc.mFont.GetLineSpacing();
|
||||||
g.FillRect(0, GS!(2) + cursorLineNumber * lineSpacing, editX - GS!(2), lineSpacing);
|
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)
|
if (lineEnd <= lineStart)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -4144,8 +4282,8 @@ namespace IDE.ui
|
||||||
int breakpointCount = (.)(curLineFlags & .BreakpointCountMask);
|
int breakpointCount = (.)(curLineFlags & .BreakpointCountMask);
|
||||||
curLineFlags++;
|
curLineFlags++;
|
||||||
|
|
||||||
float iconX = Math.Max(GS!(-2), mEditWidget.mX - GS!(24)) + breakpointCount*-GS!(2);
|
float iconX = Math.Max(GS!(-2), mEditWidget.mX - GS!(24) - leftAdjust) + breakpointCount*-GS!(2);
|
||||||
float iconY = 0 + drawLineNum * lineSpacing + (lineSpacing - DarkTheme.sUnitSize + GS!(5)) / 2;
|
float iconY = 0 + ewc.mLineCoords[drawLineNum] + (lineSpacing - DarkTheme.sUnitSize + GS!(5)) / 2;
|
||||||
|
|
||||||
// Just leave last digit visible
|
// Just leave last digit visible
|
||||||
/*using (g.PushColor(0xFF595959))
|
/*using (g.PushColor(0xFF595959))
|
||||||
|
@ -4166,7 +4304,7 @@ namespace IDE.ui
|
||||||
if ((drawLineNum < lineStart) || (drawLineNum >= lineEnd))
|
if ((drawLineNum < lineStart) || (drawLineNum >= lineEnd))
|
||||||
continue;
|
continue;
|
||||||
//hadLineIcon[drawLineNum - lineStart] = true;
|
//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);
|
0 + bookmark.mLineNum * lineSpacing);
|
||||||
|
|
||||||
var curLineFlags = ref lineFlags[drawLineNum - lineStart];
|
var curLineFlags = ref lineFlags[drawLineNum - lineStart];
|
||||||
|
@ -4199,6 +4337,10 @@ namespace IDE.ui
|
||||||
{
|
{
|
||||||
for (int lineIdx = lineStart; lineIdx < lineEnd; lineIdx++)
|
for (int lineIdx = lineStart; lineIdx < lineEnd; lineIdx++)
|
||||||
{
|
{
|
||||||
|
float drawHeight = ewc.mLineCoords[lineIdx + 1] - ewc.mLineCoords[lineIdx];
|
||||||
|
if (drawHeight < lineSpacing * 0.25f)
|
||||||
|
continue;
|
||||||
|
|
||||||
lineStr.Clear();
|
lineStr.Clear();
|
||||||
|
|
||||||
int maxLineChars = Int32.MaxValue;
|
int maxLineChars = Int32.MaxValue;
|
||||||
|
@ -4216,7 +4358,43 @@ namespace IDE.ui
|
||||||
case 2: lineStr.AppendF("{0}", (lineIdx + 1) % 100);
|
case 2: lineStr.AppendF("{0}", (lineIdx + 1) % 100);
|
||||||
default: lineStr.AppendF("{0}", lineIdx + 1);
|
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;
|
Point mousePos;
|
||||||
bool mouseoverFired = DarkTooltipManager.CheckMouseover(editWidgetContent, 10, out mousePos);
|
bool mouseoverFired = DarkTooltipManager.CheckMouseover(editWidgetContent, 10, out mousePos);
|
||||||
|
|
||||||
|
if (mouseoverFired)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#unwarn
|
#unwarn
|
||||||
CompilerBase compiler = ResolveCompiler;
|
CompilerBase compiler = ResolveCompiler;
|
||||||
|
|
||||||
|
@ -5571,6 +5754,8 @@ namespace IDE.ui
|
||||||
if (checkIdx >= mDeferredResolveResults.Count)
|
if (checkIdx >= mDeferredResolveResults.Count)
|
||||||
break;
|
break;
|
||||||
resolveResult = mDeferredResolveResults[checkIdx];
|
resolveResult = mDeferredResolveResults[checkIdx];
|
||||||
|
}
|
||||||
|
|
||||||
if ((autocompleteOnly) && (resolveResult.mResolveType != .Autocomplete))
|
if ((autocompleteOnly) && (resolveResult.mResolveType != .Autocomplete))
|
||||||
{
|
{
|
||||||
checkIdx++;
|
checkIdx++;
|
||||||
|
@ -5588,8 +5773,9 @@ namespace IDE.ui
|
||||||
checkIdx++;
|
checkIdx++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using (mMonitor.Enter())
|
||||||
mDeferredResolveResults.RemoveAt(checkIdx);
|
mDeferredResolveResults.RemoveAt(checkIdx);
|
||||||
}
|
|
||||||
|
|
||||||
//Debug.WriteLine($"HandleResolveResult {resolveResult}");
|
//Debug.WriteLine($"HandleResolveResult {resolveResult}");
|
||||||
|
|
||||||
|
@ -6127,8 +6313,6 @@ namespace IDE.ui
|
||||||
DeleteAndNullify!(mQueuedAutoComplete);
|
DeleteAndNullify!(mQueuedAutoComplete);
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessDeferredResolveResults(0);
|
|
||||||
|
|
||||||
if (mLockFlashPct != 0)
|
if (mLockFlashPct != 0)
|
||||||
{
|
{
|
||||||
mLockFlashPct += 0.02f;
|
mLockFlashPct += 0.02f;
|
||||||
|
@ -6139,6 +6323,20 @@ namespace IDE.ui
|
||||||
|
|
||||||
if ((mEmitRevision >= 0) && ((mUpdateCnt % 30) == 0))
|
if ((mEmitRevision >= 0) && ((mUpdateCnt % 30) == 0))
|
||||||
CheckEmitRevision();
|
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)
|
void InjectErrors(BfPassInstance processingPassInstance, EditWidgetContent.CharData[] processResolveCharData, IdSpan processCharIdSpan, bool keepPersistentErrors)
|
||||||
|
@ -6267,7 +6465,7 @@ namespace IDE.ui
|
||||||
|
|
||||||
var font = IDEApp.sApp.mTinyCodeFont;
|
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);
|
return Math.Max(GS!(24), lineWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6285,7 +6483,7 @@ namespace IDE.ui
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always leave enough to read the first 3 lines
|
// Always leave enough to read the first 3 lines
|
||||||
if (mHeight < GS!(88))
|
if ((mHeight < GS!(88)) && (mSplitBottomPanel == null))
|
||||||
mHeight = GS!(88);
|
mHeight = GS!(88);
|
||||||
|
|
||||||
float splitterHeight = GS!(3);
|
float splitterHeight = GS!(3);
|
||||||
|
@ -6367,6 +6565,30 @@ namespace IDE.ui
|
||||||
{
|
{
|
||||||
base.MouseDown(x, y, btn, btnCount);
|
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)
|
if (mSplitBottomPanel != null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -6438,12 +6660,15 @@ namespace IDE.ui
|
||||||
if (x > mEditWidget.mX - GS!(4))
|
if (x > mEditWidget.mX - GS!(4))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
DarkEditWidgetContent darkEditWidgetContent = (DarkEditWidgetContent)mEditWidget.Content;
|
var ewc = (SourceEditWidgetContent)mEditWidget.Content;
|
||||||
float lineSpacing = darkEditWidgetContent.mFont.GetLineSpacing();
|
|
||||||
float relY = y - mEditWidget.mY - mEditWidget.Content.Y - GS!(3);
|
float relY = y - mEditWidget.mY - mEditWidget.Content.Y - GS!(3);
|
||||||
if (relY < 0)
|
if (relY < 0)
|
||||||
return -1;
|
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)
|
public bool SelectBreakpointsAtLine(int selectLine)
|
||||||
|
@ -6481,7 +6706,7 @@ namespace IDE.ui
|
||||||
|
|
||||||
if (btn == 0)
|
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);
|
int lineClick = GetLineAt(x, y);
|
||||||
if (lineClick >= 0)
|
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)
|
public override void DrawAll(Graphics g)
|
||||||
{
|
{
|
||||||
DarkEditWidgetContent darkEditWidgetContent = (DarkEditWidgetContent)mEditWidget.Content;
|
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;
|
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)
|
BF_EXPORT bool BF_CALLTYPE BfCompiler_VerifyTypeName(BfCompiler* bfCompiler, char* name, int cursorPos)
|
||||||
{
|
{
|
||||||
String typeName = name;
|
String typeName = name;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue