mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 20:42:21 +02:00
870 lines
22 KiB
Beef
870 lines
22 KiB
Beef
![]() |
using Beefy.theme.dark;
|
||
|
using Beefy.widgets;
|
||
|
using System;
|
||
|
using System.Collections;
|
||
|
using Beefy.gfx;
|
||
|
using Beefy.events;
|
||
|
using IDE.Compiler;
|
||
|
using System.Threading;
|
||
|
using System.Security.Cryptography;
|
||
|
using Beefy.theme;
|
||
|
|
||
|
namespace IDE.ui
|
||
|
{
|
||
|
class GenerateListView : DarkListView
|
||
|
{
|
||
|
public GenerateDialog mNewClassDialog;
|
||
|
}
|
||
|
|
||
|
class GenerateKindBar : DarkComboBox
|
||
|
{
|
||
|
public class Entry
|
||
|
{
|
||
|
public String mTypeName ~ delete _;
|
||
|
public String mName ~ delete _;
|
||
|
}
|
||
|
|
||
|
public static Dictionary<String, int32> sMRU = new Dictionary<String, int32>() ~ delete _;
|
||
|
public static int32 sCurrentMRUIndex = 1;
|
||
|
|
||
|
public GenerateDialog mNewClassDialog;
|
||
|
public List<Entry> mEntries = new List<Entry>() ~ DeleteContainerAndItems!(_);
|
||
|
public List<Entry> mShownEntries = new List<Entry>() ~ delete _;
|
||
|
public String mFilterString ~ delete _;
|
||
|
public String mCurLocation = new String() ~ delete _;
|
||
|
public bool mIgnoreChange = false;
|
||
|
|
||
|
public this(GenerateDialog dialog)
|
||
|
{
|
||
|
mNewClassDialog = dialog;
|
||
|
mLabelAlign = FontAlign.Left;
|
||
|
Label = "";
|
||
|
mLabelX = GS!(16);
|
||
|
mPopulateMenuAction.Add(new => PopulateNavigationBar);
|
||
|
MakeEditable();
|
||
|
mEditWidget.mOnContentChanged.Add(new => NavigationBarChanged);
|
||
|
mEditWidget.mOnGotFocus.Add(new (widget) => mEditWidget.mEditWidgetContent.SelectAll());
|
||
|
mEditWidget.mEditWidgetContent.mWantsUndo = false;
|
||
|
mEditWidget.mOnSubmit.Add(new => mNewClassDialog.[Friend]EditSubmitHandler);
|
||
|
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);
|
||
|
mEditWidget.mEditWidgetContent.SelectAll();
|
||
|
// SetText can attempt to scroll to the right to make the cursor position visible. Just scroll back to the start.
|
||
|
mEditWidget.HorzScrollTo(0);
|
||
|
//mNewClassDialog.SelectKind();
|
||
|
mIgnoreChange = false;
|
||
|
}
|
||
|
}
|
||
|
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.mName.IndexOf(findStr, true) == -1)
|
||
|
continue EntryLoop;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
mShownEntries.Add(entry);
|
||
|
var menuItem = menu.AddItem(entry.mName);
|
||
|
menuItem.mOnMenuItemSelected.Add(new (evt) =>
|
||
|
{
|
||
|
mNewClassDialog.mPendingUIFocus = true;
|
||
|
ShowEntry(entryIdx, entry);
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void ShowEntry(int32 entryIdx, Entry entry)
|
||
|
{
|
||
|
mEditWidget.SetText(entry.mName);
|
||
|
mEditWidget.mEditWidgetContent.SelectAll();
|
||
|
mCurMenuWidget?.Close();
|
||
|
}
|
||
|
|
||
|
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; }
|
||
|
|
||
|
if (!mEditWidget.mHasFocus)
|
||
|
SetFocus();
|
||
|
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
return menuWidget;
|
||
|
}
|
||
|
|
||
|
void SelectionChanged(int selIdx)
|
||
|
{
|
||
|
if (mEditWidget.mEditWidgetContent.HasSelection())
|
||
|
{
|
||
|
bool prevIgnoreShowDropdown = mIgnoreShowDropdown;
|
||
|
mIgnoreShowDropdown = true;
|
||
|
mEditWidget.SetText("");
|
||
|
mIgnoreShowDropdown = prevIgnoreShowDropdown;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void MenuClosed()
|
||
|
{
|
||
|
}
|
||
|
}
|
||
|
|
||
|
class GenerateDialog : IDEDialog
|
||
|
{
|
||
|
public class UIEntry
|
||
|
{
|
||
|
public String mName ~ delete _;
|
||
|
public String mData ~ delete _;
|
||
|
public String mLabel ~ delete _;
|
||
|
public Widget mWidget;
|
||
|
}
|
||
|
|
||
|
public enum ThreadState
|
||
|
{
|
||
|
None,
|
||
|
Executing,
|
||
|
Done
|
||
|
}
|
||
|
|
||
|
public bool mPendingGenList;
|
||
|
public GenerateKindBar mKindBar;
|
||
|
public ThreadState mThreadState;
|
||
|
public int mThreadWaitCount;
|
||
|
public String mNamespace ~ delete _;
|
||
|
public String mProjectName ~ delete _;
|
||
|
public ProjectItem mProjectItem ~ _.ReleaseRef();
|
||
|
public String mFolderPath ~ delete _;
|
||
|
public List<UIEntry> mUIEntries = new .() ~ DeleteContainerAndItems!(_);
|
||
|
public GenerateKindBar.Entry mSelectedEntry;
|
||
|
public GenerateKindBar.Entry mPendingSelectedEntry;
|
||
|
public String mUIData ~ delete _;
|
||
|
public float mUIHeight = 0;
|
||
|
public OutputPanel mOutputPanel;
|
||
|
public bool mPendingUIFocus;
|
||
|
public bool mSubmitting;
|
||
|
public bool mSubmitQueued;
|
||
|
public bool mRegenerating;
|
||
|
|
||
|
public this(ProjectItem projectItem, bool allowHashMismatch = false)
|
||
|
{
|
||
|
var project = projectItem.mProject;
|
||
|
mProjectItem = projectItem;
|
||
|
mProjectItem.AddRef();
|
||
|
|
||
|
mNamespace = new .();
|
||
|
|
||
|
var projectFolder = projectItem as ProjectFolder;
|
||
|
var projectSource = projectItem as ProjectSource;
|
||
|
if (projectSource != null)
|
||
|
{
|
||
|
projectFolder = projectSource.mParentFolder;
|
||
|
mRegenerating = true;
|
||
|
}
|
||
|
|
||
|
projectFolder.GetRelDir(mNamespace); mNamespace.Replace('/', '.'); mNamespace.Replace('\\', '.'); mNamespace.Replace(" ", "");
|
||
|
if (mNamespace.StartsWith("src."))
|
||
|
{
|
||
|
mNamespace.Remove(0, 4);
|
||
|
if (!project.mBeefGlobalOptions.mDefaultNamespace.IsWhiteSpace)
|
||
|
{
|
||
|
mNamespace.Insert(0, ".");
|
||
|
mNamespace.Insert(0, project.mBeefGlobalOptions.mDefaultNamespace);
|
||
|
}
|
||
|
}
|
||
|
else if (projectItem.mParentFolder == null)
|
||
|
{
|
||
|
mNamespace.Clear();
|
||
|
mNamespace.Append(project.mBeefGlobalOptions.mDefaultNamespace);
|
||
|
}
|
||
|
else
|
||
|
mNamespace.Clear();
|
||
|
|
||
|
mFolderPath = projectFolder.GetFullImportPath(.. new .());
|
||
|
mProjectName = new String(projectItem.mProject.mProjectName);
|
||
|
|
||
|
mWindowFlags = .ClientSized | .TopMost | .Caption | .Border | .SysMenu | .Resizable | .PopupPosition;
|
||
|
|
||
|
AddOkCancelButtons(new (evt) => { CreateClass(); }, null, 0, 1);
|
||
|
|
||
|
Title = "Generate";
|
||
|
|
||
|
mKindBar = new GenerateKindBar(this);
|
||
|
AddWidget(mKindBar);
|
||
|
mKindBar.mEditWidget.mOnContentChanged.Add(new (theEvent) => { SelectKind(); });
|
||
|
|
||
|
if (mRegenerating)
|
||
|
{
|
||
|
mSubmitQueued = true;
|
||
|
mKindBar.SetVisible(false);
|
||
|
|
||
|
SourceViewPanel sourceViewPanel = gApp.ShowProjectItem(projectSource, false);
|
||
|
|
||
|
String filePath = projectSource.GetFullImportPath(.. scope .());
|
||
|
|
||
|
String text = scope .();
|
||
|
sourceViewPanel.mEditWidget.GetText(text);
|
||
|
|
||
|
StringView generatorName = default;
|
||
|
StringView hash = default;
|
||
|
|
||
|
int dataIdx = -1;
|
||
|
for (var line in text.Split('\n'))
|
||
|
{
|
||
|
if (!line.StartsWith("// "))
|
||
|
{
|
||
|
dataIdx = @line.MatchPos + 1;
|
||
|
break;
|
||
|
}
|
||
|
int eqPos = line.IndexOf('=');
|
||
|
if (eqPos == -1)
|
||
|
break;
|
||
|
StringView key = line.Substring(3, eqPos - 3);
|
||
|
StringView value = line.Substring(eqPos + 1);
|
||
|
if (key == "Generator")
|
||
|
generatorName = value;
|
||
|
else if (key == "GenHash")
|
||
|
hash = value;
|
||
|
else
|
||
|
{
|
||
|
UIEntry uiEntry = new .();
|
||
|
uiEntry.mName = new .(key);
|
||
|
uiEntry.mData = new .(value);
|
||
|
mUIEntries.Add(uiEntry);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((generatorName == default) || (hash == default))
|
||
|
{
|
||
|
Close();
|
||
|
gApp.Fail(scope $"File '{filePath}' was not generated by a generator that include regeneration information");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if ((dataIdx != -1) && (!allowHashMismatch))
|
||
|
{
|
||
|
var origHash = MD5Hash.Parse(hash).GetValueOrDefault();
|
||
|
|
||
|
StringView dataStr = text.Substring(dataIdx);
|
||
|
var checkHash = MD5.Hash(.((.)dataStr.Ptr, dataStr.Length));
|
||
|
|
||
|
if (origHash != checkHash)
|
||
|
{
|
||
|
Close();
|
||
|
Dialog dialog = ThemeFactory.mDefault.CreateDialog("Regenerate?", "This file has been modified since it was generated. Are you sure you want to regenerate?", DarkTheme.sDarkTheme.mIconWarning);
|
||
|
dialog.AddButton("Yes", new (evt) =>
|
||
|
{
|
||
|
gApp.mProjectPanel.Regenerate(true);
|
||
|
//dialog.Close();
|
||
|
});
|
||
|
dialog.AddButton("No", new (evt) =>
|
||
|
{
|
||
|
//dialog.Close();
|
||
|
});
|
||
|
dialog.PopupWindow(gApp.GetActiveWindow());
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
GenerateKindBar.Entry entry = new .();
|
||
|
entry.mName = new .(generatorName);
|
||
|
entry.mTypeName = new .(generatorName);
|
||
|
mKindBar.mEntries.Add(entry);
|
||
|
mPendingSelectedEntry = entry;
|
||
|
}
|
||
|
else
|
||
|
mPendingGenList = true;
|
||
|
|
||
|
mKindBar.mMouseVisible = false;
|
||
|
mTabWidgets.Add(mKindBar.mEditWidget);
|
||
|
}
|
||
|
|
||
|
public ~this()
|
||
|
{
|
||
|
var bfCompiler = gApp.mBfResolveCompiler;
|
||
|
if (mThreadState == .Executing)
|
||
|
{
|
||
|
bfCompiler.WaitForBackground();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void SelectKind()
|
||
|
{
|
||
|
GenerateKindBar.Entry foundEntry = null;
|
||
|
|
||
|
String text = mKindBar.mEditWidget.GetText(.. scope .());
|
||
|
for (var entry in mKindBar.mEntries)
|
||
|
if (entry.mName == text)
|
||
|
foundEntry = entry;
|
||
|
|
||
|
if (foundEntry == null)
|
||
|
return;
|
||
|
|
||
|
if (mSelectedEntry == foundEntry)
|
||
|
return;
|
||
|
|
||
|
mPendingSelectedEntry = foundEntry;
|
||
|
}
|
||
|
|
||
|
public void ThreadProc()
|
||
|
{
|
||
|
var bfSystem = gApp.mBfResolveSystem;
|
||
|
var bfCompiler = gApp.mBfResolveCompiler;
|
||
|
|
||
|
String outStr = scope String();
|
||
|
|
||
|
bfSystem.Lock(0);
|
||
|
defer bfSystem.Unlock();
|
||
|
|
||
|
if (mSelectedEntry != null)
|
||
|
{
|
||
|
String args = scope .();
|
||
|
var project = gApp.mWorkspace.FindProject(mProjectName);
|
||
|
if (project == null)
|
||
|
return;
|
||
|
using (gApp.mMonitor.Enter())
|
||
|
{
|
||
|
args.AppendF(
|
||
|
$"""
|
||
|
ProjectName\t{mProjectName}
|
||
|
ProjectDir\t{project.mProjectPath}
|
||
|
FolderDir\t{mFolderPath}
|
||
|
Namespace\t{mNamespace}
|
||
|
DefaultNamespace\t{project.mBeefGlobalOptions.mDefaultNamespace}
|
||
|
WorkspaceName\t{gApp.mWorkspace.mName}
|
||
|
WorkspaceDir\t{gApp.mWorkspace.mDir}
|
||
|
DateTime\t{DateTime.Now}
|
||
|
|
||
|
""");
|
||
|
|
||
|
if (mSubmitting)
|
||
|
{
|
||
|
args.AppendF($"Generator\t{mSelectedEntry.mTypeName}\n");
|
||
|
for (var uiEntry in mUIEntries)
|
||
|
{
|
||
|
String data = scope .();
|
||
|
if (uiEntry.mData != null)
|
||
|
{
|
||
|
data.Append(uiEntry.mData);
|
||
|
}
|
||
|
else if (var editWidget = uiEntry.mWidget as EditWidget)
|
||
|
{
|
||
|
editWidget.GetText(data);
|
||
|
}
|
||
|
else if (var comboBox = uiEntry.mWidget as DarkComboBox)
|
||
|
{
|
||
|
comboBox.GetLabel(data);
|
||
|
}
|
||
|
else if (var checkBox = uiEntry.mWidget as CheckBox)
|
||
|
{
|
||
|
checkBox.Checked.ToString(data);
|
||
|
}
|
||
|
data.Replace('\n', '\r');
|
||
|
args.AppendF($"{uiEntry.mName}\t{data}\n");
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
mUIData = new String();
|
||
|
if (mSubmitting)
|
||
|
bfCompiler.GetGeneratorGenData(mSelectedEntry.mTypeName, args, mUIData);
|
||
|
else
|
||
|
bfCompiler.GetGeneratorInitData(mSelectedEntry.mTypeName, args, mUIData);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
bfCompiler.GetGeneratorTypeDefList(outStr);
|
||
|
|
||
|
for (var line in outStr.Split('\n', .RemoveEmptyEntries))
|
||
|
{
|
||
|
if (line.StartsWith("!error"))
|
||
|
{
|
||
|
ShowError(line.Substring(7));
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
var entry = new GenerateKindBar.Entry();
|
||
|
var partItr = line.Split('\t');
|
||
|
entry.mTypeName = new String(partItr.GetNext().Value);
|
||
|
if (partItr.GetNext() case .Ok(let val))
|
||
|
entry.mName = new String(val);
|
||
|
else
|
||
|
{
|
||
|
entry.mName = new String(entry.mTypeName);
|
||
|
int termPos = entry.mName.LastIndexOf('.');
|
||
|
if (termPos != -1)
|
||
|
entry.mName.Remove(0, termPos + 1);
|
||
|
termPos = entry.mName.LastIndexOf('+');
|
||
|
if (termPos != -1)
|
||
|
entry.mName.Remove(0, termPos + 1);
|
||
|
}
|
||
|
mKindBar.mEntries.Add(entry);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void CalcSize()
|
||
|
{
|
||
|
mWidth = GS!(320);
|
||
|
mHeight = GS!(96);
|
||
|
mMinWidth = mWidth;
|
||
|
}
|
||
|
|
||
|
protected override void RehupMinSize()
|
||
|
{
|
||
|
mWidgetWindow.SetMinimumSize(GS!(240), (.)mUIHeight + GS!(24), true);
|
||
|
}
|
||
|
|
||
|
void CreateClass()
|
||
|
{
|
||
|
//mClassViewPanel.[Friend]mSearchEdit.mOnSubmit(null);
|
||
|
}
|
||
|
|
||
|
void ShowError(StringView error)
|
||
|
{
|
||
|
if (mOutputPanel == null)
|
||
|
{
|
||
|
mOutputPanel = new OutputPanel();
|
||
|
AddWidget(mOutputPanel);
|
||
|
ResizeComponents();
|
||
|
}
|
||
|
String str = scope .();
|
||
|
str.Append(error);
|
||
|
str.Replace('\r', '\n');
|
||
|
str.Append("\n");
|
||
|
mOutputPanel.WriteSmart(str);
|
||
|
}
|
||
|
|
||
|
public override void Update()
|
||
|
{
|
||
|
base.Update();
|
||
|
|
||
|
if ((!mKindBar.mEditWidget.mHasFocus) && (mWidgetWindow.mHasFocus))
|
||
|
{
|
||
|
var sel = mPendingSelectedEntry ?? mSelectedEntry;
|
||
|
String editText = mKindBar.mEditWidget.GetText(.. scope .());
|
||
|
if ((sel != null) && (editText != sel.mName))
|
||
|
{
|
||
|
mKindBar.mIgnoreChange = true;
|
||
|
mKindBar.mEditWidget.SetText(sel.mName);
|
||
|
mKindBar.mIgnoreChange = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (mThreadState == .Done)
|
||
|
{
|
||
|
if (mSelectedEntry != null)
|
||
|
{
|
||
|
List<UIEntry> oldEntries = scope .();
|
||
|
Dictionary<String, UIEntry> entryMap = scope .();
|
||
|
if (!mSubmitting)
|
||
|
{
|
||
|
for (var uiEntry in mUIEntries)
|
||
|
{
|
||
|
if (!entryMap.TryAdd(uiEntry.mName, uiEntry))
|
||
|
oldEntries.Add(uiEntry);
|
||
|
}
|
||
|
mUIEntries.Clear();
|
||
|
}
|
||
|
|
||
|
if (mUIData != null)
|
||
|
{
|
||
|
if (mOutputPanel != null)
|
||
|
{
|
||
|
mOutputPanel.RemoveSelf();
|
||
|
DeleteAndNullify!(mOutputPanel);
|
||
|
}
|
||
|
|
||
|
String fileName = default;
|
||
|
StringView genText = default;
|
||
|
bool hadError = false;
|
||
|
|
||
|
if (mUIData.IsEmpty)
|
||
|
{
|
||
|
gApp.Fail("Generator failed to return results");
|
||
|
}
|
||
|
|
||
|
LinesLoop: for (var line in mUIData.Split('\n', .RemoveEmptyEntries))
|
||
|
{
|
||
|
var partItr = line.Split('\t');
|
||
|
var kind = partItr.GetNext().Value;
|
||
|
|
||
|
switch (kind)
|
||
|
{
|
||
|
case "!error":
|
||
|
ShowError(line.Substring(7));
|
||
|
case "addEdit":
|
||
|
if (mSubmitting)
|
||
|
break;
|
||
|
UIEntry uiEntry = new UIEntry();
|
||
|
uiEntry.mName = partItr.GetNext().Value.UnQuoteString(.. new .());
|
||
|
uiEntry.mLabel = partItr.GetNext().Value.UnQuoteString(.. new .());
|
||
|
var defaultValue = partItr.GetNext().Value.UnQuoteString(.. scope .());
|
||
|
DarkEditWidget editWidget = new DarkEditWidget();
|
||
|
uiEntry.mWidget = editWidget;
|
||
|
editWidget.SetText(defaultValue);
|
||
|
editWidget.mEditWidgetContent.SelectAll();
|
||
|
editWidget.mOnSubmit.Add(new => EditSubmitHandler);
|
||
|
AddWidget(editWidget);
|
||
|
mUIEntries.Add(uiEntry);
|
||
|
mTabWidgets.Add(editWidget);
|
||
|
case "addCombo":
|
||
|
if (mSubmitting)
|
||
|
break;
|
||
|
UIEntry uiEntry = new UIEntry();
|
||
|
uiEntry.mName = partItr.GetNext().Value.UnQuoteString(.. new .());
|
||
|
uiEntry.mLabel = partItr.GetNext().Value.UnQuoteString(.. new .());
|
||
|
var defaultValue = partItr.GetNext().Value.UnQuoteString(.. scope .());
|
||
|
List<String> choices = new List<String>();
|
||
|
DarkComboBox comboBox = new DarkComboBox();
|
||
|
while (partItr.GetNext() case .Ok(let val))
|
||
|
{
|
||
|
choices.Add(val.UnQuoteString(.. new .()));
|
||
|
}
|
||
|
comboBox.mOnDeleted.Add(new (widget) => { DeleteContainerAndItems!(choices); });
|
||
|
comboBox.mPopulateMenuAction.Add(new (menu) =>
|
||
|
{
|
||
|
for (var choice in choices)
|
||
|
{
|
||
|
var item = menu.AddItem(choice);
|
||
|
item.mOnMenuItemSelected.Add(new (menu) =>
|
||
|
{
|
||
|
comboBox.Label = menu.mLabel;
|
||
|
});
|
||
|
}
|
||
|
});
|
||
|
uiEntry.mWidget = comboBox;
|
||
|
comboBox.Label = defaultValue;
|
||
|
AddWidget(comboBox);
|
||
|
mUIEntries.Add(uiEntry);
|
||
|
mTabWidgets.Add(comboBox);
|
||
|
case "addCheckbox":
|
||
|
if (mSubmitting)
|
||
|
break;
|
||
|
UIEntry uiEntry = new UIEntry();
|
||
|
uiEntry.mName = partItr.GetNext().Value.UnQuoteString(.. new .());
|
||
|
uiEntry.mLabel = partItr.GetNext().Value.UnQuoteString(.. new .());
|
||
|
var defaultValue = partItr.GetNext().Value;
|
||
|
DarkCheckBox checkbox = new DarkCheckBox();
|
||
|
uiEntry.mWidget = checkbox;
|
||
|
checkbox.Label = uiEntry.mLabel;
|
||
|
checkbox.Checked = defaultValue == "True";
|
||
|
AddWidget(checkbox);
|
||
|
mUIEntries.Add(uiEntry);
|
||
|
mTabWidgets.Add(checkbox);
|
||
|
case "error":
|
||
|
hadError = true;
|
||
|
gApp.Fail(line.Substring(6).UnQuoteString(.. scope .()));
|
||
|
case "fileName":
|
||
|
fileName = line.Substring(9).UnQuoteString(.. scope:: .());
|
||
|
case "options":
|
||
|
case "data":
|
||
|
genText = .(mUIData, @line.MatchPos + 1);
|
||
|
break LinesLoop;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ResizeComponents();
|
||
|
RehupMinSize();
|
||
|
|
||
|
if (fileName?.EndsWith(".bf", .OrdinalIgnoreCase) == true)
|
||
|
fileName.RemoveFromEnd(3);
|
||
|
|
||
|
if ((fileName != null) && (!mRegenerating))
|
||
|
{
|
||
|
for (char8 c in fileName.RawChars)
|
||
|
{
|
||
|
if (!c.IsLetterOrDigit)
|
||
|
{
|
||
|
gApp.Fail(scope $"Invalid generated file name: {fileName}");
|
||
|
hadError = true;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (fileName.IsEmpty)
|
||
|
{
|
||
|
gApp.Fail("Geneator failed to specify file name");
|
||
|
hadError = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((!hadError) && (genText != default) && (fileName != null))
|
||
|
{
|
||
|
if (!mProjectItem.mDetached)
|
||
|
{
|
||
|
if (mRegenerating)
|
||
|
{
|
||
|
gApp.mProjectPanel.Regenerate(mProjectItem as ProjectSource, genText);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
gApp.mProjectPanel.Generate(mProjectItem as ProjectFolder, fileName, genText);
|
||
|
}
|
||
|
}
|
||
|
Close();
|
||
|
}
|
||
|
|
||
|
if (mPendingUIFocus)
|
||
|
{
|
||
|
mPendingUIFocus = false;
|
||
|
if (!mUIEntries.IsEmpty)
|
||
|
mUIEntries[0].mWidget.SetFocus();
|
||
|
}
|
||
|
|
||
|
DeleteAndNullify!(mUIData);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
|
||
|
if (mSubmitting)
|
||
|
{
|
||
|
if (!mClosed)
|
||
|
{
|
||
|
mSubmitting = false;
|
||
|
mSubmitQueued = false;
|
||
|
mDefaultButton.mDisabled = false;
|
||
|
mEscButton.mDisabled = false;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (var uiEntry in entryMap.Values)
|
||
|
oldEntries.Add(uiEntry);
|
||
|
|
||
|
for (var uiEntry in oldEntries)
|
||
|
{
|
||
|
mTabWidgets.Remove(uiEntry.mWidget);
|
||
|
uiEntry.mWidget.RemoveSelf();
|
||
|
DeleteAndNullify!(uiEntry.mWidget);
|
||
|
}
|
||
|
|
||
|
ClearAndDeleteItems(oldEntries);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
mKindBar.mMouseVisible = true;
|
||
|
mKindBar.SetFocus();
|
||
|
mKindBar.SetLocation("New Class");
|
||
|
}
|
||
|
mThreadState = .None;
|
||
|
MarkDirty();
|
||
|
}
|
||
|
|
||
|
bool isWorking = false;
|
||
|
if (mThreadState == .None)
|
||
|
{
|
||
|
if ((mPendingGenList) || (mPendingSelectedEntry != null))
|
||
|
{
|
||
|
isWorking = true;
|
||
|
var bfCompiler = gApp.mBfResolveCompiler;
|
||
|
if (!bfCompiler.IsPerformingBackgroundOperation())
|
||
|
{
|
||
|
bfCompiler.CheckThreadDone();
|
||
|
|
||
|
mPendingGenList = false;
|
||
|
if (mPendingSelectedEntry != null)
|
||
|
{
|
||
|
if (mSubmitQueued)
|
||
|
mSubmitting = true;
|
||
|
mSelectedEntry = mPendingSelectedEntry;
|
||
|
mPendingSelectedEntry = null;
|
||
|
}
|
||
|
mThreadState = .Executing;
|
||
|
bfCompiler.DoBackgroundHi(new => ThreadProc, new () =>
|
||
|
{
|
||
|
mThreadState = .Done;
|
||
|
}, false);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
gApp.mBfResolveCompiler.CheckThreadDone();
|
||
|
|
||
|
if ((mThreadState == .Executing) || (isWorking))
|
||
|
{
|
||
|
mThreadWaitCount++;
|
||
|
if (mUpdateCnt % 8 == 0)
|
||
|
MarkDirty();
|
||
|
}
|
||
|
else
|
||
|
mThreadWaitCount = 0;
|
||
|
}
|
||
|
|
||
|
public override void Resize(float x, float y, float width, float height)
|
||
|
{
|
||
|
base.Resize(x, y, width, height);
|
||
|
ResizeComponents();
|
||
|
//mClassViewPanel.Resize(0, 0, width, height - GS!(34));
|
||
|
}
|
||
|
|
||
|
public override void PopupWindow(WidgetWindow parentWindow, float offsetX = 0, float offsetY = 0)
|
||
|
{
|
||
|
base.PopupWindow(parentWindow, offsetX, offsetY);
|
||
|
//mKindBar.SetFocus();
|
||
|
}
|
||
|
|
||
|
public override void Draw(Graphics g)
|
||
|
{
|
||
|
base.Draw(g);
|
||
|
|
||
|
void DrawLabel(Widget widget, StringView label)
|
||
|
{
|
||
|
if (widget == null)
|
||
|
return;
|
||
|
if (widget is CheckBox)
|
||
|
return;
|
||
|
g.DrawString(label, widget.mX + GS!(6), widget.mY - GS!(20));
|
||
|
}
|
||
|
|
||
|
DrawLabel(mKindBar, mRegenerating ? "Regenerating ..." : "Using Generator");
|
||
|
for (var uiEntry in mUIEntries)
|
||
|
DrawLabel(uiEntry.mWidget, uiEntry.mLabel);
|
||
|
}
|
||
|
|
||
|
public override void DrawAll(Graphics g)
|
||
|
{
|
||
|
base.DrawAll(g);
|
||
|
|
||
|
if (mThreadWaitCount > 10)
|
||
|
{
|
||
|
using (g.PushColor(0x60505050))
|
||
|
g.FillRect(0, 0, mWidth, mHeight - GS!(40));
|
||
|
IDEUtils.DrawWait(g, mWidth/2, mHeight/2, mUpdateCnt);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void ResizeComponents()
|
||
|
{
|
||
|
base.ResizeComponents();
|
||
|
|
||
|
mUIHeight = GS!(32);
|
||
|
|
||
|
float insetSize = GS!(12);
|
||
|
|
||
|
mKindBar.Resize(insetSize, mUIHeight, mWidth - insetSize - insetSize, GS!(22));
|
||
|
mUIHeight += GS!(52);
|
||
|
|
||
|
for (var uiEntry in mUIEntries)
|
||
|
{
|
||
|
if (uiEntry.mWidget == null)
|
||
|
continue;
|
||
|
|
||
|
float height = GS!(22);
|
||
|
if (uiEntry.mWidget is ComboBox)
|
||
|
height = GS!(26);
|
||
|
|
||
|
if (uiEntry.mWidget is CheckBox)
|
||
|
{
|
||
|
mUIHeight -= GS!(20);
|
||
|
height = GS!(20);
|
||
|
}
|
||
|
|
||
|
uiEntry.mWidget.Resize(insetSize, mUIHeight, mWidth - insetSize - insetSize, height);
|
||
|
mUIHeight += height + GS!(28);
|
||
|
}
|
||
|
|
||
|
if (mOutputPanel != null)
|
||
|
{
|
||
|
float startY = mKindBar.mVisible ? GS!(60) : GS!(36);
|
||
|
mOutputPanel.Resize(insetSize, startY, mWidth - insetSize - insetSize, Math.Max(mHeight - startY - GS!(44), GS!(32)));
|
||
|
mUIHeight = Math.Max(mUIHeight, GS!(160));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public override void Close()
|
||
|
{
|
||
|
if (mThreadState == .Executing)
|
||
|
{
|
||
|
var bfCompiler = gApp.mBfResolveCompiler;
|
||
|
bfCompiler.RequestFastFinish();
|
||
|
bfCompiler.WaitForBackground();
|
||
|
}
|
||
|
base.Close();
|
||
|
}
|
||
|
|
||
|
public override void Submit()
|
||
|
{
|
||
|
mDefaultButton.mDisabled = true;
|
||
|
mEscButton.mDisabled = true;
|
||
|
|
||
|
if (mSubmitQueued)
|
||
|
return;
|
||
|
mSubmitQueued = true;
|
||
|
mPendingSelectedEntry = mPendingSelectedEntry ?? mSelectedEntry;
|
||
|
}
|
||
|
}
|
||
|
}
|