1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 04:22:20 +02:00
Beef/IDE/src/ui/ClassViewPanel.bf
2021-02-25 10:14:22 -08:00

1051 lines
26 KiB
Beef

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;
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 _;
public bool mProcessedLabel;
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)
{
if ((!mProcessedLabel) && (mLabel != null))
{
uint32 color = 0;
switch (mMemberInfo.mKind)
{
case .Globals:
/*color = SourceEditWidgetContent.sTextColors[(int32)SourceElementType.Identifier];
color = Color.Mult(color, Color.Get(0.8f));*/
case .Namespace:
color = SourceEditWidgetContent.sTextColors[(int32)SourceElementType.Namespace];
case .Interface,
.Class,
.ValueType:
IDEUtils.ColorizeCodeString(mLabel, .Type);
case .Field,
.Property:
IDEUtils.ColorizeCodeString(mLabel, .Field);
case .Method,
.MethodOverride:
IDEUtils.ColorizeCodeString(mLabel, .Method);
default:
}
if (color != 0)
IDEUtils.InsertColorChange(mLabel, 0, color);
mProcessedLabel = true;
}
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,
.MethodOverride:
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;
}
[Commutable]
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)
{
if ((val1.mKind == .Project) || (val2.mKind == .Project))
return false;
if ((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,
MethodOverride,
}
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>();
char8[] seps = scope char8[] ('.', '+');
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;
else if (cmd == 'g')
kind = .Globals;
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(seps))
{
if (nameIdx < addIdx)
{
nameIdx++;
continue;
}
String subNameStr = scope String();
bool isLast = subName.Ptr + subName.Length == param.Ptr + param.Length;
if (nameIdx == addIdx)
{
DataKind insertKind = isLast ? kind : .Namespace;
subNameStr.Reference(StringView(param, 0, @subName.MatchPos));
curEntry = mPendingInfo.mPendingRoot.AddChild(insertKind, subNameStr);
curEntry.mParent = curProject;
Debug.Assert(curProject != (Object)curEntry);
partialRefs.Add(curEntry);
nameIdx++;
addIdx = -1;
continue;
}
DataKind insertKind = kind;
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;
case 'o': kind = .MethodOverride;
}
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);
if (!entry.mFile.IsEmpty)
{
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;
childListViewItem.mProcessedLabel = false;
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();
if (gApp.mBfResolveCompiler == null)
return;
var focusedItem = (ClassViewListViewItem)mTypeLV.GetRoot().FindFocusedItem();
var focusedStr = scope String();
if (focusedItem != null)
GetName(focusedItem, focusedStr);
if (gApp.mBfResolveCompiler != null)
{
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);
mWantsSubmit = 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);
}
}
}