1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-07-04 15:26:00 +02:00

Merge branch 'master' into BookmarkPanel

This commit is contained in:
Simon Lübeß 2022-08-13 18:02:49 +02:00
commit 6884b9fc21
267 changed files with 26197 additions and 17792 deletions

View file

@ -13,6 +13,7 @@ namespace IDE
public class RegistryEntry
{
public String mProjName ~ delete _;
public Project.TargetType mTargetType;
public SemVer mVersion ~ delete _;
public VerSpec mLocation ~ _.Dispose();
public ConfigFile mConfigFile;
@ -51,6 +52,29 @@ namespace IDE
using (mMonitor.Enter())
entry.mProjName.Set(projName);
}
if (sd.Contains("StartupObject"))
entry.mTargetType = .BeefConsoleApplication;
else
entry.mTargetType = .BeefLib;
var targetTypeName = scope String();
sd.GetString("TargetType", targetTypeName);
if (!targetTypeName.IsEmpty)
{
switch (targetTypeName)
{ // Handle Legacy names first
case "BeefWindowsApplication":
entry.mTargetType = .BeefGUIApplication;
case "C_WindowsApplication":
entry.mTargetType = .C_GUIApplication;
case "BeefDynLib":
entry.mTargetType = .BeefLib;
default:
entry.mTargetType = sd.GetEnum<Project.TargetType>("TargetType", entry.mTargetType);
}
}
}
}
}

View file

@ -627,15 +627,7 @@ namespace IDE
return false;
}
String compilerExePath = scope String();
#if BF_PLATFORM_WINDOWS
String llvmDir = scope String(IDEApp.sApp.mInstallDir);
IDEUtils.FixFilePath(llvmDir);
llvmDir.Append("llvm/");
#else
String llvmDir = "";
#endif
if (gApp.mSettings.mEmscriptenPath.IsEmpty)
{
gApp.OutputErrorLine("Emscripten path not configured. Check Wasm configuration in File\\Preferences\\Settings.");

View file

@ -90,10 +90,11 @@ namespace IDE
{
if (mParent == null)
return;
int startIdx = strBuffer.Length;
mParent.ToString(strBuffer);
if (mBoundKeyState != null)
{
if (!strBuffer.IsEmpty)
if (strBuffer.Length > startIdx)
strBuffer.Append(", ");
mBoundKeyState.ToString(strBuffer);
}

View file

@ -156,7 +156,7 @@ namespace IDE.Compiler
static extern int32 BfCompiler_GetEmitSourceVersion(void* bfCompiler, char8* fileName);
[CallingConvention(.Stdcall), CLink]
static extern char8* BfCompiler_GetEmitLocation(void* bfCompiler, char8* typeName, int32 line, out int32 embedLine, out int32 embedLineChar);
static extern char8* BfCompiler_GetEmitLocation(void* bfCompiler, char8* typeName, int32 line, out int32 embedLine, out int32 embedLineChar, out uint64 hash);
[CallingConvention(.Stdcall), CLink]
static extern void BfCompiler_WriteEmitData(void* bfCompiler, char8* filePath, void* bfProject);
@ -362,11 +362,11 @@ namespace IDE.Compiler
return BfCompiler_GetEmitSourceVersion(mNativeBfCompiler, fileName.ToScopeCStr!());
}
public void GetEmitLocation(StringView typeName, int line, String outFilePath, out int embedLine, out int embedLineChar)
public void GetEmitLocation(StringView typeName, int line, String outFilePath, out int embedLine, out int embedLineChar, out uint64 hash)
{
int32 embedLine32;
int32 embedLineChar32;
outFilePath.Append(BfCompiler_GetEmitLocation(mNativeBfCompiler, typeName.ToScopeCStr!(), (.)line, out embedLine32, out embedLineChar32));
outFilePath.Append(BfCompiler_GetEmitLocation(mNativeBfCompiler, typeName.ToScopeCStr!(), (.)line, out embedLine32, out embedLineChar32, out hash));
embedLine = embedLine32;
embedLineChar = embedLineChar32;
}
@ -603,6 +603,8 @@ namespace IDE.Compiler
UpdateRebuildFileWatches();
mBfSystem.RemoveOldParsers();
mBfSystem.RemoveOldData();
if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Build)
QueueRefreshViewCommand(.Collapse);
}
if (command is ResolveAllCommand)

View file

