mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-19 16:40:26 +02:00
713 lines
19 KiB
Beef
713 lines
19 KiB
Beef
using System;
|
|
using System.Collections;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Diagnostics;
|
|
using Beefy;
|
|
using Beefy.widgets;
|
|
using Beefy.theme;
|
|
using Beefy.gfx;
|
|
using Beefy.theme.dark;
|
|
using Beefy.events;
|
|
using Beefy.utils;
|
|
using IDE.Debugger;
|
|
|
|
|
|
namespace IDE.ui
|
|
{
|
|
class ProfilePanel : Panel
|
|
{
|
|
class ProfileListViewItem : DarkListViewItem
|
|
{
|
|
public int32 mSelfSamples;
|
|
public int32 mChildSamples;
|
|
|
|
float ArrowCenterY
|
|
{
|
|
get
|
|
{
|
|
return DarkTheme.sUnitSize * 0.5f + GS!(4) + 1;
|
|
}
|
|
}
|
|
|
|
protected override void DrawChildren(Graphics g, int itemStart, int itemEnd)
|
|
{
|
|
base.DrawChildren(g, itemStart, itemEnd);
|
|
|
|
if (mParentItem == null)
|
|
return;
|
|
|
|
float barWidth = (int)GS!(1.5f);
|
|
|
|
let lastItem = mChildItems.Back;
|
|
if (!lastItem.mVisible)
|
|
return;
|
|
|
|
let parent = (DarkListView)mListView;
|
|
float absX = (mDepth - 1) * parent.mChildIndent + GS!(12);
|
|
if (absX >= parent.mColumns[0].mWidth)
|
|
return;
|
|
|
|
using (g.PushColor(0xFFB0B0B0))
|
|
g.FillRect((int)ArrowCenterY, GS!(14), barWidth, (int)lastItem.mY - (int)GS!(4.8f));
|
|
}
|
|
|
|
public override void DrawAll(Graphics g)
|
|
{
|
|
float barWidth = (int)GS!(1.5f);
|
|
|
|
var listView = (DarkListView)mListView;
|
|
float xStart = mDepth * listView.mChildIndent - GS!(12);
|
|
if (xStart < listView.mColumns[0].mWidth)
|
|
{
|
|
if ((mVisible) && (mColumnIdx == 0) && (mX > 10))
|
|
{
|
|
using (g.PushColor(0xFFB0B0B0))
|
|
{
|
|
float horzWidth = GS!(13) - 3 - barWidth;
|
|
if (mOpenButton == null)
|
|
horzWidth += GS!(4);
|
|
g.FillRect(-mX + (int)(ArrowCenterY + GS!(0.7f)), GS!(9), horzWidth, barWidth);
|
|
}
|
|
}
|
|
}
|
|
|
|
base.DrawAll(g);
|
|
}
|
|
}
|
|
|
|
class ProfileListView : DarkListView
|
|
{
|
|
public this()
|
|
{
|
|
//mShowLineGrid = true;
|
|
}
|
|
|
|
protected override ListViewItem CreateListViewItem()
|
|
{
|
|
return new ProfileListViewItem();
|
|
}
|
|
|
|
protected override void SetScaleData()
|
|
{
|
|
base.SetScaleData();
|
|
|
|
mIconX = GS!(4);
|
|
mOpenButtonX = GS!(4);
|
|
mLabelX = GS!(23);
|
|
mChildIndent = GS!(16);
|
|
mHiliteOffset = GS!(-2);
|
|
}
|
|
}
|
|
|
|
public class SessionComboBox : DarkComboBox
|
|
{
|
|
public bool mIsRecording;
|
|
|
|
public override void Draw(Graphics g)
|
|
{
|
|
base.Draw(g);
|
|
}
|
|
|
|
public override void Update()
|
|
{
|
|
base.Update();
|
|
}
|
|
|
|
public override void DrawAll(Graphics g)
|
|
{
|
|
base.DrawAll(g);
|
|
|
|
mLabelX = mIsRecording ? GS!(24) : GS!(8);
|
|
if (mIsRecording)
|
|
g.Draw(DarkTheme.sDarkTheme.GetImage(.RedDot), GS!(4), GS!(0));
|
|
}
|
|
}
|
|
|
|
ProfileListView mListView;
|
|
public SessionComboBox mSessionComboBox;
|
|
public DarkComboBox mThreadComboBox;
|
|
DarkButton mStopButton;
|
|
public bool mThreadsDirty = true;
|
|
public int32 mThreadIdx;
|
|
public int32 mDisabledTicks;
|
|
public DbgProfiler mProfiler;
|
|
public List<int32> mThreadList = new List<int32>() ~ delete _;
|
|
public uint32 mTickCreated;
|
|
public int32 mCurIdx;
|
|
public DbgProfiler mUserProfiler;
|
|
public DbgProfiler.Overview mShowOverview ~ delete _;
|
|
public int mOverviewAge;
|
|
public bool mAwaitingLoad;
|
|
public bool mIsSamplingHidden;
|
|
|
|
public List<DbgProfiler> mProfilers = new List<DbgProfiler>() ~ DeleteContainerAndItems!(_);
|
|
|
|
const String cStartProfilingCmd = " < Start Profiling > ";
|
|
const String cStartProfilingExCmd = " < Profile... > ";
|
|
|
|
public bool IsSamplingHidden
|
|
{
|
|
get
|
|
{
|
|
return mIsSamplingHidden;
|
|
}
|
|
}
|
|
|
|
public this()
|
|
{
|
|
mSessionComboBox = new SessionComboBox();
|
|
mSessionComboBox.mPopulateMenuAction.Add(new => PopulateSessionList);
|
|
AddWidget(mSessionComboBox);
|
|
mSessionComboBox.Label = cStartProfilingCmd;
|
|
mTabWidgets.Add(mSessionComboBox);
|
|
|
|
mStopButton = new DarkButton();
|
|
mStopButton.Label = "Stop";
|
|
AddWidget(mStopButton);
|
|
mStopButton.mOnMouseClick.Add(new (evt) =>
|
|
{
|
|
if (mProfiler != null)
|
|
mProfiler.Stop();
|
|
});
|
|
|
|
mThreadComboBox = new DarkComboBox();
|
|
mThreadComboBox.mPopulateMenuAction.Add(new => PopulateThreadList);
|
|
AddWidget(mThreadComboBox);
|
|
mTabWidgets.Add(mThreadComboBox);
|
|
|
|
mListView = new ProfileListView();
|
|
mListView.InitScrollbars(true, true);
|
|
mListView.mHorzScrollbar.mPageSize = GS!(100);
|
|
mListView.mHorzScrollbar.mContentSize = GS!(500);
|
|
mListView.mVertScrollbar.mPageSize = GS!(100);
|
|
mListView.mVertScrollbar.mContentSize = GS!(500);
|
|
mListView.UpdateScrollbars();
|
|
mListView.mOnMouseDown.Add(new (mouseArgs) =>
|
|
{
|
|
SetFocus();
|
|
});
|
|
mListView.mOnItemMouseDown.Add(new => ValueMouseDown);
|
|
mTabWidgets.Add(mListView);
|
|
|
|
//mListView.mDragEndHandler += HandleDragEnd;
|
|
//mListView.mDragUpdateHandler += HandleDragUpdate;
|
|
|
|
AddWidget(mListView);
|
|
|
|
//mListView.mMouseDownHandler += ListViewMouseDown;
|
|
|
|
ListViewColumn column = mListView.AddColumn(300, "Function");
|
|
column.mMinWidth = 100;
|
|
|
|
column = mListView.AddColumn(80, "Total CPU %");
|
|
column.mMinWidth = 60;
|
|
column = mListView.AddColumn(80, "Self CPU %");
|
|
column.mMinWidth = 60;
|
|
column = mListView.AddColumn(90, "Total CPU (ms)");
|
|
column.mMinWidth = 60;
|
|
column = mListView.AddColumn(90, "Self CPU (ms)");
|
|
column.mMinWidth = 60;
|
|
//RebuildUI();
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
mUserProfiler = null;
|
|
mProfiler = null;
|
|
ClearAndDeleteItems(mProfilers);
|
|
|
|
mSessionComboBox.Label = cStartProfilingCmd;
|
|
mThreadComboBox.Label = "";
|
|
mListView.GetRoot().Clear();
|
|
mThreadList.Clear();
|
|
DeleteAndNullify!(mShowOverview);
|
|
mAwaitingLoad = false;
|
|
}
|
|
|
|
public void StartProfiling(int threadId, String desc, int sampleRate)
|
|
{
|
|
if (mUserProfiler != null)
|
|
return;
|
|
|
|
if (!gApp.mDebugger.mIsRunning)
|
|
{
|
|
gApp.RunWithCompiling();
|
|
|
|
gApp.QueueProfiling(threadId, desc, sampleRate);
|
|
return;
|
|
}
|
|
|
|
mUserProfiler = gApp.mDebugger.StartProfiling(threadId, desc, sampleRate);
|
|
mUserProfiler.mIsManual = true;
|
|
Add(mUserProfiler);
|
|
Show(mUserProfiler);
|
|
}
|
|
|
|
public void StartProfiling()
|
|
{
|
|
StartProfiling(0, "", gApp.mSettings.mDebuggerSettings.mProfileSampleRate);
|
|
}
|
|
|
|
public void StopProfiling()
|
|
{
|
|
if (mUserProfiler == null)
|
|
return;
|
|
|
|
mUserProfiler.Stop();
|
|
mUserProfiler = null;
|
|
}
|
|
|
|
void PopulateSessionList(Menu menu)
|
|
{
|
|
var item = menu.AddItem(cStartProfilingCmd);
|
|
item.mOnMenuItemSelected.Add(new (item) =>
|
|
{
|
|
StartProfiling();
|
|
});
|
|
|
|
item = menu.AddItem(cStartProfilingExCmd);
|
|
item.mOnMenuItemSelected.Add(new (item) =>
|
|
{
|
|
var profileDialog = new ProfileDialog();
|
|
profileDialog.PopupWindow(mWidgetWindow);
|
|
//StartProfilingEx();
|
|
});
|
|
|
|
for (int profilerIdx = mProfilers.Count - 1; profilerIdx >= 0; profilerIdx--)
|
|
{
|
|
var profiler = mProfilers[profilerIdx];
|
|
var label = scope String();
|
|
profiler.GetLabel(label);
|
|
item = menu.AddItem(label);
|
|
|
|
var overview = scope DbgProfiler.Overview();
|
|
profiler.GetOverview(overview);
|
|
if (overview.IsSampling)
|
|
item.mIconImage = DarkTheme.sDarkTheme.GetImage(.RedDot);
|
|
item.mOnMenuItemSelected.Add(new (item) =>
|
|
{
|
|
mSessionComboBox.Label = item.mLabel;
|
|
Show(profiler);
|
|
});
|
|
}
|
|
}
|
|
|
|
struct ThreadEntry : this(int32 mThreadId, int32 mCPUUsage, StringView mName)
|
|
{
|
|
}
|
|
|
|
void PopulateThreadList(Menu menu)
|
|
{
|
|
if (mProfiler == null)
|
|
return;
|
|
|
|
if (mProfiler.IsSampling)
|
|
return;
|
|
|
|
var subItem = menu.AddItem("All Threads");
|
|
subItem.mOnMenuItemSelected.Add(new (item) => { Show(0, .()); });
|
|
|
|
var threadListStr = scope String();
|
|
mProfiler.GetThreadList(threadListStr);
|
|
|
|
List<ThreadEntry> entries = scope .();
|
|
for (var entry in threadListStr.Split('\n'))
|
|
{
|
|
if (entry.Length == 0)
|
|
continue;
|
|
|
|
var dataItr = entry.Split('\t');
|
|
|
|
ThreadEntry threadEntry = default;
|
|
threadEntry.mThreadId = int32.Parse(dataItr.GetNext());
|
|
threadEntry.mCPUUsage = int32.Parse(dataItr.GetNext());
|
|
threadEntry.mName = dataItr.GetNext();
|
|
entries.Add(threadEntry);
|
|
}
|
|
|
|
entries.Sort(scope (lhs, rhs) =>
|
|
{
|
|
int cmp = rhs.mCPUUsage <=> lhs.mCPUUsage;
|
|
if (cmp == 0)
|
|
cmp = lhs.mThreadId <=> rhs.mThreadId;
|
|
return cmp;
|
|
});
|
|
|
|
for (var entry in entries)
|
|
{
|
|
String threadStr = null;
|
|
var str = scope String();
|
|
str.AppendF("{0}", entry.mThreadId);
|
|
str.AppendF($" ({entry.mCPUUsage}%)");
|
|
if (!entry.mName.IsEmpty)
|
|
{
|
|
threadStr = new String(entry.mName);
|
|
str.AppendF($" - {entry.mName}");
|
|
}
|
|
|
|
subItem = menu.AddItem(str);
|
|
subItem.mOnMenuItemSelected.Add(new (item) => { Show(entry.mThreadId, threadStr); } ~ delete threadStr);
|
|
}
|
|
}
|
|
|
|
public void Show(int32 threadId, StringView threadName)
|
|
{
|
|
mTickCreated = Utils.GetTickCount();
|
|
|
|
if (threadId == 0)
|
|
mThreadComboBox.Label = "All Threads";
|
|
else
|
|
{
|
|
var threadStr = scope String();
|
|
threadStr.AppendF("{0}", threadId);
|
|
if (!threadName.IsEmpty)
|
|
threadStr.AppendF(" - {0}", threadName);
|
|
mThreadComboBox.Label = threadStr;
|
|
}
|
|
|
|
mThreadList.Clear();
|
|
|
|
var str = scope String();
|
|
mProfiler.GetCallTree(threadId, str, false);
|
|
|
|
List<DarkListViewItem> itemStack = scope List<DarkListViewItem>();
|
|
DarkListViewItem curItem = (DarkListViewItem)mListView.GetRoot();
|
|
|
|
mListView.GetRoot().Clear();
|
|
|
|
var overview = scope DbgProfiler.Overview();
|
|
mProfiler.GetOverview(overview);
|
|
|
|
int32 totalSamples = 0;
|
|
float sampleTimeMult = 1000.0f / overview.mSamplesPerSecond; // 1ms per sample
|
|
|
|
for (var lineView in str.Split('\n'))
|
|
{
|
|
var line = scope String(lineView);
|
|
if (line.Length == 0)
|
|
continue;
|
|
if (line == "-")
|
|
{
|
|
curItem = itemStack.PopBack();
|
|
|
|
curItem.mChildItems.Sort(scope (baseA, baseB) =>
|
|
{
|
|
var a = (ProfileListViewItem)baseA;
|
|
var b = (ProfileListViewItem)baseB;
|
|
return (b.mChildSamples + b.mSelfSamples) - (a.mChildSamples + a.mSelfSamples);
|
|
});
|
|
|
|
continue;
|
|
}
|
|
|
|
var dataList = scope List<StringView>(line.Split('\t'));
|
|
|
|
ProfileListViewItem newItem = (ProfileListViewItem)curItem.CreateChildItem();
|
|
newItem.mLabel = new String(dataList[0]);
|
|
//newItem.mOnMouseDown.Add(new => ValueClicked);
|
|
|
|
var selfStr = scope String(dataList[1]);
|
|
var childStr = scope String(dataList[2]);
|
|
|
|
newItem.mSelfSamples = int32.Parse(selfStr);
|
|
newItem.mChildSamples = int32.Parse(childStr);
|
|
|
|
if (totalSamples == 0)
|
|
totalSamples = newItem.mChildSamples;
|
|
|
|
var subItem = newItem.CreateSubItem(1);
|
|
var tempStr = scope String();
|
|
if (totalSamples == 0)
|
|
tempStr.Append("0.00%");
|
|
else
|
|
tempStr.AppendF("{0:0.00}%", (newItem.mSelfSamples + newItem.mChildSamples) * 100.0f / totalSamples);
|
|
subItem.Label = tempStr;
|
|
//subItem.mOnMouseDown.Add(new => ValueClicked);
|
|
|
|
subItem = newItem.CreateSubItem(2);
|
|
tempStr.Clear();
|
|
if (totalSamples == 0)
|
|
tempStr.Append("0.00%");
|
|
else
|
|
tempStr.AppendF("{0:0.00}%", newItem.mSelfSamples * 100.0f / totalSamples);
|
|
subItem.Label = tempStr;
|
|
//subItem.mOnMouseDown.Add(new => ValueClicked);
|
|
|
|
subItem = newItem.CreateSubItem(3);
|
|
tempStr.Clear();
|
|
tempStr.AppendF("{0}ms", (int32)((newItem.mSelfSamples + newItem.mChildSamples) * sampleTimeMult + 0.5f));
|
|
subItem.Label = tempStr;
|
|
//subItem.mOnMouseDown.Add(new => ValueClicked);
|
|
|
|
subItem = newItem.CreateSubItem(4);
|
|
tempStr.Clear();
|
|
tempStr.AppendF("{0}ms", (int32)(newItem.mSelfSamples * sampleTimeMult + 0.5f));
|
|
subItem.Label = tempStr;
|
|
//subItem.mOnMouseDown.Add(new => ValueClicked);
|
|
|
|
itemStack.Add(curItem);
|
|
curItem = newItem;
|
|
}
|
|
}
|
|
|
|
public void Add(DbgProfiler profiler)
|
|
{
|
|
profiler.mIdx = mCurIdx++;
|
|
mProfilers.Add(profiler);
|
|
}
|
|
|
|
public void UpdateOverview(out bool changed)
|
|
{
|
|
changed = false;
|
|
int prevActualSamples = (mShowOverview?.mTotalActualSamples).GetValueOrDefault();
|
|
|
|
DeleteAndNullify!(mShowOverview);
|
|
|
|
if (mProfiler == null)
|
|
return;
|
|
|
|
mShowOverview = new DbgProfiler.Overview();
|
|
mProfiler.GetOverview(mShowOverview);
|
|
changed = mShowOverview.mTotalActualSamples != prevActualSamples;
|
|
mOverviewAge = 0;
|
|
}
|
|
|
|
public void Show(DbgProfiler profiler)
|
|
{
|
|
mThreadList.Clear();
|
|
|
|
mProfiler = profiler;
|
|
|
|
UpdateOverview(var changed);
|
|
|
|
var overview = scope DbgProfiler.Overview();
|
|
profiler.GetOverview(overview);
|
|
|
|
var label = scope String();
|
|
profiler.GetLabel(label);
|
|
mSessionComboBox.Label = label;
|
|
|
|
if (overview.IsSampling)
|
|
{
|
|
mAwaitingLoad = true;
|
|
mThreadComboBox.Label = "";
|
|
mListView.GetRoot().Clear();
|
|
ResizeComponents();
|
|
return;
|
|
}
|
|
|
|
mAwaitingLoad = false;
|
|
var threadListStr = scope String();
|
|
mProfiler.GetThreadList(threadListStr);
|
|
|
|
for (var entry in threadListStr.Split('\n'))
|
|
{
|
|
if (entry.Length == 0)
|
|
continue;
|
|
var dataItr = entry.Split('\t');
|
|
int32 threadId = int32.Parse(dataItr.GetNext());
|
|
|
|
mThreadList.Add(threadId);
|
|
}
|
|
|
|
if (mThreadList.Count == 0)
|
|
return;
|
|
|
|
int32 threadId = mThreadList[0];
|
|
Show(threadId, .());
|
|
ResizeComponents();
|
|
}
|
|
|
|
public override void Serialize(StructuredData data)
|
|
{
|
|
base.Serialize(data);
|
|
|
|
data.Add("Type", "ProfilePanel");
|
|
}
|
|
|
|
public override bool Deserialize(StructuredData data)
|
|
{
|
|
return base.Deserialize(data);
|
|
}
|
|
|
|
void ValueMouseDown(ListViewItem item, float x, float y, int32 btnNum, int32 btnCount)
|
|
{
|
|
#unwarn
|
|
DarkListViewItem baseItem = (DarkListViewItem)item.GetSubItem(0);
|
|
|
|
ListViewItemMouseDown(item, x, y, btnNum, btnCount);
|
|
|
|
if ((btnNum == 0) && (btnCount > 1))
|
|
{
|
|
/*for (int childIdx = 0; childIdx < mListView.GetRoot().GetChildCount(); childIdx++)
|
|
{
|
|
var checkListViewItem = mListView.GetRoot().GetChildAtIndex(childIdx);
|
|
checkListViewItem.IconImage = null;
|
|
}
|
|
|
|
int selectedIdx = mListView.GetRoot().GetIndexOfChild(item);
|
|
|
|
int threadId = int.Parse(item.mLabel);
|
|
IDEApp.sApp.mDebugger.SetActiveThread(threadId);
|
|
IDEApp.sApp.mDebugger.mCallStackDirty = true;
|
|
IDEApp.sApp.mCallStackPanel.MarkCallStackDirty();
|
|
IDEApp.sApp.mCallStackPanel.Update();
|
|
IDEApp.sApp.mWatchPanel.MarkWatchesDirty(true);
|
|
IDEApp.sApp.mAutoWatchPanel.MarkWatchesDirty(true);
|
|
IDEApp.sApp.mMemoryPanel.MarkViewDirty();
|
|
IDEApp.sApp.ShowPCLocation(IDEApp.sApp.mDebugger.mSelectedCallStackIdx, false, true);
|
|
|
|
item.IconImage = DarkTheme.sDarkTheme.GetImage(DarkTheme.ImageIdx.ArrowRight);*/
|
|
}
|
|
}
|
|
|
|
void ResizeComponents()
|
|
{
|
|
mThreadComboBox.Resize(GS!(80), GS!(22), GS!(220), GS!(24));
|
|
mListView.Resize(0, GS!(44), mWidth, Math.Max(mHeight - GS!(44), 0));
|
|
|
|
if (mSessionComboBox.mIsRecording)
|
|
{
|
|
mStopButton.mVisible = true;
|
|
mStopButton.Resize(GS!(28), GS!(1), GS!(52), GS!(22));
|
|
//mSessionComboBox.Resize(GS!(80) + GS!(42), GS!(1), GS!(220) - GS!(42), GS!(24));
|
|
mSessionComboBox.Resize(GS!(80), GS!(1), GS!(220), GS!(24));
|
|
}
|
|
else
|
|
{
|
|
mStopButton.mVisible = false;
|
|
mSessionComboBox.Resize(GS!(80), GS!(1), GS!(220), GS!(24));
|
|
}
|
|
}
|
|
|
|
public override void Resize(float x, float y, float width, float height)
|
|
{
|
|
base.Resize(x, y, width, height);
|
|
|
|
ResizeComponents();
|
|
}
|
|
|
|
public void MarkThreadsDirty()
|
|
{
|
|
mThreadsDirty = true;
|
|
}
|
|
|
|
public override void LostFocus()
|
|
{
|
|
base.LostFocus();
|
|
mListView.GetRoot().SelectItemExclusively(null);
|
|
}
|
|
|
|
public override void Update()
|
|
{
|
|
base.Update();
|
|
|
|
if (mUserProfiler != null)
|
|
{
|
|
if (!mUserProfiler.IsSampling)
|
|
mUserProfiler = null;
|
|
}
|
|
|
|
if (mProfiler == null)
|
|
{
|
|
if (!mProfilers.IsEmpty)
|
|
{
|
|
var profiler = mProfilers.Back;
|
|
Show(profiler);
|
|
MarkDirty();
|
|
}
|
|
}
|
|
|
|
if (mProfiler != null)
|
|
{
|
|
++mOverviewAge;
|
|
if (mOverviewAge >= 15)
|
|
{
|
|
UpdateOverview(var changed);
|
|
if (changed)
|
|
MarkDirty();
|
|
}
|
|
|
|
if (mUpdateCnt % 60 == 0)
|
|
MarkDirty();
|
|
|
|
if ((!mProfiler.IsSampling) && (mAwaitingLoad))
|
|
Show(mProfiler);
|
|
}
|
|
|
|
if (mShowOverview != null)
|
|
mSessionComboBox.mIsRecording = mShowOverview.IsSampling;
|
|
else
|
|
mSessionComboBox.mIsRecording = false;
|
|
ResizeComponents();
|
|
}
|
|
|
|
public void ForcedUpdate()
|
|
{
|
|
bool isSamplingHidden = false;
|
|
if ((mWidgetWindow == null) || (mProfiler == null) || (!mProfiler.IsSampling))
|
|
{
|
|
for (var profile in mProfilers)
|
|
if (profile.IsSampling)
|
|
isSamplingHidden = true;
|
|
}
|
|
|
|
if (mIsSamplingHidden != isSamplingHidden)
|
|
{
|
|
mIsSamplingHidden = isSamplingHidden;
|
|
gApp.MarkDirty();
|
|
}
|
|
}
|
|
|
|
public override void DrawAll(Graphics g)
|
|
{
|
|
base.DrawAll(g);
|
|
}
|
|
|
|
public override void Draw(Graphics g)
|
|
{
|
|
base.Draw(g);
|
|
|
|
g.SetFont(DarkTheme.sDarkTheme.mSmallFont);
|
|
g.DrawString("Session", mSessionComboBox.mX - GS!(2), mSessionComboBox.mY, .Right);
|
|
g.DrawString("Thread", mThreadComboBox.mX - GS!(2), mThreadComboBox.mY, .Right);
|
|
|
|
if ((mProfiler != null) && (mShowOverview != null))
|
|
{
|
|
g.DrawString(StackStringFormat!("Rate: {0} Hz", mShowOverview.mSamplesPerSecond), GS!(320), GS!(2));
|
|
int32 seconds = (mShowOverview.mRecordedTicks / 1000);
|
|
g.DrawString(StackStringFormat!("Length: {0}:{1:00}.{2}", seconds / 60, seconds % 60, (mShowOverview.mRecordedTicks % 1000)/100), GS!(320), GS!(22));
|
|
|
|
seconds = (mShowOverview.mEndedTicks / 1000);
|
|
if (seconds > 60*60)
|
|
g.DrawString(StackStringFormat!("Age: {0}:{1:00}:{2:00}", seconds / 60 / 60, (seconds / 60) % 60, seconds % 60), GS!(420), GS!(22));
|
|
else
|
|
g.DrawString(StackStringFormat!("Age: {0}:{1:00}", seconds / 60, seconds % 60), GS!(420), GS!(22));
|
|
|
|
g.DrawString(StackStringFormat!("Samples: {0}", mShowOverview.mTotalActualSamples), GS!(420), GS!(2));
|
|
g.DrawString(StackStringFormat!("Missed Samples: {0}", mShowOverview.mTotalVirtualSamples - mShowOverview.mTotalActualSamples), GS!(550), GS!(2));
|
|
}
|
|
|
|
if (mTickCreated != 0)
|
|
{
|
|
|
|
/*String text = scope String();
|
|
text.AppendF("{0}s ago", (int32)(Utils.GetTickCount() - mTickCreated) / 1000);
|
|
g.DrawString(text, mWidth - 4, 2, FontAlign.Right);*/
|
|
}
|
|
}
|
|
|
|
public override void FocusForKeyboard()
|
|
{
|
|
base.FocusForKeyboard();
|
|
mSessionComboBox.SetFocus();
|
|
}
|
|
|
|
public override void MouseDown(float x, float y, int32 btn, int32 btnCount)
|
|
{
|
|
base.MouseDown(x, y, btn, btnCount);
|
|
SetFocus();
|
|
}
|
|
}
|
|
}
|