mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
444 lines
14 KiB
Beef
444 lines
14 KiB
Beef
using System;
|
|
using System.Collections;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Beefy;
|
|
using Beefy.gfx;
|
|
using Beefy.widgets;
|
|
using Beefy.theme.dark;
|
|
using Beefy.geom;
|
|
using IDE.Debugger;
|
|
using IDE;
|
|
using System.Diagnostics;
|
|
using IDE.Compiler;
|
|
|
|
namespace IDE.ui
|
|
{
|
|
public class StatusBar : Widget
|
|
{
|
|
public int32 mClangCommandQueueSize;
|
|
public DarkComboBox mConfigComboBox;
|
|
public DarkComboBox mPlatformComboBox;
|
|
public bool mWasCompiling;
|
|
public int mEvalCount;
|
|
public ImageWidget mCancelSymSrvButton;
|
|
public int mDirtyDelay;
|
|
public int mStatusBoxUpdateCnt = -1;
|
|
|
|
public this()
|
|
{
|
|
mConfigComboBox = new DarkComboBox();
|
|
mConfigComboBox.mFrameKind = .Frameless;
|
|
mConfigComboBox.mPopulateMenuAction.Add(new => PopulateConfigMenu);
|
|
AddWidget(mConfigComboBox);
|
|
|
|
mPlatformComboBox = new DarkComboBox();
|
|
mPlatformComboBox.mFrameKind = .Frameless;
|
|
mPlatformComboBox.mPopulateMenuAction.Add(new => PopulatePlatformMenu);
|
|
AddWidget(mPlatformComboBox);
|
|
}
|
|
|
|
void PopulateConfigMenu(Menu menu)
|
|
{
|
|
var nameList = scope List<String>(gApp.mWorkspace.mConfigs.Keys);
|
|
nameList.Sort(scope (lhs, rhs) => lhs.CompareTo(rhs, true));
|
|
for (var configName in nameList)
|
|
{
|
|
String dispStr = configName;
|
|
/*if (gApp.mConfigName == configName)
|
|
{
|
|
dispStr = stack String();
|
|
dispStr.AppendF("Active({0})", configName);
|
|
}*/
|
|
var item = menu.AddItem(dispStr);
|
|
if (gApp.mConfigName == configName)
|
|
item.mBold = true;
|
|
item.mOnMenuItemSelected.Add(new (evt) => { SelectConfig(configName); });
|
|
}
|
|
}
|
|
|
|
public void SelectConfig(String configName)
|
|
{
|
|
mConfigComboBox.Label = configName;
|
|
gApp.mConfigName.Set(configName);
|
|
gApp.CurrentWorkspaceConfigChanged();
|
|
MarkDirty();
|
|
}
|
|
|
|
void SelectPlatform(String platformName)
|
|
{
|
|
mPlatformComboBox.Label = platformName;
|
|
gApp.mPlatformName.Set(platformName);
|
|
gApp.CurrentWorkspaceConfigChanged();
|
|
MarkDirty();
|
|
}
|
|
|
|
void PopulatePlatformMenu(Menu menu)
|
|
{
|
|
var nameList = scope List<String>();
|
|
gApp.mWorkspace.GetPlatformList(nameList);
|
|
for (var platformName in nameList)
|
|
{
|
|
String dispStr = platformName;
|
|
/*if (gApp.mPlatformName == platformName)
|
|
{
|
|
dispStr = stack String();
|
|
dispStr.AppendF("Active({0})", platformName);
|
|
}*/
|
|
var item = menu.AddItem(dispStr);
|
|
if (gApp.mPlatformName == platformName)
|
|
item.mBold = true;
|
|
|
|
item.mOnMenuItemSelected.Add(new (evt) => { SelectPlatform(platformName); });
|
|
}
|
|
}
|
|
|
|
void ResizeComponents()
|
|
{
|
|
int btnLeft = gApp.mSettings.mEnableDevMode ? GS!(380) : GS!(300);
|
|
mConfigComboBox.Resize(mWidth - btnLeft, GS!(0), GS!(120), GS!(24));
|
|
mPlatformComboBox.Resize(mWidth - btnLeft - GS!(120), GS!(0), GS!(120), GS!(24));
|
|
|
|
if (mCancelSymSrvButton != null)
|
|
mCancelSymSrvButton.Resize(GS!(546), 0, GS!(20), GS!(20));
|
|
}
|
|
|
|
public override void Resize(float x, float y, float width, float height)
|
|
{
|
|
base.Resize(x, y, width, height);
|
|
ResizeComponents();
|
|
}
|
|
|
|
// This marks us dirty on the next frame also
|
|
void MarkDirtyEx(int dirtyDelay = 1)
|
|
{
|
|
mDirtyDelay = Math.Min(dirtyDelay, mDirtyDelay);
|
|
MarkDirty();
|
|
}
|
|
|
|
public override void Update()
|
|
{
|
|
base.Update();
|
|
|
|
if (mDirtyDelay > 0)
|
|
{
|
|
if (--mDirtyDelay == 0)
|
|
MarkDirty();
|
|
}
|
|
|
|
if (mStatusBoxUpdateCnt != -1)
|
|
mStatusBoxUpdateCnt++;
|
|
|
|
if (gApp.mWorkspace.IsInitialized)
|
|
{
|
|
mConfigComboBox.Label = gApp.mConfigName;
|
|
mPlatformComboBox.Label = gApp.mPlatformName;
|
|
}
|
|
else
|
|
{
|
|
mConfigComboBox.Label = "";
|
|
mPlatformComboBox.Label = "";
|
|
}
|
|
|
|
bool canChangeConfig = !gApp.IsCompiling && !gApp.mDebugger.mIsRunning && !gApp.AreTestsRunning() && gApp.mWorkspace.IsInitialized;
|
|
mConfigComboBox.mDisabled = !canChangeConfig;
|
|
mPlatformComboBox.mDisabled = !canChangeConfig;
|
|
|
|
if ((gApp.IsCompiling || gApp.mRunningTestScript) && (mUpdateCnt % 8 == 0))
|
|
MarkDirtyEx(8);
|
|
|
|
var debugState = gApp.mDebugger.GetRunState();
|
|
//if (mWidgetWindow.IsKeyDown(.Control))
|
|
//debugState = .SearchingSymSrv;
|
|
|
|
if (debugState == .DebugEval)
|
|
{
|
|
mEvalCount++;
|
|
MarkDirtyEx();
|
|
}
|
|
else
|
|
mEvalCount = 0;
|
|
|
|
if (debugState == .SearchingSymSrv)
|
|
{
|
|
MarkDirtyEx();
|
|
|
|
if (mCancelSymSrvButton == null)
|
|
{
|
|
mCancelSymSrvButton = new ImageWidget();
|
|
mCancelSymSrvButton.mImage = DarkTheme.sDarkTheme.GetImage(.Close);
|
|
mCancelSymSrvButton.mOverImage = DarkTheme.sDarkTheme.GetImage(.CloseOver);
|
|
mCancelSymSrvButton.mOnMouseClick.Add(new (evt) => { gApp.mDebugger.CancelSymSrv(); });
|
|
AddWidget(mCancelSymSrvButton);
|
|
ResizeComponents();
|
|
}
|
|
|
|
float len = GS!(200);
|
|
float x = GS!(350);
|
|
Rect completionRect = Rect(x, GS!(1), len, GS!(17));
|
|
|
|
Point mousePos;
|
|
if (DarkTooltipManager.CheckMouseover(this, 25, out mousePos, true))
|
|
{
|
|
if (completionRect.Contains(mousePos.x, mousePos.y))
|
|
{
|
|
DarkTooltipManager.ShowTooltip(gApp.mSymSrvStatus, this, mousePos.x, mousePos.y);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((DarkTooltipManager.sTooltip != null) && (DarkTooltipManager.sTooltip.mRelWidget == this))
|
|
DarkTooltipManager.sTooltip.Close();
|
|
|
|
if (mCancelSymSrvButton != null)
|
|
{
|
|
RemoveAndDelete(mCancelSymSrvButton);
|
|
mCancelSymSrvButton = null;
|
|
}
|
|
}
|
|
|
|
if ((gApp.mBfResolveCompiler != null) && (gApp.mBfResolveCompiler.IsPerformingBackgroundOperation())
|
|
#if IDE_C_SUPPORT
|
|
|| (gApp.mResolveClang.IsPerformingBackgroundOperation()) ||
|
|
(gApp.mDepClang.IsPerformingBackgroundOperation())
|
|
#endif
|
|
)
|
|
{
|
|
MarkDirtyEx();
|
|
}
|
|
}
|
|
|
|
public override void Draw(Graphics g)
|
|
{
|
|
bool atError = gApp.mDebugger.GetRunState() == DebugManager.RunState.Exception;
|
|
|
|
uint32 bkgColor = 0xFF404040;
|
|
if (atError)
|
|
bkgColor = 0xFF800000;
|
|
if (gApp.IsCompiling)
|
|
bkgColor = 0xFF35306A;
|
|
else if (gApp.mDebugger.mIsRunning)
|
|
bkgColor = 0xFFB65D08;
|
|
else if (gApp.AreTestsRunning())
|
|
bkgColor = 0xFF562143;
|
|
|
|
using (g.PushColor(bkgColor))
|
|
g.FillRect(0, 0, mWidth, mHeight);
|
|
|
|
// Helps debug MarkDirtys
|
|
/*using (g.PushColor(Color.FromHSV(Utils.RandFloat(), 1.0f, 1.0f)))
|
|
{
|
|
g.FillRect(0, mHeight - 4, 4, 4);
|
|
}*/
|
|
|
|
g.SetFont(DarkTheme.sDarkTheme.mSmallFont);
|
|
|
|
var activeDocument = gApp.GetActiveDocumentPanel();
|
|
if (activeDocument is SourceViewPanel)
|
|
{
|
|
var sourceViewPanel = (SourceViewPanel)activeDocument;
|
|
sourceViewPanel = sourceViewPanel.GetActivePanel();
|
|
|
|
int32 line;
|
|
int32 column;
|
|
sourceViewPanel.GetCursorPosition(out line, out column);
|
|
|
|
using (g.PushColor(DarkTheme.COLOR_TEXT))
|
|
{
|
|
if (gApp.mSettings.mEnableDevMode)
|
|
g.DrawString(StackStringFormat!("Idx {0}", sourceViewPanel.mEditWidget.Content.CursorTextPos), mWidth - GS!(240), 0);
|
|
g.DrawString(StackStringFormat!("Ln {0}", line + 1), mWidth - GS!(150), 0);
|
|
g.DrawString(StackStringFormat!("Col {0}", column + 1), mWidth - GS!(78), 0);
|
|
}
|
|
}
|
|
|
|
using (g.PushColor(0xFF101010))
|
|
{
|
|
//g.FillRect(50 + ((mUpdateCnt) % 50) * 2, 0, 3, mHeight);
|
|
}
|
|
|
|
var bfBuildCompiler = gApp.mBfBuildCompiler;
|
|
#if IDE_C_SUPPORT
|
|
var buildClang = gApp.mDepClang;
|
|
#endif
|
|
|
|
float? completionPct = null;
|
|
|
|
if (bfBuildCompiler.HasQueuedCommands())
|
|
{
|
|
completionPct = bfBuildCompiler.GetCompletionPercentage();
|
|
Debug.Assert(completionPct.GetValueOrDefault() >= 0);
|
|
}
|
|
#if IDE_C_SUPPORT
|
|
else if ((gApp.IsCompiling) && (buildClang.mCompileWaitsForQueueEmpty))
|
|
{
|
|
mClangCommandQueueSize = Math.Max(mClangCommandQueueSize, buildClang.GetCommandQueueSize());
|
|
if (mClangCommandQueueSize != 0)
|
|
{
|
|
int32 itemsLeft = buildClang.GetCommandQueueSize();
|
|
completionPct = (mClangCommandQueueSize - itemsLeft) / (float)mClangCommandQueueSize;
|
|
Debug.Assert(completionPct.GetValueOrDefault() >= 0);
|
|
if (itemsLeft == 0)
|
|
mClangCommandQueueSize = 0;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
float statusLabelPos = (int)GS!(-1.3f);
|
|
|
|
//completionPct = 0.4f;
|
|
if (completionPct.HasValue)
|
|
{
|
|
Rect completionRect = Rect(GS!(200), GS!(2), GS!(120), GS!(15));
|
|
using (g.PushColor(0xFF000000))
|
|
g.FillRect(completionRect.mX, completionRect.mY, completionRect.mWidth, completionRect.mHeight);
|
|
completionRect.Inflate(GS!(-1), GS!(-1));
|
|
using (g.PushColor(0xFF00FF00))
|
|
g.FillRect(completionRect.mX, completionRect.mY, completionRect.mWidth * completionPct.Value, completionRect.mHeight);
|
|
}
|
|
else if ((gApp.mDebugger.mIsRunning) && (gApp.HaveSourcesChanged()))
|
|
{
|
|
Rect completionRect = Rect(GS!(200), GS!(1), GS!(120), GS!(17));
|
|
using (g.PushColor(0x60000000))
|
|
g.FillRect(completionRect.mX, completionRect.mY, completionRect.mWidth, completionRect.mHeight);
|
|
completionRect.Inflate(-1, -1);
|
|
using (g.PushColor(0x40202080))
|
|
g.FillRect(completionRect.mX, completionRect.mY, completionRect.mWidth, completionRect.mHeight);
|
|
|
|
g.DrawString("Source Changed", GS!(200), statusLabelPos, FontAlign.Centered, GS!(120));
|
|
}
|
|
|
|
void DrawStatusBox(StringView str, int32 updateCnt = -1)
|
|
{
|
|
if (mStatusBoxUpdateCnt == -1)
|
|
mStatusBoxUpdateCnt = 0;
|
|
|
|
float len = GS!(200);
|
|
float x = GS!(350);
|
|
Rect completionRect = Rect(x, GS!(1), len, GS!(17));
|
|
using (g.PushColor(0x60000000))
|
|
g.FillRect(completionRect.mX, completionRect.mY, completionRect.mWidth, completionRect.mHeight);
|
|
completionRect.Inflate(-1, -1);
|
|
//float pulseSpeed = Math.Min(mStatusBoxUpdateCnt * 0.001f, 0.2f);
|
|
float pulseSpeed = 0.2f;
|
|
if (updateCnt != -1)
|
|
pulseSpeed = Math.Max(0.14f, pulseSpeed - updateCnt * 0.00005f);
|
|
float pulsePct = -Math.Cos(Math.Max(mStatusBoxUpdateCnt - 30, 0) * pulseSpeed);
|
|
if (updateCnt != -1)
|
|
pulsePct *= Math.Max(0.4f, 1.0f - updateCnt * 0.0004f);
|
|
using (g.PushColor(Color.FromHSV(0.1f, 0.5f, (float)Math.Max(pulsePct * 0.15f + 0.3f, 0.3f))))
|
|
g.FillRect(completionRect.mX, completionRect.mY, completionRect.mWidth, completionRect.mHeight);
|
|
|
|
if (mCancelSymSrvButton != null)
|
|
mCancelSymSrvButton.mX = completionRect.Right - GS!(16);
|
|
|
|
using (g.PushColor(DarkTheme.COLOR_TEXT))
|
|
g.DrawString(str, x, statusLabelPos, FontAlign.Centered, len);
|
|
}
|
|
|
|
if (gApp.mKeyChordState != null)
|
|
{
|
|
String chordState = scope String();
|
|
gApp.mKeyChordState.mCommandMap.ToString(chordState);
|
|
chordState.Append(", <Awaiting Key>...");
|
|
DrawStatusBox(chordState);
|
|
}
|
|
else if (mCancelSymSrvButton != null)
|
|
{
|
|
DrawStatusBox("Retrieving Debug Symbols... ");
|
|
}
|
|
else if (mEvalCount > 20)
|
|
{
|
|
DrawStatusBox("Evaluating Expression");
|
|
}
|
|
else if (gApp.mRunningTestScript)
|
|
{
|
|
DrawStatusBox("Running Script");
|
|
}
|
|
else if ((gApp.mBuildContext != null) && (!completionPct.HasValue))
|
|
{
|
|
DrawStatusBox("Custom Build Commands...", gApp.mBuildContext.mUpdateCnt);
|
|
}
|
|
else
|
|
mStatusBoxUpdateCnt = -1;
|
|
|
|
///
|
|
{
|
|
if (gApp.mErrorsPanel.mErrorCount > 0)
|
|
{
|
|
g.Draw(DarkTheme.sDarkTheme.GetImage(.CodeError), GS!(6), 0);
|
|
}
|
|
else if (gApp.mErrorsPanel.mWarningCount > 0)
|
|
{
|
|
g.Draw(DarkTheme.sDarkTheme.GetImage(.CodeWarning), GS!(6), 0);
|
|
}
|
|
}
|
|
|
|
if (gApp.mSettings.mEnableDevMode)
|
|
{
|
|
using (g.PushColor(DarkTheme.COLOR_TEXT))
|
|
g.DrawString(StackStringFormat!("FPS: {0}", gApp.mLastFPS), GS!(32), 0);
|
|
|
|
String resolveStr = scope String();
|
|
let bfResolveCompiler = gApp.mBfResolveCompiler;
|
|
if ((bfResolveCompiler != null) && (gApp.mBfResolveCompiler.mThreadWorker.mThreadRunning))
|
|
{
|
|
resolveStr.Append("B");
|
|
}
|
|
if ((bfResolveCompiler != null) && (gApp.mBfResolveCompiler.mThreadWorkerHi.mThreadRunning))
|
|
{
|
|
resolveStr.Append("H");
|
|
}
|
|
#if IDE_C_SUPPORT
|
|
if (gApp.mResolveClang.IsPerformingBackgroundOperation())
|
|
{
|
|
if (resolveStr.Length > 0)
|
|
resolveStr.Append(" & ");
|
|
resolveStr.Append("Clang");
|
|
}
|
|
if (gApp.mDepClang.IsPerformingBackgroundOperation())
|
|
{
|
|
if (resolveStr.Length > 0)
|
|
resolveStr.Append(" ");
|
|
resolveStr.Append("ClangB");
|
|
}
|
|
#endif
|
|
|
|
/*if (BfPassInstance.sPassInstances.Count > 0)
|
|
{
|
|
//resolveStr += String.Format(" PassInstances: {0}", BfPassInstance.sPassInstances.Count);
|
|
|
|
resolveStr += "ResolvePasses: {";
|
|
|
|
//foreach (var passInstance in BfPassInstance.sPassInstances)
|
|
for (int passIdx = 0; passIdx < BfPassInstance.sPassInstances.Count; passIdx++)
|
|
{
|
|
var passInstance = BfPassInstance.sPassInstances[passIdx];
|
|
if (passIdx > 0)
|
|
resolveStr += ", ";
|
|
if (passInstance.mDbgStr != null)
|
|
resolveStr += passInstance.mDbgStr;
|
|
resolveStr += String.Format(" #{0}", passInstance.mId);
|
|
}
|
|
|
|
resolveStr += "}";
|
|
}*/
|
|
|
|
if (resolveStr.Length != 0)
|
|
g.DrawString(resolveStr, GS!(100), 0);
|
|
}
|
|
}
|
|
|
|
public override void MouseDown(float x, float y, int32 btn, int32 btnCount)
|
|
{
|
|
base.MouseDown(x, y, btn, btnCount);
|
|
|
|
if (Rect(GS!(6), 0, GS!(20), mHeight).Contains(x, y))
|
|
{
|
|
gApp.mErrorsPanel.ShowErrorNext();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|