@ -239,6 +239,16 @@ namespace IDE.Compiler
}
}
public BfParser GetParser(ProjectSource projectSource)
{
using (mMonitor.Enter())
{
BfParser parser;
mParserMap.TryGetValue(projectSource, out parser);
return parser;
}
}
public BfParser CreateNewParserRevision(BfParser prevParser)
{
using (mMonitor.Enter())

View file

@ -57,6 +57,14 @@ namespace IDE
String mWorkspaceDir = new String() ~ delete _;
bool mWantWorkspaceCleanup;
public bool mDisabled;
Dictionary<String, List<uint8>> mDB = new .() ~ DeleteDictionaryAndKeysAndValues!(_);
public bool mDBDirty;
public String mDBWorkspaceDir = new String() ~ delete _;
public this()
{
}
public ~this()
{
@ -84,6 +92,26 @@ namespace IDE
bool wantWorkspaceCleanup = false;
using (mMonitor.Enter())
{
if (mDBDirty)
{
String recoverPath = scope String();
recoverPath.Append(mWorkspaceDir);
recoverPath.Append("/recovery/db.bin");
FileStream fs = scope .();
if (fs.Create(recoverPath) case .Ok)
{
fs.Write((uint32)0xBEEF0701);
for (var kv in mDB)
{
fs.WriteStrSized32(kv.key).IgnoreError();
fs.Write((int32)kv.value.Count);
fs.TryWrite(kv.value).IgnoreError();
}
}
mDBDirty = false;
}
for (var entry in mFileSet)
{
if (entry.mRecoveryFileName == null)
@ -250,6 +278,104 @@ namespace IDE
}
}
public void CheckDB()
{
if (mDBWorkspaceDir == gApp.mWorkspace.mDir)
return;
using (mMonitor.Enter())
{
for (var kv in mDB)
{
delete kv.key;
delete kv.value;
}
mDB.Clear();
mDBWorkspaceDir.Set(gApp.mWorkspace.mDir);
if (mDBWorkspaceDir.IsEmpty)
return;
String recoverPath = scope String();
recoverPath.Append(mDBWorkspaceDir);
recoverPath.Append("/recovery/db.bin");
FileStream fs = scope .();
if (fs.Open(recoverPath) case .Ok)
{
if (fs.Read<uint32>() == 0xBEEF0701)
{
String filePath = scope .();
while (true)
{
filePath.Clear();
if (fs.ReadStrSized32(filePath) case .Err)
break;
if (filePath.IsEmpty)
break;
int32 dataSize = fs.Read<int32>();
List<uint8> list = new List<uint8>();
mDB[new String(filePath)] = list;
list.Resize(dataSize);
if (fs.TryRead(.(list.Ptr, dataSize)) case .Err)
break;
}
}
}
}
}
public void SetDB(StringView key, Span<uint8> data)
{
using (mMonitor.Enter())
{
CheckDB();
if (mDB.TryAddAlt(key, var keyPtr, var valuePtr))
{
*keyPtr = new .(key);
*valuePtr = new .();
}
(*valuePtr).Clear();
(*valuePtr).AddRange(data);
mDBDirty = true;
}
}
public bool GetDB(StringView key, List<uint8> data)
{
using (mMonitor.Enter())
{
CheckDB();
if (mDB.TryGetAlt(key, var matchKey, var value))
{
data.AddRange(value);
return true;
}
return false;
}
}
public bool DeleteDB(StringView key)
{
using (mMonitor.Enter())
{
CheckDB();
if (mDB.GetAndRemoveAlt(key) case .Ok((var mapKey, var value)))
{
mDBDirty = true;
delete mapKey;
delete value;
return true;
}
return false;
}
}
public void Update()
{
if (mProcessingEvent != null)
@ -261,7 +387,7 @@ namespace IDE
using (mMonitor.Enter())
{
if ((!mDirty) && (!mWantWorkspaceCleanup))
if ((!mDirty) && (!mDBDirty) && (!mWantWorkspaceCleanup))
return;
}

View file

@ -95,6 +95,16 @@ namespace IDE
FileChanged(starPath, null, .Changed);
}
if ((isDirectory) && (changeType == .Renamed))
{
// On Windows, renaming a directory with only case changes will result in a remove before a rename
var dirName = scope String();
Path.GetDirectoryPath(newPath.Substring(0, newPath.Length - 1), dirName);
dirName.Append(Path.DirectorySeparatorChar);
FileChanged(dirName, newPath, .DirectoryCreated);
}
var newPath;
if (isDirectory)
{

View file

@ -119,7 +119,7 @@ namespace IDE
public class IDEApp : BFApp
{
public static String sRTVersionStr = "042";
public const String cVersion = "0.43.3";
public const String cVersion = "0.43.4";
#if BF_PLATFORM_WINDOWS
public static readonly String sPlatform64Name = "Win64";
@ -1475,6 +1475,14 @@ namespace IDE
return true;
}
public void SetEmbedCompiler(Settings.EditorSettings.CompilerKind emitCompiler)
{
gApp.mSettings.mEditorSettings.mEmitCompiler = emitCompiler;
mBfResolveCompiler?.QueueRefreshViewCommand(.Collapse);
if (emitCompiler == .Resolve)
mBfResolveCompiler?.QueueRefreshViewCommand(.FullRefresh);
}
public Result<void, FileError> LoadTextFile(String fileName, String outBuffer, bool autoRetry = true, delegate void() onPreFilter = null)
{
if (mWorkspace.IsSingleFileWorkspace)
@ -1490,9 +1498,23 @@ namespace IDE
if (fileName.StartsWith("$Emit$"))
{
BfCompiler compiler = mBfResolveCompiler;
String useFileName = fileName;
BfCompiler compiler = (gApp.mSettings.mEditorSettings.mEmitCompiler == .Resolve) ? mBfResolveCompiler : mBfBuildCompiler;
if (useFileName.StartsWith("$Emit$Build$"))
{
useFileName = scope:: $"$Emit${useFileName.Substring("$Emit$Build$".Length)}";
compiler = mBfBuildCompiler;
}
else if (useFileName.StartsWith("$Emit$Resolve$"))
{
useFileName = scope:: $"$Emit${useFileName.Substring("$Emit$Resolve$".Length)}";
compiler = mBfResolveCompiler;
}
if (!compiler.IsPerformingBackgroundOperation())
compiler.GetEmitSource(fileName, outBuffer);
compiler.GetEmitSource(useFileName, outBuffer);
if (onPreFilter != null)
onPreFilter();
@ -2299,7 +2321,7 @@ namespace IDE
AddNewProjectToWorkspace(project);
project.FinishCreate();
mProjectPanel.InitProject(project);
mProjectPanel.InitProject(project, mProjectPanel.GetSelectedWorkspaceFolder());
mProjectPanel.Sort();
mWorkspace.FixOptions();
mWorkspace.mHasChanged = true;
@ -2693,7 +2715,7 @@ namespace IDE
AddProjectToWorkspace(project, false);
if (addToUI)
mProjectPanel.InitProject(project);
mProjectPanel.InitProject(project, null);
}
}
if (!hadLoad)
@ -2977,6 +2999,8 @@ namespace IDE
{
using (mBeefConfig.mRegistry.mMonitor.Enter())
{
BeefConfig.RegistryEntry matchedEntry = null;
for (int regEntryIdx = mBeefConfig.mRegistry.mEntries.Count - 1; regEntryIdx >= 0; regEntryIdx--)
{
var regEntry = mBeefConfig.mRegistry.mEntries[regEntryIdx];
@ -2986,11 +3010,19 @@ namespace IDE
if (regEntry.mProjName == projectName)
{
useVerSpec = regEntry.mLocation;
verConfigDir = regEntry.mConfigFile.mConfigDir;
break FindLoop;
// Prioritize a lib file over a non-lib
if ((matchedEntry == null) ||
((!matchedEntry.mTargetType.IsLib) && (regEntry.mTargetType.IsLib)))
matchedEntry = regEntry;
}
}
if (matchedEntry != null)
{
useVerSpec = matchedEntry.mLocation;
verConfigDir = matchedEntry.mConfigFile.mConfigDir;
break FindLoop;
}
}
mBeefConfig.mRegistry.WaitFor();
}
@ -5429,6 +5461,20 @@ namespace IDE
sysMenu.Modify(null, null, null, true, checkVal ? 1 : 0);
}
public Menu AddMenuItem(Menu menu, StringView label, StringView command = default)
{
var command;
if (command.IsEmpty)
command = label;
String labelStr = scope String(label);
if (mCommands.mCommandMap.TryGetAlt(command, var matchKey, var ideCommand))
{
labelStr.Append("|");
ideCommand.ToString(labelStr);
}
return menu.AddItem(labelStr);
}
public bool AreTestsRunning()
{
return (mTestManager != null);
@ -5683,6 +5729,17 @@ namespace IDE
AddMenuItem(bookmarkMenu, "&Previous Bookmark", "Bookmark Prev");
AddMenuItem(bookmarkMenu, "&Clear Bookmarks", "Bookmark Clear");
var comptimeMenu = subMenu.AddMenuItem("Comptime");
var emitViewCompiler = comptimeMenu.AddMenuItem("Emit View Compiler");
var subItem = emitViewCompiler.AddMenuItem("Resolve", null,
new (menu) => { SetEmbedCompiler(.Resolve); } ,
new (menu) => { menu.SetCheckState((mSettings.mEditorSettings.mEmitCompiler == .Resolve) ? 1 : 0); },
null, true, (mSettings.mEditorSettings.mEmitCompiler == .Resolve) ? 1 : 0);
subItem = emitViewCompiler.AddMenuItem("Build", null,
new (menu) => { SetEmbedCompiler(.Build); } ,
new (menu) => { menu.SetCheckState((mSettings.mEditorSettings.mEmitCompiler == .Build) ? 1 : 0); },
null, true, (mSettings.mEditorSettings.mEmitCompiler == .Build) ? 1 : 0);
var advancedEditMenu = subMenu.AddMenuItem("Advanced");
AddMenuItem(advancedEditMenu, "Duplicate Line", "Duplicate Line");
AddMenuItem(advancedEditMenu, "Move Line Up", "Move Line Up");
@ -6285,6 +6342,11 @@ namespace IDE
let process = scope SpawnedProcess();
process.Start(procInfo).IgnoreError();
});
item = menu.AddItem("Show in Workspace Panel");
item.mOnMenuItemSelected.Add(new (menu) =>
{
sourceViewPanel.SyncWithWorkspacePanel();
});
item = menu.AddItem("Close");
item.mOnMenuItemSelected.Add(new (menu) =>
{
@ -7155,10 +7217,11 @@ namespace IDE
public SourceViewPanel ShowSourceFileLocation(String filePath, int showHotIdx, int refHotIdx, int line, int column, LocatorType hilitePosition, bool showTemp = false)
{
var useFilePath = filePath;
if (filePath.StartsWith("$Emit$"))
{
var compiler = mBfResolveCompiler;
if (compiler.IsPerformingBackgroundOperation())
if ((mBfBuildCompiler.IsPerformingBackgroundOperation()) || (mBfResolveCompiler.IsPerformingBackgroundOperation()))
{
DeleteAndNullify!(mDeferredShowSource);
mDeferredShowSource = new DeferredShowSource()
@ -7174,18 +7237,76 @@ namespace IDE
return null;
}
var itr = filePath.Split('$');
itr.GetNext();
itr.GetNext();
var typeName = itr.GetNext().Value;
String embedFilePath;
bool isViewValid = true;
StringView typeName;
int embedLine;
int embedLineChar;
//var compiler = (kindStr == "Emit") ? mBfBuildCompiler : mBfResolveCompiler;
compiler.mBfSystem.Lock(0);
var embedFilePath = compiler.GetEmitLocation(typeName, line, .. scope .(), var embedLine, var embedLineChar);
compiler.mBfSystem.Unlock();
if (filePath.StartsWith("$Emit$Resolve$"))
{
if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Resolve)
{
var itr = filePath.Split('$');
itr.GetNext();
itr.GetNext();
itr.GetNext();
typeName = itr.GetNext().Value;
mBfResolveCompiler.mBfSystem.Lock(0);
embedFilePath = mBfResolveCompiler.GetEmitLocation(typeName, line, .. scope:: .(), out embedLine, out embedLineChar, var embedHash);
mBfResolveCompiler.mBfSystem.Unlock();
useFilePath = scope:: $"$Emit${useFilePath.Substring("$Emit$Resolve$".Length)}";
}
else
isViewValid = false;
}
else if (filePath.StartsWith("$Emit$Build$"))
{
if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Build)
{
var itr = filePath.Split('$');
itr.GetNext();
itr.GetNext();
itr.GetNext();
typeName = itr.GetNext().Value;
mBfBuildCompiler.mBfSystem.Lock(0);
embedFilePath = mBfBuildCompiler.GetEmitLocation(typeName, line, .. scope:: .(), out embedLine, out embedLineChar, var embedHash);
mBfBuildCompiler.mBfSystem.Unlock();
useFilePath = scope:: $"$Emit${useFilePath.Substring("$Emit$Build$".Length)}";
}
else
isViewValid = false;
}
else
{
var itr = filePath.Split('$');
itr.GetNext();
itr.GetNext();
typeName = itr.GetNext().Value;
if (!embedFilePath.IsEmpty)
mBfBuildCompiler.mBfSystem.Lock(0);
embedFilePath = mBfBuildCompiler.GetEmitLocation(typeName, line, .. scope:: .(), out embedLine, out embedLineChar, var embedHash);
mBfBuildCompiler.mBfSystem.Unlock();
if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Resolve)
{
mBfResolveCompiler.mBfSystem.Lock(0);
mBfResolveCompiler.GetEmitLocation(typeName, line, scope .(), var resolveLine, var resolveLineChar, var resolveHash);
mBfResolveCompiler.mBfSystem.Unlock();
if ((resolveLine != embedLine) || (resolveLineChar != embedLineChar) || (embedHash != resolveHash))
{
isViewValid = false;
useFilePath = scope:: $"$Emit$Build${useFilePath.Substring("$Emit$".Length)}";
}
}
}
if ((isViewValid) && (!embedFilePath.IsEmpty))
{
var sourceViewPanel = ShowSourceFile(scope .(embedFilePath), null, showTemp ? SourceShowType.Temp : SourceShowType.ShowExisting).panel;
if (sourceViewPanel == null)
@ -7201,11 +7322,7 @@ namespace IDE
emitShowData.mColumn = (.)column;
DeleteAndNullify!(sourceViewPanel.[Friend]mQueuedEmitShowData);
sourceViewPanel.[Friend]mQueuedEmitShowData = emitShowData;
//sourceViewPanel.ShowHotFileIdx(showHotIdx);
sourceViewPanel.ShowFileLocation(refHotIdx, embedLine, embedLineChar, .None);
//sourceViewPanel.QueueFullRefresh(false);
//sourceViewPanel.mBackgroundDelay = 1; // Don't immediately perform the full classify
if (typeName.Contains('<'))
{
@ -7220,7 +7337,7 @@ namespace IDE
}
}
var (sourceViewPanel, tabButton) = ShowSourceFile(filePath, null, showTemp ? SourceShowType.Temp : SourceShowType.ShowExisting);
var (sourceViewPanel, tabButton) = ShowSourceFile(useFilePath, null, showTemp ? SourceShowType.Temp : SourceShowType.ShowExisting);
if (sourceViewPanel == null)
return null;
if (((filePath.StartsWith("$")) && (var svTabButton = tabButton as SourceViewTabButton)))
@ -14259,7 +14376,8 @@ namespace IDE
if (IDEApp.sApp.mSpellChecker != null)
IDEApp.sApp.mSpellChecker.CheckThreadDone();
if ((mDeferredShowSource != null) && (mBfResolveCompiler?.IsPerformingBackgroundOperation() == false))
if ((mDeferredShowSource != null) && (!mBfBuildCompiler.IsPerformingBackgroundOperation()) &&
(mBfResolveCompiler?.IsPerformingBackgroundOperation() != true))
{
var deferredShowSource = mDeferredShowSource;
mDeferredShowSource = null;

View file

@ -636,6 +636,38 @@ namespace IDE
label.Append('\x02');
}
}
static String sHexUpperChars = "0123456789ABCDEF";
public static void URLEncode(StringView inStr, String outStr)
{
for (var c in inStr)
{
if ((c.IsLetterOrDigit) || (c == '-') || (c == '_') || (c == '.') || (c == '~') || (c == '/'))
{
outStr.Append(c);
}
else
{
outStr.Append('%');
outStr.Append(sHexUpperChars[(.)c>>4]);
outStr.Append(sHexUpperChars[(.)c&0xF]);
}
}
}
public static void URLDecode(StringView inStr, String outStr)
{
for (int i < inStr.Length)
{
char8 c = inStr[i];
if ((c == '%') && (i < inStr.Length-2))
{
c = (.)int32.Parse(inStr.Substring(i+1, 2), .HexNumber).GetValueOrDefault();
i += 2;
}
outStr.Append(c);
}
}
}
}

View file

@ -979,6 +979,20 @@ namespace IDE
}
}
}
public bool IsLib
{
get
{
switch (this)
{
case BeefLib:
return true;
default:
return false;
}
}
}
}
public class WindowsOptions

View file

@ -304,6 +304,7 @@ namespace IDE
public Color mWorkspaceFailedText = 0xFFE04040;
public Color mWorkspaceManualIncludeText = 0xFFE0E0FF;
public Color mWorkspaceIgnoredText = 0xFF909090;
public Color mWorkspaceCutText = 0xFFC0B0B0;
public Color mCode = 0xFFFFFFFF;
public Color mKeyword = 0xFFE1AE9A;
@ -628,6 +629,12 @@ namespace IDE
Spaces
}
public enum CompilerKind
{
Resolve,
Build
}
public List<String> mFonts = new .() ~ DeleteContainerAndItems!(_);
public float mFontSize = 12;
public AutoCompleteShowKind mAutoCompleteShowKind = .PanelIfVisible;
@ -641,6 +648,7 @@ namespace IDE
public bool mHiliteCurrentLine = false;
public bool mLockEditing;
public LockWhileDebuggingKind mLockEditingWhenDebugging = .WhenNotHotSwappable;// Only applicable for
public CompilerKind mEmitCompiler;
// non-Beef sources
public bool mPerforceAutoCheckout = true;
public bool mSpellCheckEnabled = true;
@ -674,6 +682,7 @@ namespace IDE
sd.Add("HiliteCurrentLine", mHiliteCurrentLine);
sd.Add("LockEditing", mLockEditing);
sd.Add("LockEditingWhenDebugging", mLockEditingWhenDebugging);
sd.Add("EmitCompiler", mEmitCompiler);
sd.Add("PerforceAutoCheckout", mPerforceAutoCheckout);
sd.Add("SpellCheckEnabled", mSpellCheckEnabled);
sd.Add("ShowLineNumbers", mShowLineNumbers);
@ -710,6 +719,7 @@ namespace IDE
sd.Get("HiliteCurrentLine", ref mHiliteCurrentLine);
sd.Get("LockEditing", ref mLockEditing);
sd.Get("LockEditingWhenDebugging", ref mLockEditingWhenDebugging);
sd.Get("EmitCompiler", ref mEmitCompiler);
sd.Get("PerforceAutoCheckout", ref mPerforceAutoCheckout);
sd.Get("SpellCheckEnabled", ref mSpellCheckEnabled);
sd.Get("ShowLineNumbers", ref mShowLineNumbers);
@ -944,7 +954,7 @@ namespace IDE
curCmdMap = (*valuePtr) as CommandMap;
if (curCmdMap == null)
{
curCmdMap.FailValues.Add(ideCommand);
gApp.OutputLineSmart("ERROR: The same key is bound for '{0}' and as part of a key chord", entry.mCommand);
break;
}
}

