diff --git a/IDE/screenshot0.gif b/IDE/screenshot0.gif index 003cfc87..4262a12d 100644 Binary files a/IDE/screenshot0.gif and b/IDE/screenshot0.gif differ diff --git a/IDE/src/ui/ErrorsPanel.bf b/IDE/src/ui/ErrorsPanel.bf new file mode 100644 index 00000000..eaf81793 --- /dev/null +++ b/IDE/src/ui/ErrorsPanel.bf @@ -0,0 +1,302 @@ +using Beefy.widgets; +using Beefy.theme.dark; +using IDE.Compiler; +using System.Collections.Generic; +using System.Threading; +using System; +using Beefy.gfx; +using System.IO; +using Beefy.utils; + +namespace IDE.ui +{ + class ErrorsPanel : Panel + { + public class ErrorsListView : IDEListView + { + protected override ListViewItem CreateListViewItem() + { + return new ErrorsListViewItem(); + } + } + + public class ErrorsListViewItem : IDEListViewItem + { + public String mFilePath ~ delete _; + public int mLine; + public int mColumn; + + public override void DrawSelect(Graphics g) + { + bool hasFocus = mListView.mHasFocus; + if ((mWidgetWindow.mFocusWidget != null) && (mWidgetWindow.mFocusWidget.HasParent(mListView))) + hasFocus = true; + using (g.PushColor(hasFocus ? 0xFFFFFFFF : 0x80FFFFFF)) + base.DrawSelect(g); + } + + public bool Goto() + { + if (mFilePath == null) + return false; + gApp.ShowSourceFileLocation(mFilePath, -1, -1, mLine, mColumn, .Always); + return false; + } + } + + public DarkDockingFrame mDockingFrame; + public ErrorsListView mErrorLV; + public OutputWidget mOutputWidget; + + public bool mNeedsResolveAll; + public bool mErrorsDirty; + public Monitor mMonitor = new .() ~ delete _; + public List mErrorList = new .() ~ DeleteContainerAndItems!(_); + public int mDirtyTicks; + + public int mErrorCount; + public int mWarningCount; + + public this() + { + mErrorLV = new .(); + //mErrorLV.mPanel = this; + //mErrorLV.SetShowHeader(false); + mErrorLV.InitScrollbars(true, true); + mErrorLV.mLabelX = GS!(6); + //mErrorLV.mOnItemMouseDown.Add(new => ItemMouseDown); + mErrorLV.mOnItemMouseClicked.Add(new => ListViewItemMouseClicked); + mErrorLV.mOnKeyDown.Add(new => ListViewKeyDown_ShowMenu); + mErrorLV.AddColumn(100, "Code"); + mErrorLV.AddColumn(400, "Description"); + mErrorLV.AddColumn(100, "Project"); + mErrorLV.AddColumn(120, "File"); + mErrorLV.AddColumn(40, "Line"); + mErrorLV.mOnItemMouseDown.Add(new (item, x, y, btnNum, btnCount) => + { + if ((btnNum == 0) && (btnCount == 2)) + { + let mainItem = (ErrorsListViewItem)item.GetSubItem(0); + mainItem.Goto(); + } + + ListViewItemMouseDown(item, x, y, btnNum, btnCount); + //mErrorLV.GetRoot().SelectItemExclusively() + }); + //let newItem = mErrorLV.GetRoot().CreateChildItem(); + //newItem.Label = "Hey"; + + mOutputWidget = new .(); + + var errorDock = new DockingProxy(mErrorLV); + var detailsDock = new DockingProxy(mOutputWidget); + + mDockingFrame = new DarkDockingFrame(); + mDockingFrame.mDrawBkg = false; + mDockingFrame.AddDockedWidget(errorDock, null, .Top); + mDockingFrame.AddDockedWidget(detailsDock, errorDock, .Bottom); + AddWidget(mDockingFrame); + } + + public override void Serialize(StructuredData data) + { + base.Serialize(data); + + data.Add("Type", "ErrorsPanel"); + } + + public override void Resize(float x, float y, float width, float height) + { + base.Resize(x, y, width, height); + mDockingFrame.Resize(0, 0, width, height); + } + + public enum ResolveKind + { + None, + Parse, + Resolve + } + + public void ProcessPassInstance(BfPassInstance passInstance, BfPassInstance.PassKind passKind) + { + using (mMonitor.Enter()) + { + mErrorCount = 0; + mWarningCount = 0; + + int32 errorCount = passInstance.GetErrorCount(); + ClearAndDeleteItems(mErrorList); + mErrorList.Capacity = mErrorList.Count; + + for (int32 errorIdx = 0; errorIdx < errorCount; errorIdx++) + { + BfPassInstance.BfError bfError = new BfPassInstance.BfError(); + passInstance.GetErrorData(errorIdx, bfError, true); + + if (bfError.mIsWarning) + mWarningCount++; + else + mErrorCount++; + + for (int32 moreInfoIdx < bfError.mMoreInfoCount) + { + BfPassInstance.BfError moreInfo = new BfPassInstance.BfError(); + passInstance.GetMoreInfoErrorData(errorIdx, moreInfoIdx, moreInfo, true); + if (bfError.mMoreInfo == null) + bfError.mMoreInfo = new List(); + bfError.mMoreInfo.Add(moreInfo); + } + + mErrorList.Add(bfError); + } + + mErrorsDirty = true; + } + } + + public void ClearParserErrors(StringView filePath) + { + + } + + void ProcessErrors() + { + using (mMonitor.Enter()) + { + if (mErrorsDirty) + { + let root = mErrorLV.GetRoot(); + + for (let error in mErrorList) + { + ErrorsListViewItem item; + + bool changed = false; + void SetLabel(ListViewItem item, StringView str) + { + if (item.Label == str) + return; + changed = true; + item.Label = str; + } + + int idx = @error.Index; + if (idx >= root.GetChildCount()) + { + item = (.)root.CreateChildItem(); + item.CreateSubItem(1); + item.CreateSubItem(2); + item.CreateSubItem(3); + item.CreateSubItem(4); + } + else + item = (.)root.GetChildAtIndex(idx); + + if (error.mFilePath == null) + DeleteAndNullify!(error.mFilePath); + else + String.NewOrSet!(item.mFilePath, error.mFilePath); + item.mLine = error.mLine; + item.mColumn = error.mColumn; + + String codeStr = scope String(32); + codeStr.AppendF(error.mIsWarning ? "{}Warning" : "{}Error", Font.EncodeColor(error.mIsWarning ? 0xFFFFFF80 : 0xFFFF8080)); + if (error.mCode != 0) + codeStr.AppendF(" {}", error.mCode); + codeStr.AppendF("{}", Font.EncodePopColor()); + SetLabel(item, codeStr); + + let descItem = item.GetSubItem(1); + SetLabel(descItem, scope String(32)..AppendF(error.mError)); + + let projectItem = item.GetSubItem(2); + SetLabel(projectItem, error.mProject); + + let fileNameItem = item.GetSubItem(3); + let fileName = scope String(128); + Path.GetFileName(error.mFilePath, fileName); + SetLabel(fileNameItem, fileName); + let lineNumberItem = item.GetSubItem(4); + if (error.mLine != -1) + SetLabel(lineNumberItem, scope String(16)..AppendF("{}", error.mLine + 1)); + else + SetLabel(lineNumberItem, ""); + + if (changed) + item.Focused = false; + } + + while (root.GetChildCount() > mErrorList.Count) + root.RemoveChildItemAt(root.GetChildCount() - 1); + + mErrorsDirty = false; + } + } + } + + public void CheckResolveAll() + { + let compiler = gApp.mBfResolveCompiler; + if ((mNeedsResolveAll) && (!compiler.IsPerformingBackgroundOperation())) + { + if (compiler.mResolveAllWait == 0) + compiler.QueueDeferredResolveAll(); + mNeedsResolveAll = false; + } + } + + public override void Update() + { + base.Update(); + + if (!mVisible) + { + // Very dirty + mDirtyTicks = Math.Max(100, mDirtyTicks); + return; + } + + let compiler = gApp.mBfResolveCompiler; + if ((!compiler.IsPerformingBackgroundOperation()) && (compiler.mResolveAllWait == 0)) + mDirtyTicks = 0; + else + mDirtyTicks++; + + ProcessErrors(); + } + + public void SetNeedsResolveAll() + { + mNeedsResolveAll = true; + } + + public void ShowErrorNext() + { + ProcessErrors(); + + bool foundFocused = false; + let root = mErrorLV.GetRoot(); + if (root.mChildItems == null) + return; + for (let lvItem in root.mChildItems) + { + if (lvItem.Focused) + { + lvItem.Focused = false; + foundFocused = true; + } + else if (foundFocused) + { + lvItem.Focused = true; + ((ErrorsListViewItem)lvItem).Goto(); + return; + } + } + + let lvItem = (ErrorsListViewItem)root.GetChildAtIndex(0); + lvItem.Focused = true; + lvItem.Goto(); + } + } +}