mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-16 23:34:10 +02:00
Initial checkin
This commit is contained in:
parent
c74712dad9
commit
078564ac9e
3242 changed files with 1616395 additions and 0 deletions
992
IDE/src/ui/ClassViewPanel.bf
Normal file
992
IDE/src/ui/ClassViewPanel.bf
Normal file
|
@ -0,0 +1,992 @@
|
|||
using Beefy.theme.dark;
|
||||
using System;
|
||||
using Beefy.widgets;
|
||||
using Beefy.gfx;
|
||||
using Beefy.events;
|
||||
using Beefy.utils;
|
||||
using System.Diagnostics;
|
||||
using IDE.Compiler;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace IDE.ui
|
||||
{
|
||||
class ClassViewPanel : Panel
|
||||
{
|
||||
public class ClassViewListViewItem : IDEListViewItem
|
||||
{
|
||||
public float mLabelOffset;
|
||||
public Object mRefObject;
|
||||
public DataKind mKind;
|
||||
public PendingEntry mMemberInfo ~ delete _;
|
||||
|
||||
protected override float GetLabelOffset()
|
||||
{
|
||||
return mLabelOffset;
|
||||
}
|
||||
|
||||
public override float ResizeComponents(float xOffset)
|
||||
{
|
||||
return base.ResizeComponents(xOffset);
|
||||
}
|
||||
|
||||
public override void DrawSelect(Graphics g)
|
||||
{
|
||||
bool hasFocus = mListView.mHasFocus;
|
||||
if ((mWidgetWindow.mFocusWidget != null) && (mWidgetWindow.mFocusWidget.HasParent(mListView)))
|
||||
hasFocus = true;
|
||||
let parent = (ClassViewListView)mListView;
|
||||
if (parent.mPanel.mFindClassDialog != null)
|
||||
hasFocus = true;
|
||||
using (g.PushColor(hasFocus ? 0xFFFFFFFF : 0x80FFFFFF))
|
||||
base.DrawSelect(g);
|
||||
}
|
||||
|
||||
public override void Draw(Graphics g)
|
||||
{
|
||||
base.Draw(g);
|
||||
if (mRefObject != null)
|
||||
{
|
||||
bool hasChanged = false;
|
||||
var workspace = mRefObject as Workspace;
|
||||
if (workspace != null)
|
||||
hasChanged = workspace.mHasChanged;
|
||||
var project = mRefObject as Project;
|
||||
if (project != null)
|
||||
hasChanged = project.mHasChanged;
|
||||
if (hasChanged)
|
||||
g.DrawString("*", g.mFont.GetWidth(mLabel) + mLabelOffset + LabelX + 1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
Image icon = null;
|
||||
|
||||
switch (mKind)
|
||||
{
|
||||
case .Project:
|
||||
icon = DarkTheme.sDarkTheme.GetImage(.Project);
|
||||
case .Namespace:
|
||||
icon = DarkTheme.sDarkTheme.GetImage(.Namespace);
|
||||
case .Class:
|
||||
icon = DarkTheme.sDarkTheme.GetImage(.Type_Class);
|
||||
case .Interface:
|
||||
icon = DarkTheme.sDarkTheme.GetImage(.Interface);
|
||||
case .ValueType:
|
||||
icon = DarkTheme.sDarkTheme.GetImage(.Type_ValueType);
|
||||
case .Field:
|
||||
icon = DarkTheme.sDarkTheme.GetImage(.Field);
|
||||
case .Property:
|
||||
icon = DarkTheme.sDarkTheme.GetImage(.Property);
|
||||
case .Method:
|
||||
icon = DarkTheme.sDarkTheme.GetImage(.Method);
|
||||
default:
|
||||
}
|
||||
IconImage = icon;
|
||||
}
|
||||
}
|
||||
|
||||
public class ClassViewListView : IDEListView
|
||||
{
|
||||
public ClassViewPanel mPanel;
|
||||
|
||||
protected override ListViewItem CreateListViewItem()
|
||||
{
|
||||
var anItem = new ClassViewListViewItem();
|
||||
return anItem;
|
||||
}
|
||||
|
||||
public override void KeyDown(KeyCode keyCode, bool isRepeat)
|
||||
{
|
||||
base.KeyDown(keyCode, isRepeat);
|
||||
|
||||
if (keyCode == .Return)
|
||||
{
|
||||
if (var item = (ClassViewListViewItem)GetRoot().FindFocusedItem())
|
||||
mPanel.ShowItem(item);
|
||||
}
|
||||
else if (keyCode == .Tab)
|
||||
{
|
||||
if (this == mPanel.mTypeLV)
|
||||
{
|
||||
if (mWidgetWindow.IsKeyDown(.Shift))
|
||||
mPanel.mSearchEdit.SetFocus();
|
||||
else if (mPanel.mMemberLV != null)
|
||||
{
|
||||
if (mPanel.mMemberLV.GetRoot().GetChildCount() > 0)
|
||||
{
|
||||
if (mPanel.mMemberLV.GetRoot().FindFocusedItem() == null)
|
||||
mPanel.mMemberLV.GetRoot().GetChildAtIndex(0).Focused = true;
|
||||
mPanel.mMemberLV.SetFocus();
|
||||
}
|
||||
}
|
||||
else
|
||||
mPanel.mSearchEdit.SetFocus();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mWidgetWindow.IsKeyDown(.Shift))
|
||||
mPanel.mTypeLV.SetFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TypeArea : DockedWidget
|
||||
{
|
||||
public ClassViewPanel mPanel;
|
||||
|
||||
public override void Resize(float x, float y, float width, float height)
|
||||
{
|
||||
base.Resize(x, y, width, height);
|
||||
mPanel.mSearchEdit.Resize(GS!(2), GS!(4), width - GS!(4), GS!(24));
|
||||
mPanel.mTypeLV.Resize(0, GS!(30), width, height - GS!(30));
|
||||
}
|
||||
|
||||
public override void DrawAll(Beefy.gfx.Graphics g)
|
||||
{
|
||||
base.DrawAll(g);
|
||||
using (g.PushColor(0x80FFFFFF))
|
||||
g.DrawBox(DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.Bkg), 0, mHeight - GS!(1), mWidth, GS!(4));
|
||||
}
|
||||
}
|
||||
|
||||
public class PendingEntry : IHashable, IEquatable<PendingEntry>
|
||||
{
|
||||
public DataKind mKind;
|
||||
public bool mShow = true;
|
||||
public String mName ~ delete _;
|
||||
public PendingEntry mParent;
|
||||
public HashSet<PendingEntry> mChildren;
|
||||
public List<PendingEntry> mSortedList;
|
||||
public Object mRefObject;
|
||||
|
||||
public String mFile ~ delete _;
|
||||
public int mLine;
|
||||
public int mColumn;
|
||||
|
||||
public this()
|
||||
{
|
||||
}
|
||||
|
||||
public this(DataKind kind, String name)
|
||||
{
|
||||
mKind = kind;
|
||||
mName = name;
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
if (mSortedList != null)
|
||||
{
|
||||
DeleteContainerAndItems!(mSortedList);
|
||||
delete mChildren;
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteContainerAndItems!(mChildren);
|
||||
}
|
||||
}
|
||||
|
||||
void Detach()
|
||||
{
|
||||
mName = null;
|
||||
}
|
||||
|
||||
public bool Equals(PendingEntry other)
|
||||
{
|
||||
return this == other;
|
||||
}
|
||||
|
||||
public static bool operator==(PendingEntry val1, PendingEntry val2)
|
||||
{
|
||||
if (((Object)val1 == null) || ((Object)val2 == null))
|
||||
return ((Object)val1 == null) && ((Object)val2 == null);
|
||||
if ((val1.mKind != val2.mKind) && ((val1.mKind != .Namespace) && (val2.mKind != .Namespace)))
|
||||
return false;
|
||||
return (val1.mName == val2.mName);
|
||||
}
|
||||
|
||||
public int GetHashCode()
|
||||
{
|
||||
return mName.GetHashCode();
|
||||
}
|
||||
|
||||
public PendingEntry AddChild(DataKind kind, String name)
|
||||
{
|
||||
if (mChildren == null)
|
||||
{
|
||||
mChildren = new HashSet<PendingEntry>();
|
||||
PendingEntry child = new PendingEntry(kind, new String(name));
|
||||
if (mKind != .Root)
|
||||
child.mParent = this;
|
||||
Debug.Assert(child != (Object)this);
|
||||
mChildren.Add(child);
|
||||
return child;
|
||||
}
|
||||
|
||||
PendingEntry pendingEntry = scope PendingEntry(kind, name);
|
||||
PendingEntry* entryPtr;
|
||||
if (mChildren.Add(pendingEntry, out entryPtr))
|
||||
{
|
||||
let child = new PendingEntry(kind, new String(name));
|
||||
if (mKind != .Root)
|
||||
child.mParent = this;
|
||||
Debug.Assert(child != (Object)this);
|
||||
*entryPtr = child;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (kind > (*entryPtr).mKind)
|
||||
(*entryPtr).mKind = kind;
|
||||
}
|
||||
pendingEntry.Detach();
|
||||
return *entryPtr;
|
||||
}
|
||||
|
||||
public void Sort()
|
||||
{
|
||||
if (mChildren == null)
|
||||
return;
|
||||
|
||||
mSortedList = new List<PendingEntry>();
|
||||
for (var entry in mChildren)
|
||||
{
|
||||
entry.Sort();
|
||||
mSortedList.Add(entry);
|
||||
}
|
||||
mSortedList.Sort(scope (a, b) =>
|
||||
{
|
||||
DataKind lk = a.mKind;
|
||||
DataKind rk = b.mKind;
|
||||
if (lk < .Field)
|
||||
lk = .ValueType;
|
||||
if (rk < .Field)
|
||||
rk = .ValueType;
|
||||
int comp = lk <=> rk;
|
||||
if (comp != 0)
|
||||
return comp;
|
||||
return a.mName.CompareTo(b.mName, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public enum DataKind
|
||||
{
|
||||
Root,
|
||||
Project,
|
||||
Globals,
|
||||
Namespace,
|
||||
Interface,
|
||||
Class,
|
||||
ValueType,
|
||||
|
||||
Field,
|
||||
Property,
|
||||
Method
|
||||
}
|
||||
|
||||
class PendingInfo
|
||||
{
|
||||
public PendingEntry mPendingRoot ~ delete _;
|
||||
public String mTypeStr ~ delete _;
|
||||
public String mSearchStr ~ delete _;
|
||||
public WaitEvent mDoneEvent = new .() ~ delete _;
|
||||
}
|
||||
|
||||
public DarkDockingFrame mDockingFrame;
|
||||
public DarkEditWidget mSearchEdit;
|
||||
public ClassViewListView mTypeLV;
|
||||
public ClassViewListView mMemberLV;
|
||||
public int32 mLastCompileRevision;
|
||||
public int32 mCompileRevisionDirtyDelay;
|
||||
public bool mTypesDirty = true;
|
||||
public bool mMembersDirty = true;
|
||||
public int32 mWorkWait = -1;
|
||||
public bool mWantsSubmit;
|
||||
|
||||
public String mRequestedTypeName = new .() ~ delete _;
|
||||
public String mRequestedSearchStr = new .() ~ delete _;
|
||||
PendingInfo mPendingInfo ~ delete _;
|
||||
public List<PendingEntry> mHiddenEntries = new .() ~ DeleteContainerAndItems!(_);
|
||||
public FindClassDialog mFindClassDialog;
|
||||
|
||||
public this(FindClassDialog findClassDialog = null)
|
||||
{
|
||||
mFindClassDialog = findClassDialog;
|
||||
mSearchEdit = new DarkEditWidget();
|
||||
mSearchEdit.mOnKeyDown.Add(new (evt) =>
|
||||
{
|
||||
if ((evt.mKeyCode == .Tab) && (evt.mKeyFlags == 0))
|
||||
{
|
||||
mTypeLV.SetFocus();
|
||||
}
|
||||
});
|
||||
|
||||
mTypeLV = new ClassViewListView();
|
||||
mTypeLV.mPanel = this;
|
||||
mTypeLV.SetShowHeader(false);
|
||||
mTypeLV.InitScrollbars(true, true);
|
||||
mTypeLV.mOnFocusChanged.Add(new => FocusChangedHandler);
|
||||
mTypeLV.mOnItemMouseDown.Add(new => ItemMouseDown);
|
||||
mTypeLV.mOnItemMouseClicked.Add(new => ListViewItemMouseClicked);
|
||||
mTypeLV.mOnKeyDown.Add(new => ListViewKeyDown_ShowMenu);
|
||||
|
||||
if (mFindClassDialog == null)
|
||||
{
|
||||
mMemberLV = new ClassViewListView();
|
||||
mMemberLV.mPanel = this;
|
||||
mMemberLV.SetShowHeader(false);
|
||||
mMemberLV.InitScrollbars(true, true);
|
||||
mMemberLV.mOnItemMouseDown.Add(new => ItemMouseDown);
|
||||
mMemberLV.mOnItemMouseClicked.Add(new => ListViewItemMouseClicked);
|
||||
mMemberLV.mOnKeyDown.Add(new => ListViewKeyDown_ShowMenu);
|
||||
|
||||
var typeDock = new TypeArea();
|
||||
typeDock.mPanel = this;
|
||||
typeDock.AddWidget(mSearchEdit);
|
||||
typeDock.AddWidget(mTypeLV);
|
||||
var memberDock = new DockingProxy(mMemberLV);
|
||||
|
||||
mDockingFrame = new DarkDockingFrame();
|
||||
mDockingFrame.mDrawBkg = false;
|
||||
mDockingFrame.AddDockedWidget(typeDock, null, .Top);
|
||||
mDockingFrame.AddDockedWidget(memberDock, typeDock, .Bottom);
|
||||
AddWidget(mDockingFrame);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddWidget(mTypeLV);
|
||||
AddWidget(mSearchEdit);
|
||||
|
||||
mFindClassDialog.[Friend]mTabWidgets.Add(mTypeLV);
|
||||
mFindClassDialog.[Friend]mTabWidgets.Add(mSearchEdit);
|
||||
|
||||
mSearchEdit.mOnKeyDown.Add(new => EditKeyDownHandler);
|
||||
mSearchEdit.mOnSubmit.Add(new (evt) =>
|
||||
{
|
||||
mWantsSubmit = true;
|
||||
});
|
||||
}
|
||||
|
||||
//mListView.mDragEndHandler.Add(new => HandleDragEnd);
|
||||
//mListView.mDragUpdateHandler.Add(new => HandleDragUpdate);
|
||||
|
||||
mTypeLV.mOnMouseDown.Add(new => ListViewMouseDown);
|
||||
|
||||
/*ListViewColumn column = mTypeLV.AddColumn(100, "Name");
|
||||
column.mMinWidth = 40;*/
|
||||
|
||||
SetScaleData();
|
||||
|
||||
/*ListView lv = new MemberListView();
|
||||
AddWidget(lv);
|
||||
lv.Resize(100, 100, 300, 300);
|
||||
let lvItem = lv.GetRoot().CreateChildItem();
|
||||
lvItem.Label = "Yoofster";
|
||||
lvItem.Focused = true;*/
|
||||
}
|
||||
|
||||
public ~this()
|
||||
{
|
||||
if (mPendingInfo != null)
|
||||
mPendingInfo.mDoneEvent.WaitFor();
|
||||
}
|
||||
|
||||
void EditKeyDownHandler(KeyDownEvent evt)
|
||||
{
|
||||
switch (evt.mKeyCode)
|
||||
{
|
||||
case .Up,
|
||||
.Down,
|
||||
.Left,
|
||||
.Right,
|
||||
.PageUp,
|
||||
.PageDown:
|
||||
mTypeLV.KeyDown(evt.mKeyCode, false);
|
||||
default:
|
||||
}
|
||||
|
||||
if (evt.mKeyFlags == .Ctrl)
|
||||
{
|
||||
switch (evt.mKeyCode)
|
||||
{
|
||||
case .Home,
|
||||
.End:
|
||||
mTypeLV.KeyDown(evt.mKeyCode, false);
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SetScaleData()
|
||||
{
|
||||
//mTypeLV.mColumns[0].mMinWidth = GS!(40);
|
||||
|
||||
mTypeLV.mIconX = GS!(20);
|
||||
mTypeLV.mOpenButtonX = GS!(4);
|
||||
mTypeLV.mLabelX = GS!(44);
|
||||
mTypeLV.mChildIndent = GS!(16);
|
||||
mTypeLV.mHiliteOffset = GS!(-2);
|
||||
|
||||
if (mMemberLV != null)
|
||||
{
|
||||
mMemberLV.mIconX = GS!(20);
|
||||
mMemberLV.mOpenButtonX = GS!(4);
|
||||
mMemberLV.mLabelX = GS!(44);
|
||||
mMemberLV.mChildIndent = GS!(16);
|
||||
mMemberLV.mHiliteOffset = GS!(-2);
|
||||
}
|
||||
}
|
||||
|
||||
public override void RehupScale(float oldScale, float newScale)
|
||||
{
|
||||
base.RehupScale(oldScale, newScale);
|
||||
SetScaleData();
|
||||
}
|
||||
|
||||
public override void FocusForKeyboard()
|
||||
{
|
||||
base.FocusForKeyboard();
|
||||
mTypeLV.SetFocus();
|
||||
}
|
||||
|
||||
public void StartRebuildUI()
|
||||
{
|
||||
Debug.Assert(mPendingInfo.mPendingRoot == null);
|
||||
mPendingInfo.mPendingRoot = new .();
|
||||
|
||||
for (var project in IDEApp.sApp.mWorkspace.mProjects)
|
||||
{
|
||||
mPendingInfo.mPendingRoot.AddChild(.Project, project.mProjectName);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Serialize(StructuredData data)
|
||||
{
|
||||
base.Serialize(data);
|
||||
|
||||
data.Add("Type", "ClassViewPanel");
|
||||
}
|
||||
|
||||
public override bool Deserialize(StructuredData data)
|
||||
{
|
||||
return base.Deserialize(data);
|
||||
}
|
||||
|
||||
void FocusChangedHandler(ListViewItem listViewItem)
|
||||
{
|
||||
if (listViewItem.Focused)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void ShowRightClickMenu(ProjectItem projectItem, float x, float y)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool GetName(PendingEntry entry, String name)
|
||||
{
|
||||
if (entry.mParent != null)
|
||||
{
|
||||
if (GetName(entry.mParent, name))
|
||||
name.Append(".");
|
||||
}
|
||||
|
||||
if (entry.mKind == .Project)
|
||||
{
|
||||
name.Append(entry.mName);
|
||||
name.Append(":");
|
||||
return false;
|
||||
}
|
||||
|
||||
name.Append(entry.mName);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GetName(ClassViewListViewItem item, String name)
|
||||
{
|
||||
if (item == null)
|
||||
return false;
|
||||
|
||||
if (item.mMemberInfo != null)
|
||||
return GetName(item.mMemberInfo, name);
|
||||
|
||||
if (item.mKind == .Project)
|
||||
{
|
||||
name.Append(item.mLabel);
|
||||
name.Append(":");
|
||||
return false;
|
||||
}
|
||||
let parentItem = (ClassViewListViewItem)item.mParentItem;
|
||||
if (GetName(parentItem, name))
|
||||
name.Append(".");
|
||||
name.Append(item.mLabel);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ShowItem(ClassViewListViewItem item)
|
||||
{
|
||||
void Show(String file, int line, int column)
|
||||
{
|
||||
gApp.RecordHistoryLocation(true);
|
||||
gApp.ShowSourceFileLocation(file, -1, -1, line, column, .Always);
|
||||
if (mFindClassDialog != null)
|
||||
mFindClassDialog.Close();
|
||||
}
|
||||
|
||||
if (item.mMemberInfo != null)
|
||||
{
|
||||
let info = item.mMemberInfo;
|
||||
if (info.mFile != null)
|
||||
{
|
||||
Show(info.mFile, info.mLine, info.mColumn);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
String typeName = scope .();
|
||||
GetName(item, typeName);
|
||||
String info = scope .();
|
||||
gApp.mBfResolveCompiler.GetTypeDefInfo(typeName, info);
|
||||
|
||||
for (let str in info.Split('\n'))
|
||||
{
|
||||
if (str.IsEmpty)
|
||||
continue;
|
||||
if (str[0] == 'S')
|
||||
{
|
||||
var srcInfo = str.Substring(1).Split('\t');
|
||||
let filePath = srcInfo.GetNext().Get();
|
||||
int lineNum = int.Parse(srcInfo.GetNext());
|
||||
int column = int.Parse(srcInfo.GetNext());
|
||||
Show(scope String()..Append(filePath), lineNum, column);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void ItemMouseDown(ListViewItem item, float x, float y, int32 btnNum, int32 btnCount)
|
||||
{
|
||||
ListViewItemMouseDown(item, x, y, btnNum, btnCount);
|
||||
let baseItem = (ClassViewListViewItem)item.GetSubItem(0);
|
||||
if ((btnNum == 0) && (btnCount == 2))
|
||||
{
|
||||
ShowItem(baseItem);
|
||||
}
|
||||
}
|
||||
|
||||
void ListViewMouseDown(MouseEvent theEvent)
|
||||
{
|
||||
// We clicked off all items, so deselect
|
||||
mTypeLV.GetRoot().WithSelectedItems(scope (item) => { item.Selected = false; } );
|
||||
|
||||
if (theEvent.mBtn == 1)
|
||||
{
|
||||
float aX, aY;
|
||||
theEvent.GetRootCoords(out aX, out aY);
|
||||
ShowRightClickMenu(null, aX, aY);
|
||||
}
|
||||
}
|
||||
|
||||
void ParseTypeInfo(String str)
|
||||
{
|
||||
List<PendingEntry> projectEntries = scope List<PendingEntry>();
|
||||
PendingEntry curProject = null;
|
||||
|
||||
List<PendingEntry> partialRefs = scope List<PendingEntry>();
|
||||
|
||||
for (var subStrRef in str.Split('\n'))
|
||||
{
|
||||
String param = scope String();
|
||||
param.Reference(subStrRef);
|
||||
if (param.Length == 0)
|
||||
continue;
|
||||
|
||||
char8 cmd = param[0];
|
||||
param.AdjustPtr(1);
|
||||
|
||||
if (cmd == 'S')
|
||||
continue;
|
||||
|
||||
int addIdx = -1;
|
||||
PendingEntry parentEntry = null;
|
||||
|
||||
if (cmd == '>')
|
||||
{
|
||||
int atPos = param.IndexOf('@');
|
||||
addIdx = int.Parse(StringView(param, 0, atPos)).Get();
|
||||
param.AdjustPtr(atPos + 1);
|
||||
cmd = param[0];
|
||||
param.AdjustPtr(1);
|
||||
}
|
||||
else if (cmd == '<')
|
||||
{
|
||||
int atPos = param.IndexOf('@');
|
||||
int refIdx = int.Parse(StringView(param, 0, atPos)).Get();
|
||||
parentEntry = partialRefs[refIdx];
|
||||
param.AdjustPtr(atPos + 1);
|
||||
cmd = param[0];
|
||||
param.AdjustPtr(1);
|
||||
}
|
||||
else if (cmd == ':')
|
||||
{
|
||||
parentEntry = mPendingInfo.mPendingRoot;
|
||||
cmd = param[0];
|
||||
param.AdjustPtr(1);
|
||||
}
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case '=':
|
||||
int32 idx = int32.Parse(param);
|
||||
curProject = projectEntries[idx];
|
||||
case '+':
|
||||
curProject = mPendingInfo.mPendingRoot.AddChild(.Project, param);
|
||||
projectEntries.Add(curProject);
|
||||
if (mPendingInfo.mSearchStr != null)
|
||||
curProject.mShow = false;
|
||||
case 'i', 'c', 'v', 'g':
|
||||
var curEntry = curProject;
|
||||
|
||||
DataKind kind = .ValueType;
|
||||
if (cmd == 'i')
|
||||
kind = .Interface;
|
||||
else if (cmd == 'c')
|
||||
kind = .Class;
|
||||
|
||||
if (parentEntry != null)
|
||||
{
|
||||
if (parentEntry == (Object)mPendingInfo.mPendingRoot)
|
||||
{
|
||||
curEntry = parentEntry.AddChild(kind, param);
|
||||
curEntry.mParent = curProject;
|
||||
break;
|
||||
}
|
||||
|
||||
if (parentEntry.mName == param)
|
||||
{
|
||||
parentEntry.mKind = kind;
|
||||
break;
|
||||
}
|
||||
|
||||
param.AdjustPtr(parentEntry.mName.Length + 1);
|
||||
curEntry = parentEntry;
|
||||
}
|
||||
|
||||
int nameIdx = 0;
|
||||
for (var subName in param.Split('.'))
|
||||
{
|
||||
if (nameIdx < addIdx)
|
||||
{
|
||||
nameIdx++;
|
||||
continue;
|
||||
}
|
||||
|
||||
String subNameStr = scope String();
|
||||
|
||||
if (nameIdx == addIdx)
|
||||
{
|
||||
subNameStr.Reference(StringView(param, 0, @subName.MatchPos));
|
||||
curEntry = mPendingInfo.mPendingRoot.AddChild(kind, subNameStr);
|
||||
curEntry.mParent = curProject;
|
||||
Debug.Assert(curProject != (Object)curEntry);
|
||||
partialRefs.Add(curEntry);
|
||||
nameIdx++;
|
||||
addIdx = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
DataKind insertKind = kind;
|
||||
bool isLast = subName.Ptr + subName.Length == param.Ptr + param.Length;
|
||||
if (!isLast)
|
||||
{
|
||||
char8 nextChar = subName.Ptr[subName.Length];
|
||||
if (nextChar == '.')
|
||||
insertKind = .Namespace;
|
||||
}
|
||||
|
||||
subNameStr.Reference(subName);
|
||||
curEntry = curEntry.AddChild(insertKind, subNameStr);
|
||||
|
||||
nameIdx++;
|
||||
}
|
||||
default:
|
||||
DataKind kind = default;
|
||||
switch (cmd)
|
||||
{
|
||||
case 'I': kind = .Interface;
|
||||
case 'C': kind = .Class;
|
||||
case 'V': kind = .ValueType;
|
||||
case 'F': kind = .Field;
|
||||
case 'P': kind = .Property;
|
||||
case 'M': kind = .Method;
|
||||
}
|
||||
var itr = param.Split('\t');
|
||||
let entry = mPendingInfo.mPendingRoot.AddChild(kind, scope String()..Reference(itr.GetNext().Get()));
|
||||
if (entry.mFile == null)
|
||||
{
|
||||
if (itr.GetNext() case .Ok(let fileName))
|
||||
{
|
||||
entry.mFile = new String(fileName);
|
||||
entry.mLine = int.Parse(itr.GetNext()).Get();
|
||||
entry.mColumn = int.Parse(itr.GetNext()).Get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Assert(addIdx == -1);
|
||||
}
|
||||
|
||||
mPendingInfo.mPendingRoot.Sort();
|
||||
}
|
||||
|
||||
void BkgGetTypeList()
|
||||
{
|
||||
var bfSystem = gApp.mBfResolveSystem;
|
||||
var bfCompiler = gApp.mBfResolveCompiler;
|
||||
|
||||
bfSystem.Lock(0);
|
||||
String outStr = scope String();
|
||||
if (mPendingInfo.mSearchStr != null)
|
||||
bfCompiler.GetTypeDefMatches(mPendingInfo.mSearchStr, outStr);
|
||||
else
|
||||
bfCompiler.GetTypeDefList(outStr);
|
||||
bfSystem.Unlock();
|
||||
|
||||
ParseTypeInfo(outStr);
|
||||
|
||||
mPendingInfo.mDoneEvent.Set();
|
||||
}
|
||||
|
||||
void BkgGetTypeInfo()
|
||||
{
|
||||
var bfSystem = gApp.mBfResolveSystem;
|
||||
var bfCompiler = gApp.mBfResolveCompiler;
|
||||
|
||||
bfSystem.Lock(0);
|
||||
String info = scope .();
|
||||
bfCompiler.GetTypeDefInfo(mPendingInfo.mTypeStr, info);
|
||||
bfSystem.Unlock();
|
||||
ParseTypeInfo(info);
|
||||
|
||||
mPendingInfo.mDoneEvent.Set();
|
||||
}
|
||||
|
||||
void HandleEntries(ClassViewListViewItem listViewItem, PendingEntry pendingEntry)
|
||||
{
|
||||
int32 curIdx = 0;
|
||||
|
||||
if (pendingEntry.mSortedList != null)
|
||||
{
|
||||
for (var child in pendingEntry.mSortedList)
|
||||
{
|
||||
if (!child.mShow)
|
||||
{
|
||||
@child.Current = null;
|
||||
mHiddenEntries.Add(child);
|
||||
continue;
|
||||
}
|
||||
|
||||
ClassViewListViewItem childListViewItem;
|
||||
if (curIdx < listViewItem.GetChildCount())
|
||||
{
|
||||
childListViewItem = (ClassViewListViewItem)listViewItem.GetChildAtIndex(curIdx);
|
||||
}
|
||||
else
|
||||
{
|
||||
childListViewItem = (ClassViewListViewItem)listViewItem.CreateChildItem();
|
||||
}
|
||||
childListViewItem.Label = child.mName;
|
||||
childListViewItem.mRefObject = pendingEntry.mRefObject;
|
||||
childListViewItem.mOpenOnDoubleClick = false;
|
||||
childListViewItem.mKind = child.mKind;
|
||||
DeleteAndNullify!(childListViewItem.mMemberInfo);
|
||||
//if (child.mFile != null)
|
||||
{
|
||||
childListViewItem.mMemberInfo = child;
|
||||
@child.Current = null;
|
||||
}
|
||||
|
||||
childListViewItem.Init();
|
||||
|
||||
HandleEntries(childListViewItem, child);
|
||||
curIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
while (curIdx < listViewItem.GetChildCount())
|
||||
listViewItem.RemoveChildItemAt(curIdx);
|
||||
listViewItem.TryUnmakeParent();
|
||||
}
|
||||
|
||||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
var focusedItem = (ClassViewListViewItem)mTypeLV.GetRoot().FindFocusedItem();
|
||||
var focusedStr = scope String();
|
||||
if (focusedItem != null)
|
||||
GetName(focusedItem, focusedStr);
|
||||
|
||||
int32 compileRevision = gApp.mBfResolveCompiler.GetCompileRevision();
|
||||
if (mLastCompileRevision != compileRevision)
|
||||
{
|
||||
mCompileRevisionDirtyDelay = 30;
|
||||
mLastCompileRevision = compileRevision;
|
||||
}
|
||||
|
||||
if ((mCompileRevisionDirtyDelay > 0) && (--mCompileRevisionDirtyDelay == 0))
|
||||
{
|
||||
mTypesDirty = true;
|
||||
mMembersDirty = true;
|
||||
}
|
||||
|
||||
var searchStr = scope String();
|
||||
mSearchEdit.GetText(searchStr);
|
||||
searchStr.Trim();
|
||||
|
||||
if (mPendingInfo != null)
|
||||
{
|
||||
mWorkWait++;
|
||||
if (gApp.mUpdateCnt % 10 == 0)
|
||||
MarkDirty();
|
||||
if (mPendingInfo.mDoneEvent.WaitFor(0))
|
||||
{
|
||||
if (mPendingInfo.mTypeStr != null)
|
||||
{
|
||||
if (mPendingInfo.mTypeStr == focusedStr)
|
||||
HandleEntries((ClassViewListViewItem)mMemberLV.GetRoot(), mPendingInfo.mPendingRoot);
|
||||
}
|
||||
else if (mPendingInfo.mPendingRoot != null)
|
||||
{
|
||||
ClearAndDeleteItems(mHiddenEntries);
|
||||
HandleEntries((ClassViewListViewItem)mTypeLV.GetRoot(), mPendingInfo.mPendingRoot);
|
||||
focusedItem = (ClassViewListViewItem)mTypeLV.GetRoot().FindFocusedItem();
|
||||
if ((focusedItem == null) && (mTypeLV.GetRoot().GetChildCount() != 0))
|
||||
{
|
||||
mTypeLV.GetRoot().GetChildAtIndex(0).Focused = true;
|
||||
}
|
||||
}
|
||||
|
||||
DeleteAndNullify!(mPendingInfo);
|
||||
mWorkWait = -1;
|
||||
MarkDirty();
|
||||
}
|
||||
}
|
||||
|
||||
if (mPendingInfo == null)
|
||||
{
|
||||
bool TryStartWork()
|
||||
{
|
||||
mWorkWait++;
|
||||
return !gApp.mBfResolveCompiler.IsPerformingBackgroundOperation();
|
||||
}
|
||||
|
||||
if (!searchStr.IsEmpty)
|
||||
{
|
||||
bool hasFocus = mHasFocus;
|
||||
if ((mWidgetWindow.mFocusWidget != null) && (mWidgetWindow.mFocusWidget.HasParent(this)))
|
||||
hasFocus = true;
|
||||
if ((searchStr != mRequestedSearchStr) ||
|
||||
((mTypesDirty) && (hasFocus)))
|
||||
{
|
||||
if (TryStartWork())
|
||||
{
|
||||
mPendingInfo = new .();
|
||||
mPendingInfo.mPendingRoot = new .();
|
||||
mPendingInfo.mSearchStr = new String(searchStr);
|
||||
gApp.mBfResolveCompiler.DoBackground(new => BkgGetTypeList);
|
||||
mRequestedSearchStr.Set(searchStr);
|
||||
mTypesDirty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((searchStr != mRequestedSearchStr) || (mTypesDirty))
|
||||
{
|
||||
if (TryStartWork())
|
||||
{
|
||||
mPendingInfo = new .();
|
||||
StartRebuildUI();
|
||||
//Debug.WriteLine("Rebuilding UI...");
|
||||
gApp.mBfResolveCompiler.DoBackground(new => BkgGetTypeList);
|
||||
mRequestedSearchStr.Set(searchStr);
|
||||
mTypesDirty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((mPendingInfo == null) && (mMemberLV != null))
|
||||
{
|
||||
if ((mRequestedTypeName != focusedStr) || (mMembersDirty))
|
||||
{
|
||||
if (TryStartWork())
|
||||
{
|
||||
mPendingInfo = new PendingInfo();
|
||||
mPendingInfo.mTypeStr = new String(focusedStr);
|
||||
mPendingInfo.mPendingRoot = new .();
|
||||
gApp.mBfResolveCompiler.DoBackground(new => BkgGetTypeInfo);
|
||||
mRequestedTypeName.Set(focusedStr);
|
||||
mMembersDirty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mWorkWait == -1)
|
||||
{
|
||||
if (mWantsSubmit)
|
||||
mTypeLV.KeyDown(.Return, false);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Resize(float x, float y, float width, float height)
|
||||
{
|
||||
base.Resize(x, y, width, height);
|
||||
if (mDockingFrame != null)
|
||||
mDockingFrame.Resize(0, 0, mWidth, mHeight);
|
||||
else
|
||||
{
|
||||
float insetSize = GS!(6);
|
||||
mTypeLV.Resize(GS!(6), GS!(6), mWidth - GS!(12), mHeight - GS!(32));
|
||||
mSearchEdit.Resize(insetSize, mTypeLV.mY + mTypeLV.mHeight + insetSize, mWidth - insetSize - insetSize, GS!(22));
|
||||
}
|
||||
}
|
||||
|
||||
public override void DrawAll(Graphics g)
|
||||
{
|
||||
base.DrawAll(g);
|
||||
|
||||
void DrawRefresh(Widget widget, int life)
|
||||
{
|
||||
widget.SelfToOtherTranslate(this, 0, 0, var x, var y);
|
||||
|
||||
using (g.PushColor(0x60505050))
|
||||
g.FillRect(x, y, widget.Width, widget.Height);
|
||||
IDEUtils.DrawWait(g, x + widget.Width/2, y + widget.Height/2, life);
|
||||
}
|
||||
|
||||
if (mWorkWait >= 30)
|
||||
{
|
||||
bool hasFocus = mHasFocus;
|
||||
if ((mWidgetWindow.mFocusWidget != null) && (mWidgetWindow.mFocusWidget.HasParent(this)))
|
||||
hasFocus = true;
|
||||
bool hasContent = (mTypeLV.GetRoot().GetChildCount() > 0) || (!mSearchEdit.IsWhiteSpace());
|
||||
if ((hasFocus) || (!hasContent))
|
||||
{
|
||||
if (mPendingInfo?.mTypeStr != null)
|
||||
DrawRefresh(mMemberLV, mUpdateCnt);
|
||||
else
|
||||
DrawRefresh(mTypeLV, mUpdateCnt);
|
||||
}
|
||||
}
|
||||
|
||||
if (mFindClassDialog != null)
|
||||
IDEUtils.DrawOutline(g, mTypeLV);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue