1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-22 09:38:01 +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

@ -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")
{