View file

@ -1017,6 +1017,72 @@ namespace IDE.ui
if (cursorSection >= textSections.Count - 1)
cursorSection = textSections.Count - 2;
if ((cursorSection >= 0) && (cursorSection < mAutoComplete.mInvokeSrcPositions.Count))
{
var argText = mAutoComplete.mTargetEditWidget.mEditWidgetContent.ExtractString(mAutoComplete.mInvokeSrcPositions[cursorSection - 1],
mAutoComplete.mInvokeSrcPositions[cursorSection] - mAutoComplete.mInvokeSrcPositions[cursorSection - 1], .. scope .());
int colonPos = argText.IndexOf(':');
if (colonPos != -1)
{
do
{
bool foundSep = false;
int nameStart = -1;
for (int i = colonPos - 1; i >= 0; i--)
{
char8 c = argText[i];
if (nameStart == -1)
{
if ((c != '_') && (!c.IsLetterOrDigit))
nameStart = i + 1;
}
else
{
if (!c.IsWhiteSpace)
{
if ((!foundSep) &&
((c == ',') || (c == '(')))
foundSep = true;
else
break;
}
}
}
if (nameStart == -1)
break;
var argParamName = argText.Substring(nameStart, colonPos - nameStart);
for (int checkSectionIdx = 1; checkSectionIdx < textSections.Count; checkSectionIdx++)
{
var sectionStr = textSections[checkSectionIdx];
var checkParamName = sectionStr;
if (checkParamName.EndsWith(','))
checkParamName.RemoveFromEnd(1);
for (int checkIdx = checkParamName.Length - 1; checkIdx >= 0; checkIdx--)
{
char8 c = checkParamName[checkIdx];
if (c.IsWhiteSpace)
{
checkParamName.RemoveFromStart(checkIdx + 1);
break;
}
}
if (checkParamName == argParamName)
{
cursorSection = checkSectionIdx;
break;
}
}
}
}
}
float paramX = 0;
for (int sectionIdx = 0; sectionIdx < textSections.Count; sectionIdx++)
{

View file

@ -552,7 +552,7 @@ namespace IDE.ui
return base.Deserialize(data);
}
public void QueueLine(String text)
public void AddPendingLine(String text)
{
mCurLineNum++;
using (mMonitor.Enter())
@ -591,7 +591,17 @@ namespace IDE.ui
String outStr = scope String();
outStr.AppendF("{0}({1}):{2}", fileEditData.mFilePath, line + 1, lineStr);
gApp.mFindResultsPanel.QueueLine(outStr);
gApp.mFindResultsPanel.AddPendingLine(outStr);
}
public void QueueLine(String text)
{
using (mMonitor.Enter())
{
QueuedEntry entry = new .();
entry.mText = new .(text);
mQueuedEntries.Add(entry);
}
}
public void QueueLine(String fileName, int32 line, int32 column, String text)
@ -641,7 +651,10 @@ namespace IDE.ui
while (!mQueuedEntries.IsEmpty)
{
var entry = mQueuedEntries.PopFront();
QueueLine(gApp.GetEditData(entry.mFileName, true, false), entry.mLine, entry.mColumn, entry.mText);
if (entry.mFileName == null)
AddPendingLine(entry.mText);
else
QueueLine(gApp.GetEditData(entry.mFileName, true, false), entry.mLine, entry.mColumn, entry.mText);
delete entry;
}

View file

@ -406,14 +406,12 @@ namespace IDE.ui
void HandleMouseWheel(MouseEvent evt)
{
if (mChildWidgets.Count == 0)
return;
var lastListView = mChildWidgets[mChildWidgets.Count - 1] as HoverListView;
if ((lastListView != null) && (lastListView.mVertScrollbar != null))
return;
if (mListViews.Count > 1)
{
return;
}
if (evt.mSender != mWidgetWindow)
{
var widgetWindow = evt.mSender as BFWindow;
while (widgetWindow != null)
@ -423,6 +421,7 @@ namespace IDE.ui
widgetWindow = widgetWindow.mParent;
}
}
EditWidget editWidget = mEditWidget;
if (var sourceViewPanel = mTextPanel as SourceViewPanel)
editWidget = sourceViewPanel.mEditWidget;

View file

@ -16,9 +16,11 @@ namespace IDE.ui
public String mName ~ delete _;
public String mPath ~ delete _;
public VerSpecRecord mVersion;
public Project.TargetType mTargetType;
}
protected IDEListView mProjectList;
DarkComboBox mKindCombo;
EditWidget mEditWidget;
bool mFilterChanged;
List<InstalledProject> mInstalledProjectList = new .() ~ DeleteContainerAndItems!(_);
@ -58,6 +60,21 @@ namespace IDE.ui
mEditWidget.mOnKeyDown.Add(new => EditKeyDownHandler);
mEditWidget.mOnContentChanged.Add(new (evt) => { mFilterChanged = true; });
mKindCombo = new DarkComboBox();
mKindCombo.Label = "Libraries";
mKindCombo.mPopulateMenuAction.Add(new (menu) =>
{
for (var kind in String[?]("All", "Libraries"))
{
menu.AddItem(kind).mOnMenuItemSelected.Add(new (menu) =>
{
mFilterChanged = true;
mKindCombo.Label = kind;
});
}
});
AddWidget(mKindCombo);
FindProjects();
}
@ -78,6 +95,7 @@ namespace IDE.ui
installedProject.mPath.Append("BeefProj.toml");
default:
}
installedProject.mTargetType = registryEntry.mTargetType;
mInstalledProjectList.Add(installedProject);
}
}
@ -128,9 +146,14 @@ namespace IDE.ui
mEditWidget.GetText(filterString);
filterString.Trim();
bool onlyLibs = mKindCombo.Label == "Libraries";
mFilteredList.Clear();
for (var installedProject in mInstalledProjectList)
{
if ((onlyLibs) && (!installedProject.mTargetType.IsLib))
continue;
if ((!filterString.IsEmpty) && (installedProject.mName.IndexOf(filterString, true) == -1))
continue;
@ -138,7 +161,7 @@ namespace IDE.ui
listViewItem.Label = installedProject.mName;
var subListViewItem = listViewItem.CreateSubItem(1);
subListViewItem.Label = installedProject.mPath;
subListViewItem.Label = Path.GetDirectoryPath(installedProject.mPath, .. scope .());
mFilteredList.Add(installedProject);
}
@ -180,7 +203,7 @@ namespace IDE.ui
VerSpec verSpec = .SemVer(new .("*"));
defer verSpec.Dispose();
let project = gApp.mProjectPanel.ImportProject(entry.mPath, verSpec);
let project = gApp.mProjectPanel.ImportProject(entry.mPath, null, verSpec);
if (project == null)
{
return;
@ -223,6 +246,7 @@ namespace IDE.ui
float insetSize = GS!(6);
mProjectList.Resize(insetSize, insetSize, mWidth - insetSize - insetSize, mHeight - GS!(66));
mEditWidget.Resize(insetSize, mProjectList.mY + mProjectList.mHeight + insetSize, mWidth - insetSize - insetSize, GS!(22));
mKindCombo.Resize(insetSize, mHeight - GS!(26), Math.Min(GS!(160), mDefaultButton.mX - GS!(6)), GS!(26));
}
public override void CalcSize()

View file

