1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 12:32:20 +02:00
Beef/IDE/src/ui/NavigationBar.bf
2021-01-20 13:07:22 -08:00

266 lines
7.8 KiB
Beef

using System;
using System.Collections;
using System.Text;
using System.Threading.Tasks;
using Beefy.events;
using Beefy.gfx;
using Beefy.theme.dark;
using Beefy.widgets;
using IDE.Compiler;
using System.Diagnostics;
namespace IDE.ui
{
class NavigationBar : DarkComboBox
{
enum EntryType
{
Unknown,
Method,
ExtMethod,
Property,
Class,
Enum,
Struct,
TypeAlias
}
class Entry
{
public String mText ~ delete _;
public EntryType mEntryType;
public int32 mLine;
public int32 mLineChar;
}
public static Dictionary<String, int32> sMRU = new Dictionary<String, int32>() ~ delete _;
public static int32 sCurrentMRUIndex = 1;
SourceViewPanel mSourceViewPanel;
List<Entry> mEntries = new List<Entry>() ~ DeleteContainerAndItems!(_);
List<Entry> mShownEntries = new List<Entry>() ~ delete _;
String mFilterString ~ delete _;
String mCurLocation = new String() ~ delete _;
bool mIgnoreChange = false;
public this(SourceViewPanel sourceViewPanel)
{
mSourceViewPanel = sourceViewPanel;
mLabelAlign = FontAlign.Left;
Label = "";
mLabelX = GS!(16);
mPopulateMenuAction.Add(new => PopulateNavigationBar);
MakeEditable();
mEditWidget.mOnContentChanged.Add(new => NavigationBarChanged);
mEditWidget.mOnKeyDown.Add(new => EditKeyDownHandler);
mEditWidget.mOnGotFocus.Add(new (widget) => mEditWidget.mEditWidgetContent.SelectAll());
mEditWidget.mEditWidgetContent.mWantsUndo = false;
mFocusDropdown = false;
}
public ~this()
{
}
static ~this()
{
for (var key in sMRU.Keys)
delete key;
}
public void SetLocation(String location)
{
if (mCurMenuWidget == null)
{
mIgnoreChange = true;
mEditWidget.SetText(location);
// SetText can attempt to scroll to the right to make the cursor position visible. Just scroll back to the start.
mEditWidget.HorzScrollTo(0);
mIgnoreChange = false;
}
}
void EditKeyDownHandler(KeyDownEvent evt)
{
if (evt.mKeyCode == KeyCode.Escape)
mSourceViewPanel.FocusEdit();
}
void GetEntries()
{
ClearAndDeleteItems(mEntries);
ResolveParams resolveParams = scope ResolveParams();
mSourceViewPanel.Classify(ResolveType.GetNavigationData, resolveParams);
if (resolveParams.mNavigationData != null)
{
var autocompleteLines = scope List<StringView>(resolveParams.mNavigationData.Split('\n'));
autocompleteLines.Sort(scope (a, b) => StringView.Compare(a, b, true));
for (var autocompleteLineView in autocompleteLines)
{
if (autocompleteLineView.Length == 0)
continue;
Entry entry = new Entry();
int idx = 0;
for (var lineData in autocompleteLineView.Split('\t'))
{
switch (idx)
{
case 0: entry.mText = new String(lineData);
case 1:
switch(lineData)
{
case "method": entry.mEntryType = .Method;
case "extmethod": entry.mEntryType = .ExtMethod;
case "property": entry.mEntryType = .Property;
case "class": entry.mEntryType = .Class;
case "enum": entry.mEntryType = .Enum;
case "struct": entry.mEntryType = .Struct;
case "typealias": entry.mEntryType = .TypeAlias;
default:
}
case 2: entry.mLine = int32.Parse(lineData);
case 3: entry.mLineChar = int32.Parse(lineData);
}
++idx;
}
mEntries.Add(entry);
}
}
}
private void PopulateNavigationBar(Menu menu)
{
List<StringView> findStrs = null;
if (mFilterString != null)
findStrs = scope:: List<StringView>(mFilterString.Split(' '));
EntryLoop: for (int32 entryIdx = 0; entryIdx < mEntries.Count; entryIdx++)
{
var entry = mEntries[entryIdx];
if (findStrs != null)
{
for (let findStr in findStrs)
{
if (entry.mText.IndexOf(findStr, true) == -1)
continue EntryLoop;
}
}
mShownEntries.Add(entry);
var menuItem = menu.AddItem(entry.mText);
switch (entry.mEntryType)
{
case .Method: menuItem.mIconImage = DarkTheme.sDarkTheme.GetImage(.Method);
case .ExtMethod: menuItem.mIconImage = DarkTheme.sDarkTheme.GetImage(.ExtMethod);
case .Property: menuItem.mIconImage = DarkTheme.sDarkTheme.GetImage(.Property);
case .Class: menuItem.mIconImage = DarkTheme.sDarkTheme.GetImage(.Type_Class);
case .Enum: menuItem.mIconImage = DarkTheme.sDarkTheme.GetImage(.Type_ValueType);
case .Struct: menuItem.mIconImage = DarkTheme.sDarkTheme.GetImage(.Type_ValueType);
case .TypeAlias: menuItem.mIconImage = DarkTheme.sDarkTheme.GetImage(.MemoryArrowSingle);
default:
}
menuItem.mOnMenuItemSelected.Add(new (evt) => ShowEntry(entryIdx, entry));
}
}
void ShowEntry(int32 entryIdx, Entry entry)
{
//sMRU[entry.mText] = sCurrentMRUIndex++;
String* keyPtr;
int32* valPtr;
if (sMRU.TryAdd(entry.mText, out keyPtr, out valPtr))
*keyPtr = new String(entry.mText);
*valPtr = sCurrentMRUIndex++;
mSourceViewPanel.ShowFileLocation(-1, entry.mLine, entry.mLineChar, LocatorType.Always);
}
private void NavigationBarChanged(EditEvent theEvent)
{
if (mIgnoreChange)
return;
var editWidget = (EditWidget)theEvent.mSender;
var searchText = scope String();
editWidget.GetText(searchText);
searchText.Trim();
mFilterString = searchText;
ShowDropdown();
mFilterString = null;
}
bool mIgnoreShowDropdown;
public override MenuWidget ShowDropdown()
{
if (mIgnoreShowDropdown)
return null;
mIgnoreShowDropdown = true;
defer { mIgnoreShowDropdown = false; }
/*var stopWatch = scope Stopwatch();
stopWatch.Start();*/
//Profiler.StartSampling();
if (!mEditWidget.mHasFocus)
SetFocus();
if (mCurMenuWidget == null)
GetEntries();
if (mFilterString == null)
mEditWidget.Content.SelectAll();
mShownEntries.Clear();
base.ShowDropdown();
int32 bestItem = -1;
int32 bestPri = -1;
var menuWidget = (DarkMenuWidget)mCurMenuWidget;
for (int32 itemIdx = 0; itemIdx < menuWidget.mItemWidgets.Count; itemIdx++)
{
var menuItemWidget = (DarkMenuItem)menuWidget.mItemWidgets[itemIdx];
int32 pri;
sMRU.TryGetValue(menuItemWidget.mMenuItem.mLabel, out pri);
if (pri > bestPri)
{
bestItem = itemIdx;
bestPri = pri;
}
}
if (bestItem != -1)
{
mCurMenuWidget.mOnSelectionChanged.Add(new => SelectionChanged);
mCurMenuWidget.SetSelection(bestItem);
}
//Profiler.StopSampling();
//stopWatch.Stop();
//Debug.WriteLine("Time: {0}", stopWatch.ElapsedMilliseconds);
return menuWidget;
}
void SelectionChanged(int selIdx)
{
if (mEditWidget.mEditWidgetContent.HasSelection())
{
bool prevIgnoreShowDropdown = mIgnoreShowDropdown;
mIgnoreShowDropdown = true;
mEditWidget.SetText("");
mIgnoreShowDropdown = prevIgnoreShowDropdown;
}
}
public override void MenuClosed()
{
mSourceViewPanel.FocusEdit();
}
}
}