@ -61,6 +61,17 @@ namespace IDE.ui
else if (projectItem.mIncludeKind == .Ignore)
color = Color.Mult(color, gApp.mSettings.mUISettings.mColors.mWorkspaceIgnoredText);
if (let projectFileItem = projectItem as ProjectFileItem)
{
if (projectPanel.mClipboardCutQueued != null)
{
var path = projectFileItem.mProject.GetProjectFullPath(projectFileItem.mPath, .. scope .());
IDEUtils.MakeComparableFilePath(path);
if (projectPanel.mClipboardCutQueued.Contains(path))
color = Color.Mult(color, gApp.mSettings.mUISettings.mColors.mWorkspaceCutText);
}
}
if (let projectSource = projectItem as ProjectSource)
{
if (projectSource.mLoadFailed)
@ -146,6 +157,7 @@ namespace IDE.ui
public bool mShowIgnored = true;
public bool mSortDirty;
public bool mWantsRehup;
public HashSet<String> mClipboardCutQueued ~ DeleteContainerAndItems!(_);
public this()
{
@ -518,10 +530,22 @@ namespace IDE.ui
}
}
public void InitProject(Project project)
{
public void InitProject(Project project, WorkspaceFolder workspaceFolder)
{
var projectListViewItem = InitProjectItem(project.mRootFolder);
projectListViewItem.mRefObject = project;
if (workspaceFolder != null)
{
let root = mListView.GetRoot();
root.RemoveChildItem(projectListViewItem, false);
workspaceFolder.mListView.MakeParent();
workspaceFolder.mListView.AddChild(projectListViewItem);
workspaceFolder.mListView.Open(true);
mProjectToWorkspaceFolderMap[project.mRootFolder] = workspaceFolder;
workspaceFolder.mProjects.Add(project);
QueueSortItem(workspaceFolder.mListView);
}
}
public void RebuildUI()
@ -564,7 +588,7 @@ namespace IDE.ui
mProjectToWorkspaceFolderMap.Clear();
for (var project in IDEApp.sApp.mWorkspace.mProjects)
InitProject(project);
InitProject(project, null);
let root = mListView.GetRoot();
@ -1489,6 +1513,14 @@ namespace IDE.ui
#endif
}
public WorkspaceFolder GetSelectedWorkspaceFolder()
{
ListViewItem selectedItem = mListView.GetRoot().FindFirstSelectedItem();
if (mListViewToWorkspaceFolderMap.TryGetValue(selectedItem, let folder))
return folder;
return null;
}
ListViewItem GetSelectedParentItem()
{
ListViewItem selectedItem = mListView.GetRoot().FindFirstSelectedItem();
@ -1764,33 +1796,59 @@ namespace IDE.ui
let root = mListView.GetRoot();
List<ListViewItem> itemsToMove = scope .();
List<WorkspaceFolder> foldersToDelete = scope .();
root.WithSelectedItems(scope [&] (selectedItem) => {
if (mListViewToWorkspaceFolderMap.GetValue(selectedItem) case .Ok(let folder))
{
foldersToDelete.Add(folder);
mListViewToWorkspaceFolderMap.Remove(folder.mListView);
selectedItem.WithItems(scope [&] (item) => {
if (mListViewToProjectMap.GetValue(item) case .Ok(let project))
{
if (project.mParentFolder == null)
itemsToMove.Add(item);
}
else if (mListViewToWorkspaceFolderMap.GetValue(item) case .Ok(let itemFolder))
{
foldersToDelete.Add(itemFolder);
mListViewToWorkspaceFolderMap.Remove(itemFolder.mListView);
}
});
}
});
for (let projectListViewItem in itemsToMove)
for (let listViewItem in itemsToMove)
{
projectListViewItem.mParentItem.RemoveChildItem(projectListViewItem, false);
root.AddChildAtIndex(1, projectListViewItem);
if (mListViewToProjectMap.TryGetValue(projectListViewItem, let projectItem))
listViewItem.mParentItem.RemoveChildItem(listViewItem, false);
root.AddChildAtIndex(1, listViewItem);
if (mListViewToProjectMap.TryGetValue(listViewItem, let projectItem))
mProjectToWorkspaceFolderMap.Remove(projectItem);
}
for (let folder in foldersToDelete)
bool HasDeletedParent(WorkspaceFolder folder)
{
WorkspaceFolder parent = folder;
repeat
{
parent = parent.mParent;
if (foldersToDelete.Contains(parent))
return true;
}
while (parent != null);
return false;
}
for (let folder in foldersToDelete)
{
let folderItem = folder.mListView;
mListViewToWorkspaceFolderMap.Remove(folderItem);
folderItem.mParentItem.RemoveChildItem(folderItem);
gApp.mWorkspace.mWorkspaceFolders.Remove(folder);
if (!HasDeletedParent(folder))
{
let folderItem = folder.mListView;
folderItem.mParentItem.RemoveChildItem(folderItem);
}
gApp.mWorkspace.mWorkspaceFolders.Remove(folder);
delete folder;
}
@ -2004,6 +2062,307 @@ namespace IDE.ui
}
}
void CopyToClipboard()
{
String clipData = scope .();
mListView.GetRoot().WithSelectedItems(scope (selectedItem) =>
{
if (mListViewToProjectMap.GetValue(selectedItem) case .Ok(var sourceProjectItem))
{
String path = scope .();
if (var projectFileItem = sourceProjectItem as ProjectFileItem)
{
sourceProjectItem.mProject.GetProjectFullPath(projectFileItem.mPath, path);
path.Replace('\\', '/');
if (!clipData.IsEmpty)
clipData.Append("\n");
clipData.Append("file:///");
IDEUtils.URLEncode(path, clipData);
}
}
});
if (!clipData.IsEmpty)
gApp.SetClipboardData("code/file-list", clipData.Ptr, (.)clipData.Length, true);
}
void CutToClipboard()
{
DeleteContainerAndItems!(mClipboardCutQueued);
mClipboardCutQueued = null;
CopyToClipboard();
mClipboardCutQueued = new .();
ValidateCutClipboard();
}
void ValidateCutClipboard()
{
if (mClipboardCutQueued == null)
return;
void* data = gApp.GetClipboardData("code/file-list", var size, 0);
if (size == -1)
return;
ClearAndDeleteItems!(mClipboardCutQueued);
if (data != null)
{
StringView sv = .((.)data, size);
for (var line in sv.Split('\n'))
{
var uri = IDEUtils.URLDecode(line, .. scope .());
if (uri.StartsWith("file:///"))
{
var srcPath = scope String()..Append(uri.Substring("file:///".Length));
IDEUtils.MakeComparableFilePath(srcPath);
if (mClipboardCutQueued.TryAddAlt(srcPath, var entryPtr))
*entryPtr = new String(srcPath);
}
}
}
if (mClipboardCutQueued.IsEmpty)
DeleteAndNullify!(mClipboardCutQueued);
}
void PasteFromClipboard()
{
ValidateCutClipboard();
var projectItem = GetSelectedProjectItem();
var projectFolder = projectItem as ProjectFolder;
if (projectFolder == null)
projectFolder = projectItem.mParentFolder;
if (projectFolder == null)
return;
var folderPath = projectFolder.GetFullImportPath(.. scope .());
void* data = gApp.GetClipboardData("code/file-list", var size);
if (data == null)
return;
bool isCut = mClipboardCutQueued != null;
Dictionary<String, SourceViewPanel> sourceViewPanelMap = null;
List<(SourceViewPanel sourceViewPanel, String fromPath, String toPath)> moveList = null;
HashSet<String> foundDirs = scope .();
if (isCut)
{
sourceViewPanelMap = scope:: .();
gApp.WithSourceViewPanels(scope (sourceViewPanel) =>
{
if (sourceViewPanel.mFilePath === null)
return;
if (sourceViewPanel.mProjectSource == null)
return;
var path = scope String()..Append(sourceViewPanel.mFilePath);
IDEUtils.MakeComparableFilePath(path);
if (sourceViewPanelMap.TryAdd(path, var keyPtr, var valuePtr))
{
*keyPtr = new String(path);
*valuePtr = sourceViewPanel;
}
});
moveList = scope:: .();
}
defer
{
DeleteContainerAndItems!(mClipboardCutQueued);
mClipboardCutQueued = null;
if (sourceViewPanelMap != null)
{
for (var key in sourceViewPanelMap.Keys)
delete key;
}
if (moveList != null)
{
for (var val in moveList)
{
delete val.fromPath;
delete val.toPath;
}
}
ClearAndDeleteItems!(foundDirs);
}
void QueueDirectoryMove(StringView fromDir, StringView toDir)
{
var searchStr = scope String();
searchStr.Append(fromDir);
searchStr.Append("/*");
for (var dirEntry in Directory.Enumerate(searchStr, .Directories | .Files))
{
var fromChildPath = dirEntry.GetFilePath(.. scope .());
String toChildPath = scope String()..Append(toDir);
toChildPath.Append(Path.DirectorySeparatorChar);
dirEntry.GetFileName(toChildPath);
if (dirEntry.IsDirectory)
{
QueueDirectoryMove(fromChildPath, toChildPath);
continue;
}
var cmpPath = IDEUtils.MakeComparableFilePath(.. scope String()..Append(fromChildPath));
if (sourceViewPanelMap.TryGet(cmpPath, var matchKey, var sourceViewPanel))
{
moveList.Add((sourceViewPanel, new String(fromChildPath), new String(toChildPath)));
}
}
}
Result<void> CopyDirectory(StringView fromDir, StringView toDir)
{
if (Directory.CreateDirectory(toDir) case .Err)
{
gApp.Fail(scope $"Failed to create directory '{toDir}'");
return .Err;
}
var searchStr = scope String();
searchStr.Append(fromDir);
searchStr.Append("/*");
for (var dirEntry in Directory.Enumerate(searchStr, .Directories | .Files))
{
var fromChildPath = dirEntry.GetFilePath(.. scope .());
String toChildPath = scope String()..Append(toDir);
toChildPath.Append("/");
dirEntry.GetFileName(toChildPath);
if (dirEntry.IsDirectory)
{
CopyDirectory(fromChildPath, toChildPath);
continue;
}
if (File.Copy(fromChildPath, toChildPath) case .Err)
{
gApp.Fail(scope $"Failed to copy '{fromChildPath}' to '{toChildPath}'");
return .Err;
}
}
return .Ok;
}
StringView sv = .((.)data, size);
SrcLoop: for (var line in sv.Split('\n'))
{
var uri = IDEUtils.URLDecode(line, .. scope .());
if (uri.StartsWith("file:///"))
{
var srcPath = scope String()..Append(uri.Substring("file:///".Length));
for (int i < 100)
{
var fileName = Path.GetFileNameWithoutExtension(srcPath, .. scope .());
var destPath = scope String();
destPath.Append(folderPath);
destPath.Append("/");
destPath.Append(fileName);
if ((i > 0) && (!fileName.Contains(" - Copy")))
destPath.Append(" - Copy");
if (i > 1)
destPath.AppendF($" ({i})");
Path.GetExtension(srcPath, destPath);
IDEUtils.FixFilePath(srcPath);
IDEUtils.FixFilePath(destPath);
if ((isCut) && (Path.Equals(srcPath, destPath)))
break;
if (File.Exists(destPath))
continue;
if (Directory.Exists(destPath))
continue;
if (Directory.Exists(srcPath))
{
if (foundDirs.TryAdd(srcPath, var entryPtr))
*entryPtr = new String(srcPath);
if (isCut)
{
QueueDirectoryMove(srcPath, destPath);
if (Directory.Move(srcPath, destPath) case .Err)
{
gApp.Fail(scope $"Failed to move '{srcPath}' to '{destPath}'");
return;
}
for (var val in moveList)
{
gApp.FileRenamed(val.sourceViewPanel.mProjectSource, val.fromPath, val.toPath);
}
}
else
{
if (CopyDirectory(srcPath, destPath) case .Err)
{
return;
}
}
}
else
{
var checkPath = scope String()..Append(srcPath);
while (true)
{
String checkDir = scope .();
if (Path.GetDirectoryPath(checkPath, checkDir) case .Err)
break;
if (foundDirs.Contains(checkDir))
{
// Already handled
continue SrcLoop;
}
checkPath.Set(checkDir);
}
if (isCut)
{
if (File.Move(srcPath, destPath) case .Err)
{
gApp.Fail(scope $"Failed to move '{srcPath}' to '{destPath}'");
return;
}
var cmpPath = IDEUtils.MakeComparableFilePath(.. scope String()..Append(srcPath));
if (sourceViewPanelMap.TryGet(cmpPath, var matchKey, var sourceViewPanel))
{
gApp.FileRenamed(sourceViewPanel.mProjectSource, srcPath, destPath);
}
}
else
{
if (File.Copy(srcPath, destPath) case .Err)
{
gApp.Fail(scope $"Failed to copy '{srcPath}' to '{destPath}'");
return;
}
}
}
break;
}
}
}
}
public override void KeyDown(KeyCode keyCode, bool isRepeat)
{
mListView.KeyDown(keyCode, isRepeat);
@ -2015,8 +2374,25 @@ namespace IDE.ui
}
base.KeyDown(keyCode, isRepeat);
if (keyCode == KeyCode.Delete)
RemoveSelectedItems();
if (mWidgetWindow.GetKeyFlags() == .Ctrl)
{
switch (keyCode)
{
case (.)'C':
CopyToClipboard();
case (.)'X':
CutToClipboard();
case (.)'V':
PasteFromClipboard();
default:
}
}
else if (mWidgetWindow.GetKeyFlags() == .None)
{
if (keyCode == KeyCode.Delete)
RemoveSelectedItems();
}
}
void ItemClicked(MouseEvent theEvent)
@ -2374,7 +2750,7 @@ namespace IDE.ui
return true;
}
public void AddWorkspaceFolder(ProjectListViewItem parentListViewItem)
public WorkspaceFolder AddWorkspaceFolder(ProjectListViewItem parentListViewItem)
{
ProjectListViewItem listViewItem;
listViewItem = (ProjectListViewItem)parentListViewItem.CreateChildItem();
@ -2406,10 +2782,11 @@ namespace IDE.ui
mListView.GetRoot().SelectItemExclusively(listViewItem);
EditListViewItem(listViewItem);
gApp.mWorkspace.SetChanged();
return folder;
}
public Project ImportProject(String filePath, VerSpec verSpec = .None)
public Project ImportProject(String filePath, WorkspaceFolder workspaceFolder, VerSpec verSpec = .None)
{
if (gApp.IsCompiling)
return null;
@ -2456,7 +2833,7 @@ namespace IDE.ui
gApp.AddNewProjectToWorkspace(proj, verSpec);
gApp.mWorkspace.FixOptions();
gApp.[Friend]FlushDeferredLoadProjects(true);
InitProject(proj);
InitProject(proj, workspaceFolder);
if (failed)
{
gApp.Fail(StackStringFormat!("Failed to load project: {0}", filePath));
@ -2502,6 +2879,8 @@ namespace IDE.ui
initialDir.Concat(Path.DirectorySeparatorChar, "Samples");
}
var workspaceFolder = GetSelectedWorkspaceFolder();
fileDialog.InitialDirectory = initialDir;
fileDialog.ValidateNames = true;
fileDialog.DefaultExt = ".toml";
@ -2511,7 +2890,7 @@ namespace IDE.ui
{
for (String origProjFilePath in fileDialog.FileNames)
{
ImportProject(origProjFilePath);
ImportProject(origProjFilePath, workspaceFolder);
}
}
#endif
@ -2616,6 +2995,43 @@ namespace IDE.ui
{
Menu anItem;
void AddWorkspaceMenuItems()
{
anItem = menu.AddItem("Add New Project...");
anItem.mOnMenuItemSelected.Add(new (item) => {
AddNewProject();
});
if (gApp.IsCompiling)
anItem.SetDisabled(true);
anItem = menu.AddItem("Add Existing Project...");
anItem.mOnMenuItemSelected.Add(new (item) => {
mImportProjectDeferred = true;
});
if (gApp.IsCompiling)
anItem.SetDisabled(true);
anItem = menu.AddItem("Add From Installed...");
anItem.mOnMenuItemSelected.Add(new (item) => {
mImportInstalledDeferred = true;
});
if (gApp.IsCompiling)
anItem.SetDisabled(true);
anItem = menu.AddItem("New Folder");
anItem.mOnMenuItemSelected.Add(new (item) => {
var workspaceFolder = GetSelectedWorkspaceFolder();
if (workspaceFolder != null)
{
let newFolder = AddWorkspaceFolder(workspaceFolder.mListView);
newFolder.mParent = workspaceFolder;
}
else
{
AddWorkspaceFolder((ProjectListViewItem)mListView.GetRoot());
}
});
}
if (mListViewToWorkspaceFolderMap.TryGetValue(focusedItem, let folder))
{
anItem = menu.AddItem("Remove");
@ -2623,8 +3039,9 @@ namespace IDE.ui
anItem = menu.AddItem("Rename");
anItem.mOnMenuItemSelected.Add(new (item) => { EditListViewItem(focusedItem); });
menu.AddItem();
anItem = menu.AddItem("New Folder");
anItem.mOnMenuItemSelected.Add(new (item) => { AddWorkspaceFolder(folder.mListView); });
AddWorkspaceMenuItems();
handled = true;
}
else if (gApp.mWorkspace.IsInitialized)
@ -2632,23 +3049,7 @@ namespace IDE.ui
AddOpenContainingFolder();
menu.AddItem();
anItem = menu.AddItem("Add New Project...");
anItem.mOnMenuItemSelected.Add(new (item) => { AddNewProject(); });
if (gApp.IsCompiling)
anItem.SetDisabled(true);
anItem = menu.AddItem("Add Existing Project...");
anItem.mOnMenuItemSelected.Add(new (item) => { mImportProjectDeferred = true; });
if (gApp.IsCompiling)
anItem.SetDisabled(true);
anItem = menu.AddItem("Add From Installed...");
anItem.mOnMenuItemSelected.Add(new (item) => { mImportInstalledDeferred = true; });
if (gApp.IsCompiling)
anItem.SetDisabled(true);
anItem = menu.AddItem("New Folder");
anItem.mOnMenuItemSelected.Add(new (item) => { AddWorkspaceFolder((ProjectListViewItem)mListView.GetRoot()); });
AddWorkspaceMenuItems();
menu.AddItem();
anItem = menu.AddItem("Properties...");
anItem.mOnMenuItemSelected.Add(new (item) => { ShowWorkspaceProperties(); });
@ -2717,7 +3118,7 @@ namespace IDE.ui
});
}
item = menu.AddItem("Remove...");
item = menu.AddItem("Remove...|Del");
if (gApp.IsCompiling)
item.SetDisabled(true);
item.mOnMenuItemSelected.Add(new (item) =>
@ -2725,7 +3126,7 @@ namespace IDE.ui
RemoveSelectedItems();
});
item = menu.AddItem("Rename");
item = gApp.AddMenuItem(menu, "Rename", "Rename Item");
if (gApp.IsCompiling)
item.SetDisabled(true);
item.mOnMenuItemSelected.Add(new (item) =>
@ -2769,13 +3170,13 @@ namespace IDE.ui
if ((projectItem != null) && (!isProject))
{
item = menu.AddItem("Remove ...");
item = menu.AddItem("Remove ...|Del");
item.mOnMenuItemSelected.Add(new (item) =>
{
RemoveSelectedItems();
});
item = menu.AddItem("Rename");
item = gApp.AddMenuItem(menu, "Rename", "Rename Item");
item.mOnMenuItemSelected.Add(new (item) =>
{
var projectItem = GetSelectedProjectItem();
@ -2926,6 +3327,14 @@ namespace IDE.ui
if (!isFailedLoad)
{
item = menu.AddItem("Copy|Ctrl+C");
item.mOnMenuItemSelected.Add(new (item) => CopyToClipboard());
item = menu.AddItem("Cut|Ctrl+X");
item.mOnMenuItemSelected.Add(new (item) => CopyToClipboard());
item = menu.AddItem("Paste|Ctrl+V");
item.mOnMenuItemSelected.Add(new (item) => CopyToClipboard());
menu.AddItem();
item = menu.AddItem("New Folder");
item.mOnMenuItemSelected.Add(new (item) =>
{
@ -3098,6 +3507,8 @@ namespace IDE.ui
mImportInstalledDeferred = false;
ImportInstalledProject();
}
ValidateCutClipboard();
}
public override void Resize(float x, float y, float width, float height)
@ -3114,3 +3525,5 @@ namespace IDE.ui
}
}
///////////////////////

View file

@ -244,7 +244,12 @@ namespace IDE.ui
if (mKind == .GoToDefinition)
{
mSourceViewPanel.RecordHistoryLocation();
var sourceViewPanel = gApp.ShowSourceFileLocation(scope .(filePath), -1, -1, line, lineChar, LocatorType.Smart, true);
var usePath = scope String(filePath);
if (usePath.StartsWith("$Emit$"))
usePath.Insert("$Emit$".Length, "Resolve$");
var sourceViewPanel = gApp.ShowSourceFileLocation(usePath, -1, -1, line, lineChar, LocatorType.Smart, true);
sourceViewPanel.RecordHistoryLocation(true);
Close();
return;

View file

@ -221,6 +221,30 @@ namespace IDE.ui
}
}
// Do chord prefix search
for (var propEntries in mPropPage.mPropEntries.Values)
{
var propEntry = propEntries[0];
let keyEntry = (KeyEntry)propEntry.mTarget;
let origKeys = propEntry.mCurValue.Get<List<KeyState>>();
var keys = scope List<KeyState>(origKeys.GetEnumerator());
while (keys.Count > 1)
{
keys.PopBack();
let keyEntryStr = scope String();
KeyState.ToString(keys, keyEntryStr);
keyEntryStr.Append(" ");
CommandContextToString(keyEntry.mContextFlags, keyEntryStr);
if (mappedEntries.TryGet(keyEntryStr, var keyPtr, var valuePtr))
{
let other = valuePtr;
other.mHasConflict = true;
keyEntry.mHasConflict = true;
}
}
}
for (let keyEntryStr in mappedEntries.Keys)
delete keyEntryStr;

View file

@ -14,6 +14,8 @@ using IDE.Debugger;
using IDE.Compiler;
using Beefy.geom;
using Beefy.events;
using System.Security.Cryptography;
using System.IO;
namespace IDE.ui
{
@ -224,7 +226,7 @@ namespace IDE.ui
{
mTypeName = new .(emitEmbed.mTypeName);
mEmitEmbed = emitEmbed;
mSourceViewPanel = new SourceViewPanel((emitEmbed.mEmitKind == .Method) ? .Method : .Type);
mSourceViewPanel = new SourceViewPanel((emitEmbed.mEmitKind == .Emit_Method) ? .Method : .Type);
mSourceViewPanel.mEmbedParent = mEmitEmbed.mEditWidgetContent.mSourceViewPanel;
var emitPath = scope $"$Emit${emitEmbed.mTypeName}";
@ -382,7 +384,7 @@ namespace IDE.ui
}
mAwaitingLoad = false;
if (!mEmitRemoved)
if ((!mEmitRemoved) && (gApp.mSettings.mEditorSettings.mEmitCompiler == .Resolve))
{
for (var explicitTypeName in mEmitEmbed.mEditWidgetContent.mSourceViewPanel.[Friend]mExplicitEmitTypes)
{
@ -397,6 +399,9 @@ namespace IDE.ui
if ((mAwaitingLoad) && (gApp.mUpdateCnt % 4 == 0))
MarkDirty();
if (mSourceViewPanel.HasFocus())
mEmitEmbed.mEditWidgetContent.mEmbedSelected = mEmitEmbed;
}
public void GetGenericTypes()
@ -516,6 +521,10 @@ namespace IDE.ui
public int32 mEndLine;
public View mView;
public this()
{
}
public ~this()
{
if (mView != null)
@ -525,17 +534,29 @@ namespace IDE.ui
}
}
public bool IsSelected => mEditWidgetContent.mEmbedSelected == this;
public float LabelWidth = GS!(42);
public override float GetWidth(bool hideLine)
{
return GS!(42);
return IsSelected ? GS!(60) : LabelWidth;
}
public override void Draw(Graphics g, Rect rect, bool hideLine)
{
var rect;
rect.mWidth = LabelWidth;
if (rect.mHeight >= DarkTheme.sDarkTheme.mSmallBoldFont.GetLineSpacing())
g.SetFont(DarkTheme.sDarkTheme.mSmallBoldFont);
using (g.PushColor(0x80707070))
uint32 fillColor = 0x80707070;
if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Build)
{
fillColor = 0x805050E0;
}
using (g.PushColor(fillColor))
{
g.FillRect(rect.mX + 1, rect.mY + 1, rect.mWidth - 2, rect.mHeight - 2);
}
@ -558,6 +579,40 @@ namespace IDE.ui
var summaryString = "Emit";
g.DrawString(summaryString, rect.mX, rect.mY + (int)((rect.mHeight - g.mFont.GetLineSpacing()) * 0.5f), .Centered, rect.mWidth);
if (IsSelected)
{
g.Draw(DarkTheme.sDarkTheme.GetImage(.DropMenuButton), rect.Right, rect.Top);
}
}
public override void MouseDown(Rect rect, float x, float y, int btn, int btnCount)
{
base.MouseDown(rect, x, y, btn, btnCount);
if (x >= rect.mX + LabelWidth)
ShowMenu(x, y);
}
public void ShowMenu(float x, float y)
{
Menu menuItem;
Menu menu = new Menu();
menuItem = menu.AddItem("Compiler");
var subItem = menuItem.AddItem("Resolve");
if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Resolve)
subItem.mIconImage = DarkTheme.sDarkTheme.GetImage(.Check);
subItem.mOnMenuItemSelected.Add(new (menu) => { gApp.SetEmbedCompiler(.Resolve); });
subItem = menuItem.AddItem("Build");
if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Build)
subItem.mIconImage = DarkTheme.sDarkTheme.GetImage(.Check);
subItem.mOnMenuItemSelected.Add(new (menu) => { gApp.SetEmbedCompiler(.Build); });
MenuWidget menuWidget = DarkTheme.sDarkTheme.CreateMenuWidget(menu);
menuWidget.Init(mEditWidgetContent, x, y);
}
}
@ -575,10 +630,11 @@ namespace IDE.ui
case UsingNamespaces = 'U';
case Unknown = '?';
case HasUncertainEmits = '~';
case Emit = 'e';
case Emit_Type = 't';
case Emit_Method = 'm';
case EmitAddType = '+';
public bool IsEmit => (this == .Emit);
public bool IsEmit => (this == .Emit_Type) || (this == .Emit_Method);
}
public Kind mKind;
@ -602,6 +658,8 @@ namespace IDE.ui
public int32 mParseRevision;
public int32 mTextRevision;
public bool mDeleted;
public bool DefaultOpen => mKind != .Region;
}
public struct EmitData
@ -614,6 +672,7 @@ namespace IDE.ui
public bool mOnlyInResolveAll;
public bool mIncludedInClassify;
public bool mIncludedInResolveAll;
public bool mIncludedInBuild;
public int32 mAnchorId;
}
@ -757,6 +816,8 @@ namespace IDE.ui
public int32 mCollapseTextVersionId;
public bool mCollapseNeedsUpdate;
public bool mCollapseNoCheckOpen;
public bool mCollapseDBDirty;
public bool mCollapseAwaitingDB = true;
public List<PersistentTextPosition> PersistentTextPositions
{
@ -1784,7 +1845,19 @@ namespace IDE.ui
int line;
int lineChar;
GetCursorLineChar(out line, out lineChar);
return IDEApp.sApp.mHistoryManager.CreateHistory(mSourceViewPanel, mSourceViewPanel.mFilePath, line, lineChar, ignoreIfClose);
String useFilePath = mSourceViewPanel.mFilePath;
if ((mSourceViewPanel.mFilePath.StartsWith("$Emit$")) &&
(!mSourceViewPanel.mFilePath.StartsWith("$Emit$Build$")) &&
(!mSourceViewPanel.mFilePath.StartsWith("$Emit$Resolve$")))
{
if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Resolve)
useFilePath = scope:: String("$Emit$Resolve$")..Append(mSourceViewPanel.mFilePath.Substring("$Emit$".Length));
else
useFilePath = scope:: String("$Emit$Build$")..Append(mSourceViewPanel.mFilePath.Substring("$Emit$".Length));
}
return IDEApp.sApp.mHistoryManager.CreateHistory(mSourceViewPanel, useFilePath, line, lineChar, ignoreIfClose);
}
return null;
}
@ -3901,7 +3974,7 @@ namespace IDE.ui
prevChar = mData.mText[cursorTextPos - 1].mChar;
}
if (((keyChar == '\n') || (keyChar == '\r')) && (mIsMultiline) && (!CheckReadOnly()))
if (((keyChar == '\n') || (keyChar == '\r')) && (!HasSelection()) && (mIsMultiline) && (!CheckReadOnly()))
{
UndoBatchStart undoBatchStart = new UndoBatchStart("newline");
mData.mUndoManager.Add(undoBatchStart);
@ -4408,6 +4481,7 @@ namespace IDE.ui
public override void KeyDown(KeyCode keyCode, bool isRepeat)
{
mIgnoreKeyChar = false;
mEmbedSelected = null;
bool autoCompleteRequireControl = (gApp.mSettings.mEditorSettings.mAutoCompleteRequireControl) && (mIsMultiline);
@ -4463,7 +4537,6 @@ namespace IDE.ui
{
return;
}
if ((keyCode == KeyCode.Escape) && (mSelection != null) && (mSelection.Value.HasSelection))
{
@ -4696,6 +4769,23 @@ namespace IDE.ui
{
base.MouseClicked(x, y, origX, origY, btn);
if (btn == 1)
{
int line = GetLineAt(y);
if (mEmbeds.GetValue((.)line) case .Ok(let embed))
{
Rect embedRect = GetEmbedRect(line, embed);
if (embedRect.Contains(x, y))
{
if (var emitEmbed = embed as EmitEmbed)
{
emitEmbed.ShowMenu(x, y);
}
return;
}
}
}
var useX = x;
var useY = y;
@ -4735,15 +4825,15 @@ namespace IDE.ui
{
Menu menuItem;
menuItem = menu.AddItem("Go to Definition");
menuItem = gApp.AddMenuItem(menu, "Go to Definition", "Goto Definition");
menuItem.SetDisabled(!hasText);
menuItem.mOnMenuItemSelected.Add(new (evt) => gApp.GoToDefinition(true));
menuItem = menu.AddItem("Find All References");
menuItem = gApp.AddMenuItem(menu, "Find All References");
menuItem.SetDisabled(!hasText);
menuItem.mOnMenuItemSelected.Add(new (evt) => gApp.Cmd_FindAllReferences());
menuItem = menu.AddItem("Rename Symbol");
menuItem = gApp.AddMenuItem(menu, "Rename Symbol");
menuItem.SetDisabled(!hasText);
menuItem.mOnMenuItemSelected.Add(new (evt) => gApp.Cmd_RenameSymbol());
@ -4823,7 +4913,12 @@ namespace IDE.ui
var autoComplete = new AutoComplete(mEditWidget);
autoComplete.SetInfo(infoCopy);
autoComplete.mAutoCompleteListWidget.mSelectIdx = fixitIdx;
UndoBatchStart undoBatchStart = new UndoBatchStart("autocomplete");
mData.mUndoManager.Add(undoBatchStart);
autoComplete.InsertSelection(0);
mData.mUndoManager.Add(undoBatchStart.mBatchEnd);
autoComplete.Close();
}
~
@ -4866,10 +4961,14 @@ namespace IDE.ui
menu.AddItem();
var debugger = IDEApp.sApp.mDebugger;
bool isPaused = debugger.IsPaused();
menuItem = menu.AddItem("Show Disassembly");
menuItem = gApp.AddMenuItem(menu, "Show Disassembly");
menuItem.SetDisabled(!isPaused);
menuItem.mOnMenuItemSelected.Add(new (evt) => IDEApp.sApp.ShowDisassemblyAtCursor());
menuItem = gApp.AddMenuItem(menu, "Set Next Statement");
menuItem.SetDisabled(!isPaused);
menuItem.mOnMenuItemSelected.Add(new (evt) => IDEApp.sApp.[Friend]SetNextStatement());
var stepIntoSpecificMenu = menu.AddItem("Step into Specific");
stepIntoSpecificMenu.SetDisabled(!isPaused);
stepIntoSpecificMenu.IsParent = true;
@ -5019,20 +5118,26 @@ namespace IDE.ui
Rect embedRect = GetEmbedRect(line, embed);
if (embedRect.Contains(x, y))
{
if ((btn == 0) && (btnCount % 2 == 0))
mEmbedSelected = embed;
embed.MouseDown(GetEmbedRect(line, embed), x, y, btn, btnCount);
if (btn == 0)
{
if (var collapseSummary = embed as SourceEditWidgetContent.CollapseSummary)
SetCollapseOpen(collapseSummary.mCollapseIndex, true);
else if (var emitEmbed = embed as EmitEmbed)
if (btnCount % 2 == 0)
{
emitEmbed.mIsOpen = !emitEmbed.mIsOpen;
mCollapseNeedsUpdate = true;
if (var collapseSummary = embed as SourceEditWidgetContent.CollapseSummary)
SetCollapseOpen(collapseSummary.mCollapseIndex, true);
else if (var emitEmbed = embed as EmitEmbed)
{
emitEmbed.mIsOpen = !emitEmbed.mIsOpen;
mCollapseNeedsUpdate = true;
}
}
}
return;
}
}
mEmbedSelected = null;
base.MouseDown(x, y, btn, btnCount);
}
@ -5727,6 +5832,13 @@ namespace IDE.ui
}
}
void DeleteEmbed(Embed embed)
{
if (mEmbedSelected == embed)
mEmbedSelected = null;
delete embed;
}
public override void GetTextData()
{
var data = Data;
@ -5755,8 +5867,14 @@ namespace IDE.ui
}
}
IdSpan.LookupContext lookupCtx = null;
for (var emitData in ref data.mEmitData)
{
if (lookupCtx == null)
lookupCtx = scope:: .(mData.mTextIdData);
emitData.mAnchorIdx = (.)lookupCtx.GetIndexFromId(emitData.mAnchorId);
GetLineCharAtIdx(emitData.mAnchorIdx, var line, var lineChar);
SourceEditWidgetContent.EmitEmbed emitEmbed = null;
@ -5776,7 +5894,7 @@ namespace IDE.ui
else
{
//Debug.WriteLine($" Occupied- deleting {emitEmbed}");
delete emitEmbed;
DeleteEmbed(emitEmbed);
emitEmbed = null;
}
}
@ -5837,13 +5955,14 @@ namespace IDE.ui
{
mCollapseNeedsUpdate = true;
mEmbeds.Remove(emitEmbed.mLine);
delete emitEmbed;
DeleteEmbed(emitEmbed);
}
}
for (var collapseData in ref data.mCollapseData)
{
if (mCollapseMap.TryAdd(collapseData.mAnchorId, ?, var entry))
bool isNew = mCollapseMap.TryAdd(collapseData.mAnchorId, ?, var entry);
if (isNew)
{
*entry = .();
}
@ -5852,6 +5971,12 @@ namespace IDE.ui
entry.mPrevAnchorLine = prevAnchorLine;
entry.mParseRevision = mCollapseParseRevision;
entry.mDeleted = false;
if ((isNew) && (!entry.DefaultOpen) && (!mCollapseAwaitingDB))
{
// Likely a '#region' that we need to serialize as being open
mCollapseDBDirty = true;
}
}
for (var entry in ref mCollapseMap.Values)
@ -5863,7 +5988,7 @@ namespace IDE.ui
if (!(value is EmitEmbed))
{
mEmbeds.Remove(entry.mAnchorLine);
delete value;
DeleteEmbed(value);
}
}
@entry.Remove();
@ -5888,7 +6013,7 @@ namespace IDE.ui
{
//Debug.WriteLine($" Removing {val.value}");
if (val.value is CollapseSummary)
delete val.value;
DeleteEmbed(val.value);
}
continue;
}
@ -5914,11 +6039,68 @@ namespace IDE.ui
else
{
//Debug.WriteLine($" Deleting(3) {val}");
delete val;
DeleteEmbed(val);
}
}
}
#if !CLI
if ((mCollapseAwaitingDB) && (mSourceViewPanel != null))
{
String filePath = scope .(mSourceViewPanel.mFilePath);
IDEUtils.MakeComparableFilePath(filePath);
HashSet<int32> toggledIndices = scope .();
List<uint8> dbData = scope .();
if (gApp.mFileRecovery.GetDB(filePath, dbData))
{
MemoryStream memStream = scope .(dbData, false);
var dbHash = memStream.Read<MD5Hash>().GetValueOrDefault();
String text = scope .();
mEditWidget.GetText(text);
var curHash = MD5.Hash(.((uint8*)text.Ptr, text.Length));
if (curHash == dbHash)
{
while (true)
{
if (memStream.Read<int32>() case .Ok(let idx))
{
// We recorded indices, which (upon load) will generate an id of idx+1
toggledIndices.Add(idx + 1);
}
else
break;
}
}
}
bool wasCursorVisible = IsCursorVisible();
bool hadCloses = false;
for (var collapseEntry in mOrderedCollapseEntries)
{
bool wantOpen = collapseEntry.DefaultOpen;
if (toggledIndices.Contains(collapseEntry.mAnchorId))
wantOpen = !wantOpen;
if (collapseEntry.mIsOpen != wantOpen)
{
if (!wantOpen)
hadCloses = true;
SetCollapseOpen(@collapseEntry.Index, wantOpen, true, true);
}
}
if ((wasCursorVisible) && (hadCloses))
{
UpdateCollapse(0.0f);
EnsureCursorVisible();
}
mCollapseAwaitingDB = false;
}
#endif
//Debug.WriteLine($"ParseCollapseRegions Count:{mOrderedCollapseEntries.Count} Time:{sw.ElapsedMilliseconds}ms");
}
@ -6221,17 +6403,26 @@ namespace IDE.ui
}
public void SetCollapseOpen(int collapseIdx, bool wantOpen, bool immediate = false)
public void SetCollapseOpen(int collapseIdx, bool wantOpen, bool immediate = false, bool keepCursorVisible = false)
{
var entry = mOrderedCollapseEntries[collapseIdx];
var cursorLineAndColumn = CursorLineAndColumn;
if ((!wantOpen) && (keepCursorVisible) && (cursorLineAndColumn.mLine >= entry.mStartLine) && (cursorLineAndColumn.mLine <= entry.mEndLine))
{
if (CursorTextPos < entry.mEndIdx)
{
// Ignore close
return;
}
}
entry.mIsOpen = wantOpen;
if (immediate)
entry.mOpenPct = entry.mIsOpen ? 1.0f : 0.0f;
else
mCollapseNeedsUpdate = true;
var cursorLineAndColumn = CursorLineAndColumn;
mCollapseNeedsUpdate = true;
mCollapseDBDirty = true;
if (wantOpen)
{
@ -6241,7 +6432,7 @@ namespace IDE.ui
{
if ((embed.mKind == .HideLine) || (embed.mKind == .LineEnd))
{
delete embed;
DeleteEmbed(embed);
mEmbeds.Remove(entry.mAnchorLine);
}
}
@ -6283,7 +6474,7 @@ namespace IDE.ui
if (!(value is EmitEmbed))
{
mEmbeds.Remove(prevAnchorLine);
delete value;
DeleteEmbed(value);
}
}
@ -6304,7 +6495,7 @@ namespace IDE.ui
else
{
//Debug.WriteLine($" Occupied- deleting {val}");
delete val.value;
DeleteEmbed(val.value);
}
}
}
@ -6360,7 +6551,7 @@ namespace IDE.ui
if (entry.mDeleted)
{
if (mEmbeds.GetAndRemove(entry.mAnchorIdx) case .Ok(let val))
delete val.value;
DeleteEmbed(val.value);
continue;
}
@ -6388,7 +6579,7 @@ namespace IDE.ui
*valuePtr = val.value;
}
else
delete val.value;
DeleteEmbed(val.value);
}
}
}
@ -6401,7 +6592,7 @@ namespace IDE.ui
RehupLineCoords();
}
public void ParseCollapseRegions(String collapseText, int32 textVersion, ref IdSpan idSpan, ResolveType resolveType)
public void ParseCollapseRegions(String collapseText, int32 textVersion, ref IdSpan idSpan, ResolveType? resolveType)
{
/*if (resolveType == .None)
return;*/
@ -6410,11 +6601,13 @@ namespace IDE.ui
var data = PreparedData;
if (resolveType != .None)
if ((resolveType != null) && (resolveType != .None))
{
data.ClearCollapse();
}
bool wantsBuildEmits = gApp.mSettings.mEditorSettings.mEmitCompiler == .Build;
//Debug.WriteLine($"ParseCollapseRegions {resolveType} CollapseRevision:{data.mCollapseParseRevision+1} TextVersion:{textVersion} IdSpan:{idSpan:D}");
List<int32> typeNameIdxMap = scope .();
@ -6429,7 +6622,7 @@ namespace IDE.ui
if (emitInitialized)
return;
emitInitialized = true;
if ((hasUncertainEmits) || (resolveType == .None))
if ((hasUncertainEmits) || (wantsBuildEmits) || (resolveType == .None))
{
// Leave emits alone
for (var typeName in data.mTypeNames)
@ -6437,7 +6630,11 @@ namespace IDE.ui
for (var emitData in ref data.mEmitData)
{
emitAnchorIds[emitData.mAnchorId] = (.)@emitData.Index;
if (resolveType == .None)
if (resolveType == null)
{
// Do nothing
}
else if (resolveType == .None)
emitData.mIncludedInResolveAll = false;
else
emitData.mIncludedInClassify = false;
@ -6491,6 +6688,7 @@ namespace IDE.ui
emitData.mOnlyInResolveAll = resolveType == .None;
emitData.mIncludedInClassify = resolveType != .None;
emitData.mIncludedInResolveAll = resolveType == .None;
emitData.mIncludedInBuild = resolveType == null;
if (emitData.mAnchorIdx == -1)
{
@ -6508,8 +6706,14 @@ namespace IDE.ui
{
curEmitData.mIncludedInResolveAll = true;
}
else if ((wantsBuildEmits) && (resolveType != null))
{
curEmitData.mIncludedInBuild |= emitData.mIncludedInBuild;
curEmitData.mIncludedInClassify |= emitData.mIncludedInClassify;
}
else
{
emitData.mIncludedInBuild |= curEmitData.mIncludedInBuild;
emitData.mIncludedInClassify |= curEmitData.mIncludedInClassify;
curEmitData = emitData;
}
@ -6517,12 +6721,19 @@ namespace IDE.ui
continue;
}
if ((wantsBuildEmits) && (resolveType != null))
{
// Not included in the build emit data - just show as a marker
emitData.mStartLine = 0;
emitData.mEndLine = 0;
}
//Debug.WriteLine($" New emit AnchorIdx:{emitData.mAnchorIdx} AnchorId:{emitData.mAnchorId} CurTextVersion:{textVersion} FoundTextVersion:{foundTextVersion}");
data.mEmitData.Add(emitData);
continue;
}
if (resolveType == .None)
if ((resolveType == null) || (resolveType == .None))
continue;
CollapseData collapseData;
@ -6554,7 +6765,11 @@ namespace IDE.ui
for (var emitData in ref data.mEmitData)
{
if (((emitData.mOnlyInResolveAll) && (!emitData.mIncludedInResolveAll)) ||
if ((emitData.mIncludedInBuild) && (gApp.mSettings.mEditorSettings.mEmitCompiler == .Build))
{
// Allow build-only markers to survive
}
else if (((emitData.mOnlyInResolveAll) && (!emitData.mIncludedInResolveAll)) ||
((!emitData.mOnlyInResolveAll) && (!emitData.mIncludedInClassify)))
{
@emitData.RemoveFast();

View file

@ -367,6 +367,7 @@ namespace IDE.ui
class QueuedCollapseData
{
public String mData = new .() ~ delete _;
public String mBuildData ~ delete _;
public int32 mTextVersion;
public IdSpan mCharIdSpan ~ _.Dispose();
public ResolveType mResolveType;
@ -446,6 +447,7 @@ namespace IDE.ui
int32 mTicksSinceTextChanged;
int32 mErrorLookupTextIdx = -1;
LinePointerDrawData mLinePointerDrawData;
bool mIsDraggingLinePointer;
Point? mMousePos;
#if IDE_C_SUPPORT
public String mClangHoverErrorData ~ delete mClangHoverErrorData;
@ -1262,6 +1264,9 @@ namespace IDE.ui
void FindEmbeds(ResolveParams resolveParams)
{
if (gApp.mSettings.mEditorSettings.mEmitCompiler != .Resolve)
return;
HashSet<FileEditData> foundEditData = scope .();
Dictionary<String, String> remappedTypeNames = scope .();
@ -1478,11 +1483,31 @@ namespace IDE.ui
var collapseData = bfCompiler.GetCollapseRegions(parser, resolvePassData, explicitEmitTypeNames, .. scope .());
String buildCollapseData = null;
if ((gApp.mSettings.mEditorSettings.mEmitCompiler == .Build) && (!gApp.mBfBuildCompiler.IsPerformingBackgroundOperation()))
{
gApp.mBfBuildSystem.Lock(0);
var buildParser = gApp.mBfBuildSystem.GetParser(mProjectSource);
if (buildParser != null)
{
var buildResolvePassData = buildParser.CreateResolvePassData(.None);
defer delete buildResolvePassData;
buildCollapseData = gApp.mBfBuildCompiler.GetCollapseRegions(buildParser, buildResolvePassData, explicitEmitTypeNames, .. scope:: .());
}
else
{
buildCollapseData = "";
}
gApp.mBfBuildSystem.Unlock();
}
using (mMonitor.Enter())
{
DeleteAndNullify!(mQueuedCollapseData);
mQueuedCollapseData = new .();
mQueuedCollapseData.mData.Set(collapseData);
if (buildCollapseData != null)
mQueuedCollapseData.mBuildData = new String(buildCollapseData);
mQueuedCollapseData.mTextVersion = textVersion;
mQueuedCollapseData.mCharIdSpan = charIdSpan.Duplicate();
@ -1524,13 +1549,13 @@ namespace IDE.ui
return;
//var compiler = ResolveCompiler;
var char8Data = mEditWidget.Content.mData.mText;
int char8Len = Math.Min(char8Data.Count, mEditWidget.Content.mData.mTextLength);
var charData = mEditWidget.Content.mData.mText;
int charLen = Math.Min(charData.Count, mEditWidget.Content.mData.mTextLength);
char8[] chars = new char8[char8Len];
char8[] chars = new char8[charLen];
defer delete chars;
for (int32 i = 0; i < char8Len; i++)
chars[i] = (char8)char8Data[i].mChar;
for (int32 i = 0; i < charLen; i++)
chars[i] = (char8)charData[i].mChar;
String text = scope String();
text.Append(chars, 0, chars.Count);
@ -1554,7 +1579,7 @@ namespace IDE.ui
parser.SetEmbedKind(mEmbedKind);
parser.Reduce(passInstance);
}
parser.ClassifySource(char8Data, !mIsBeefSource);
parser.ClassifySource(charData, !mIsBeefSource);
mWantsParserCleanup = true;
}
@ -2208,7 +2233,7 @@ namespace IDE.ui
{
parser.CreateClassifier(passInstance, resolvePassData, charData);
if (resolveParams != null)
if ((resolveParams != null) && (gApp.mSettings.mEditorSettings.mEmitCompiler == .Resolve))
{
for (var emitEmbedData in resolveParams.mEmitEmbeds)
{
@ -2484,7 +2509,10 @@ namespace IDE.ui
int32 prevLine = mEditWidget.Content.CursorLineAndColumn.mLine;
mEditWidget.Content.mSelection = null;
mEditWidget.Content.CursorTextPos = cursorIdx;
int wantCursorPos = Math.Min(mEditWidget.Content.mData.mTextLength - 1, cursorIdx);
if (wantCursorPos >= 0)
mEditWidget.Content.CursorTextPos = wantCursorPos;
mEditWidget.Content.CursorMoved();
mEditWidget.Content.EnsureCursorVisible(true, true);
mEditWidget.Content.mCursorImplicitlyMoved = true;
@ -4476,6 +4504,8 @@ namespace IDE.ui
BreakpointCountMask = 0x7F,
Boomkmark = 0x80
}
static float sDrawLeftAdjust = GS!(12);
public override void Draw(Graphics g)
{
@ -4505,7 +4535,6 @@ namespace IDE.ui
using (g.PushTranslate(0, mEditWidget.mY + mEditWidget.Content.Y + GS!(2)))
{
float editX = GetEditX();
float leftAdjust = GS!(12);
float lineSpacing = ewc.mFont.GetLineSpacing();
int cursorLineNumber = mEditWidget.mEditWidgetContent.CursorLineAndColumn.mLine;
@ -4623,7 +4652,7 @@ namespace IDE.ui
int breakpointCount = (.)(curLineFlags & .BreakpointCountMask);
curLineFlags++;
float iconX = Math.Max(GS!(-2), mEditWidget.mX - GS!(24) - leftAdjust) + breakpointCount*-GS!(2);
float iconX = Math.Max(GS!(-2), mEditWidget.mX - GS!(24) - sDrawLeftAdjust) + breakpointCount*-GS!(2);
float iconY = 0 + ewc.mLineCoords[drawLineNum] + (lineSpacing - DarkTheme.sUnitSize + GS!(5)) / 2;
// Just leave last digit visible
@ -4648,7 +4677,7 @@ namespace IDE.ui
continue;
//hadLineIcon[drawLineNum - lineStart] = true;
Image image = DarkTheme.sDarkTheme.GetImage(bookmark.mIsDisabled ? .IconBookmarkDisabled : .IconBookmark);
g.Draw(image, Math.Max(GS!(-5), mEditWidget.mX - GS!(30) - leftAdjust),
g.Draw(image, Math.Max(GS!(-5), mEditWidget.mX - GS!(30) - sDrawLeftAdjust),
0 + bookmark.mLineNum * lineSpacing);
var curLineFlags = ref lineFlags[drawLineNum - lineStart];
@ -4812,9 +4841,20 @@ namespace IDE.ui
{
mLinePointerDrawData.mUpdateCnt = gApp.mUpdateCnt;
mLinePointerDrawData.mDebuggerContinueIdx = gApp.mDebuggerContinueIdx;
g.Draw(img, mEditWidget.mX - GS!(20) - leftAdjust,
g.Draw(img, mEditWidget.mX - GS!(20) - sDrawLeftAdjust,
0 + ewc.GetLineY(lineNum, 0));
}
if (mMousePos != null && mIsDraggingLinePointer)
{
int dragLineNum = GetLineAt(0, mMousePos.Value.y);
if (dragLineNum >= 0 && dragLineNum != lineNum)
{
using (g.PushColor(0x7FFFFFFF))
g.Draw(img, mEditWidget.mX - GS!(20) - sDrawLeftAdjust,
0 + ewc.GetLineY(dragLineNum, 0));
}
}
}
}
}
@ -6275,15 +6315,15 @@ namespace IDE.ui
emitEmbedView.mGenericMethodCombo?.mEditWidget.SetFocus();
}
var sourceViewPanel = emitEmbedView.mSourceViewPanel;
var firstSourceViewPanel = emitEmbedView.mSourceViewPanel;
var embedEWC = sourceViewPanel.mEditWidget.mEditWidgetContent;
var firstEmbedEWC = firstSourceViewPanel.mEditWidget.mEditWidgetContent;
var prevCursorLineAndColumn = embedEWC.CursorLineAndColumn;
var prevCursorLineAndColumn = firstEmbedEWC.CursorLineAndColumn;
var editData = sourceViewPanel.mEditWidget.mEditWidgetContent.mData;
var editData = firstSourceViewPanel.mEditWidget.mEditWidgetContent.mData;
if (editData.mTextLength == 0)
DeleteAndNullify!(sourceViewPanel.mTrackedTextElementViewList);
DeleteAndNullify!(firstSourceViewPanel.mTrackedTextElementViewList);
delete editData.mText;
editData.mText = embed.mCharData;
@ -6294,15 +6334,23 @@ namespace IDE.ui
editData.mNextCharId = 0;
editData.mTextIdData.Insert(0, editData.mTextLength, ref editData.mNextCharId);
sourceViewPanel.mEditWidget.mEditWidgetContent.ContentChanged();
// We have a full classify now, FastClassify will just mess it up
sourceViewPanel.mSkipFastClassify = true;
firstSourceViewPanel.mEmitRevision = embed.mRevision;
firstSourceViewPanel.InjectErrors(resolveResult.mPassInstance, editData.mText, editData.mTextIdData, false, true);
if (prevCursorLineAndColumn.mLine >= embedEWC.GetLineCount())
embedEWC.CursorLineAndColumn = .(embedEWC.GetLineCount() - 1, prevCursorLineAndColumn.mColumn);
sourceViewPanel.mEmitRevision = embed.mRevision;
sourceViewPanel.InjectErrors(resolveResult.mPassInstance, editData.mText, editData.mTextIdData, false, true);
for (var user in editData.mUsers)
{
if (var embedEWC = user as SourceEditWidgetContent)
{
var sourceViewPanel = embedEWC.mSourceViewPanel;
sourceViewPanel.mEditWidget.mEditWidgetContent.ContentChanged();
// We have a full classify now, FastClassify will just mess it up
sourceViewPanel.mSkipFastClassify = true;
if (prevCursorLineAndColumn.mLine >= firstEmbedEWC.GetLineCount())
embedEWC.CursorLineAndColumn = .(firstEmbedEWC.GetLineCount() - 1, prevCursorLineAndColumn.mColumn);
}
}
}
}
}
@ -6595,7 +6643,7 @@ namespace IDE.ui
}
if ((mTicksSinceTextChanged >= 60) && (mWantsSpellCheck))
{
if (IsControllingEditData())
if ((IsControllingEditData()) && (mEmbedKind == .None))
StartSpellCheck();
mWantsSpellCheck = false;
}
@ -6850,7 +6898,59 @@ namespace IDE.ui
using (mMonitor.Enter())
{
if (mQueuedCollapseData != null)
{
if (gApp.mSettings.mEditorSettings.mEmitCompiler == .Build)
{
if (mQueuedCollapseData.mBuildData != null)
{
bool foundData = false;
using (gApp.mMonitor.Enter())
{
var projectSourceCompileInstance = gApp.mWorkspace.GetProjectSourceCompileInstance(projectSource, gApp.mWorkspace.HotCompileIdx);
if (projectSourceCompileInstance != null)
{
foundData = true;
ewc.ParseCollapseRegions(mQueuedCollapseData.mBuildData, mQueuedCollapseData.mTextVersion, ref projectSourceCompileInstance.mSourceCharIdData, null);
HashSet<EditWidgetContent.Data> dataLoaded = scope .();
for (var embed in ewc.mEmbeds.Values)
{
if (var emitEmbed = embed as SourceEditWidgetContent.EmitEmbed)
{
if (emitEmbed.mView != null)
{
if (dataLoaded.Add(emitEmbed.mView.mSourceViewPanel.mEditWidget.mEditWidgetContent.mData))
{
emitEmbed.mView.mSourceViewPanel.mSkipFastClassify = false;
emitEmbed.mView.mSourceViewPanel.Reload();
emitEmbed.mView.mSourceViewPanel.mWantsFastClassify = true;
}
}
}
}
}
}
if (!foundData)
{
for (var embed in ewc.mEmbeds.Values)
{
if (var emitEmbed = embed as SourceEditWidgetContent.EmitEmbed)
{
if (emitEmbed.mView != null)
{
emitEmbed.mView.mSourceViewPanel.mEditWidget.mEditWidgetContent.ClearText();
}
}
}
}
}
}
ewc.ParseCollapseRegions(mQueuedCollapseData.mData, mQueuedCollapseData.mTextVersion, ref mQueuedCollapseData.mCharIdSpan, mQueuedCollapseData.mResolveType);
}
DeleteAndNullify!(mQueuedCollapseData);
}
@ -6858,6 +6958,38 @@ namespace IDE.ui
// Process after mQueuedCollapseData so mCharIdSpan is still valid
ProcessDeferredResolveResults(0);
#if !CLI
if (ewc.mCollapseDBDirty)
{
MemoryStream memStream = scope .();
String text = scope .();
mEditWidget.GetText(text);
var hash = MD5.Hash(.((uint8*)text.Ptr, text.Length));
memStream.Write(hash);
bool hadData = false;
for (var kv in ewc.mOrderedCollapseEntries)
{
if (kv.mIsOpen != kv.DefaultOpen)
{
hadData = true;
memStream.Write(kv.mAnchorIdx);
}
}
String filePath = scope .(mFilePath);
IDEUtils.MakeComparableFilePath(filePath);
if (!hadData)
gApp.mFileRecovery.DeleteDB(filePath);
else
gApp.mFileRecovery.SetDB(filePath, memStream.Memory);
ewc.mCollapseDBDirty = false;
}
#endif
}
public override void UpdateF(float updatePct)
@ -7070,7 +7202,7 @@ namespace IDE.ui
float GetEditX()
{
if (!gApp.mSettings.mEditorSettings.mShowLineNumbers && (mEmbedKind == .None))
if ((!gApp.mSettings.mEditorSettings.mShowLineNumbers) || (mEmbedKind != .None))
return GS!(24);
var font = IDEApp.sApp.mTinyCodeFont;
@ -7268,6 +7400,29 @@ namespace IDE.ui
}
}
public override void MouseUp(float x, float y, int32 btn)
{
base.MouseUp(x, y, btn);
if (mIsDraggingLinePointer)
{
mIsDraggingLinePointer = false;
float origX;
float origY;
RootToSelfTranslate(mWidgetWindow.mMouseDownX, mWidgetWindow.mMouseDownY, out origX, out origY);
int newLine = GetLineAt(0, y);
if (newLine >= 0 && newLine != GetLineAt(origX, origY))
{
gApp.mDebugger.SetNextStatement(false, mFilePath, (int)newLine, 0);
gApp.[Friend]PCChanged();
gApp.[Friend]DebuggerUnpaused();
}
}
}
public int GetLineAt(float x, float y)
{
if (x > mEditWidget.mX - GS!(4))
@ -7321,8 +7476,9 @@ namespace IDE.ui
{
if ((x >= GS!(3)) && (x < mEditWidget.mX - GS!(14)))
{
int lineMouseDown = GetLineAt(origX, origY);
int lineClick = GetLineAt(x, y);
if (lineClick >= 0)
if (lineClick >= 0 && lineMouseDown == lineClick)
{
ToggleBreakpointAt(lineClick, 0);
}
@ -7351,6 +7507,37 @@ namespace IDE.ui
{
base.MouseMove(x, y);
mMousePos = .(x, y);
if (!mIsDraggingLinePointer && IDEApp.sApp.mExecutionPaused && gApp.mDebugger.mActiveCallStackIdx == 0 && mMouseFlags.HasFlag(.Left))
{
SourceEditWidgetContent ewc = (.)mEditWidget.Content;
Rect linePointerRect = .(
mEditWidget.mX - GS!(20) - sDrawLeftAdjust,
0 + ewc.GetLineY(mLinePointerDrawData.mLine, 0),
GS!(15),
GS!(15)
);
float origX;
float origY;
RootToSelfTranslate(mWidgetWindow.mMouseDownX, mWidgetWindow.mMouseDownY, out origX, out origY);
if (linePointerRect.Contains(origX, origY - mEditWidget.mY - mEditWidget.Content.Y - GS!(3)))
{
mIsDraggingLinePointer = true;
}
}
else if (mIsDraggingLinePointer)
{
SourceEditWidgetContent ewc = (.)mEditWidget.Content;
float linePos = ewc.GetLineY(GetLineAt(0, mMousePos.Value.y), 0);
Rect visibleRange = mEditWidget.GetVisibleContentRange();
if (visibleRange.Top > linePos)
mEditWidget.mVertScrollbar.ScrollTo(linePos);
else if (visibleRange.Bottom - mEditWidget.mHorzScrollbar.mHeight < linePos)
mEditWidget.mVertScrollbar.ScrollTo(linePos - visibleRange.mHeight + ewc.GetLineHeight(0));
}
}
public override void DrawAll(Graphics g)

View file

@ -384,6 +384,8 @@ namespace IDE.ui
protected void ConfigDeleted(String configName)
{
int32 category = mPropPage.mCategoryType;
bool currentChanged = false;
int idx = mConfigNames.IndexOf(configName);
if (idx != -1)
@ -422,7 +424,17 @@ namespace IDE.ui
}
if (currentChanged)
SelectConfig(mConfigNames);
{
mPropPage = null;
SelectConfig(mConfigNames, category);
}
if ((mActiveConfigName == configName) && (!mConfigNames.IsEmpty))
{
var newConfigName = mConfigNames[0];
gApp.mMainFrame.mStatusBar.SelectConfig(newConfigName);
mActiveConfigName.Set(newConfigName);
}
}
protected void ConfigRenamed(String from, String to)
@ -761,7 +773,7 @@ namespace IDE.ui
ShowPropPage(categoryType);
}
protected void SelectConfig(List<String> configNames)
protected void SelectConfig(List<String> configNames, int32 category = -1)
{
if (configNames != mConfigNames)
{
@ -770,7 +782,7 @@ namespace IDE.ui
mConfigNames.Add(configName);
}
if (mConfigNames.Count == 1)
SelectConfig(mConfigNames[0]);
SelectConfig(mConfigNames[0], category);
else
{
mConfigComboBox.Label = "<Multiple>";
@ -795,13 +807,16 @@ namespace IDE.ui
}
}
protected void SelectConfig(String configName)
protected void SelectConfig(String configName, int32 category = -1)
{
var category;
if (category == -1)
category = mPropPage.mCategoryType;
var newConfigName = new String(configName);
ClearAndDeleteItems(mConfigNames);
mConfigNames.Add(newConfigName);
mConfigComboBox.Label = newConfigName;
ShowPropPage(mPropPage.mCategoryType);
ShowPropPage(category);
}
protected void SelectPlatform(String platformName, int32 category = -1)

View file

@ -2752,20 +2752,29 @@ namespace IDE.ui
}
else if (memberVals0 == ":addrs")
{
WatchListViewItem memberItem = (WatchListViewItem)listViewItem.GetChildAtIndex(memberCount - 1);
String.NewOrSet!(memberItem.mWatchSeriesInfo.mAddrs, memberVals[1]);
memberItem.mWatchSeriesInfo.mAddrsEntrySize = 1;
if (memberCount > 0)
{
WatchListViewItem memberItem = (WatchListViewItem)listViewItem.GetChildAtIndex(memberCount - 1);
String.NewOrSet!(memberItem.mWatchSeriesInfo.mAddrs, memberVals[1]);
memberItem.mWatchSeriesInfo.mAddrsEntrySize = 1;
}
}
else if (memberVals0 == ":addrsEntrySize")
{
int32 addrsEntrySize = int32.Parse(scope String(memberVals[1]));
WatchListViewItem memberItem = (WatchListViewItem)listViewItem.GetChildAtIndex(memberCount - 1);
memberItem.mWatchSeriesInfo.mAddrsEntrySize = addrsEntrySize;
if (memberCount > 0)
{
int32 addrsEntrySize = int32.Parse(scope String(memberVals[1]));
WatchListViewItem memberItem = (WatchListViewItem)listViewItem.GetChildAtIndex(memberCount - 1);
memberItem.mWatchSeriesInfo.mAddrsEntrySize = addrsEntrySize;
}
}
else if (memberVals0 == ":continuation")
{
WatchListViewItem memberItem = (WatchListViewItem)listViewItem.GetChildAtIndex(memberCount - 1);
String.NewOrSet!(memberItem.mWatchSeriesInfo.mContinuationData, memberVals[1]);
if (memberCount > 0)
{
WatchListViewItem memberItem = (WatchListViewItem)listViewItem.GetChildAtIndex(memberCount - 1);
String.NewOrSet!(memberItem.mWatchSeriesInfo.mContinuationData, memberVals[1]);
}
}
else if (memberVals0 == ":action")
{