mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-17 23:56:05 +02:00
773 lines
23 KiB
Beef
773 lines
23 KiB
Beef
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Beefy.events;
|
|
using Beefy.gfx;
|
|
using Beefy.theme;
|
|
using Beefy.theme.dark;
|
|
using Beefy.utils;
|
|
using Beefy.widgets;
|
|
using IDE.Debugger;
|
|
using IDE.util;
|
|
using System.Diagnostics;
|
|
|
|
namespace IDE.ui
|
|
{
|
|
public class BreakpointListViewItem : DarkListViewItem
|
|
{
|
|
public Breakpoint mBreakpoint ~ _?.Deref();
|
|
public WatchRefreshButton mWatchRefreshButton;
|
|
|
|
public void Bind(Breakpoint breakpoint)
|
|
{
|
|
mBreakpoint?.Deref();
|
|
mBreakpoint = breakpoint;
|
|
mBreakpoint?.AddRef();
|
|
}
|
|
|
|
public override void Draw(Graphics g)
|
|
{
|
|
base.Draw(g);
|
|
|
|
if (mColumnIdx == 0)
|
|
{
|
|
if ((mBreakpoint != null) && (!mBreakpoint.mIsDead))
|
|
{
|
|
using (g.PushTranslate(6, 0))
|
|
mBreakpoint.Draw(g, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public class BreakpointListView : IDEListView
|
|
{
|
|
protected override ListViewItem CreateListViewItem()
|
|
{
|
|
DarkListViewItem anItem = new BreakpointListViewItem();
|
|
return anItem;
|
|
}
|
|
}
|
|
|
|
public class BreakpointPanel : Panel
|
|
{
|
|
public BreakpointListView mListView;
|
|
public bool mListDirty = true;
|
|
public bool mDeselectOnFocusLost = true;
|
|
public bool mHasPendingSelectionClear = false;
|
|
public String mPendingEvalStr ~ delete _;
|
|
public String mCurEvalExpr ~ delete _;
|
|
public Breakpoint mPendingMemoryBreakpoint ~ { if (_ != null) _.Deref(); };
|
|
public Action<int, int, String> mOnPendingMemoryBreakpoint ~ delete _;
|
|
|
|
public this()
|
|
{
|
|
mListView = new BreakpointListView();
|
|
mListView.mShowGridLines = true;
|
|
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 => ListViewMouseDown);
|
|
mListView.mOnMouseClick.Add(new => ListViewClicked);
|
|
|
|
AddWidget(mListView);
|
|
|
|
ListViewColumn column = mListView.AddColumn(GS!(200), "Name");
|
|
column.mMinWidth = GS!(100);
|
|
column = mListView.AddColumn(GS!(80), "Tags");
|
|
column = mListView.AddColumn(GS!(200), "Condition");
|
|
column = mListView.AddColumn(GS!(200), "Hit Count");
|
|
column = mListView.AddColumn(GS!(200), "Logging");
|
|
|
|
IDEApp.sApp.mDebugger.mBreakpointsChangedDelegate.Add(new => BreakpointsChanged);
|
|
|
|
//RebuildUI();
|
|
SetScaleData();
|
|
}
|
|
|
|
void SetScaleData()
|
|
{
|
|
mListView.mIconX = GS!(4);
|
|
mListView.mOpenButtonX = GS!(4);
|
|
mListView.mLabelX = GS!(30);
|
|
mListView.mChildIndent = GS!(16);
|
|
mListView.mHiliteOffset = GS!(-2);
|
|
}
|
|
|
|
public override void RehupScale(float oldScale, float newScale)
|
|
{
|
|
base.RehupScale(oldScale, newScale);
|
|
SetScaleData();
|
|
}
|
|
|
|
public override void FocusForKeyboard()
|
|
{
|
|
base.FocusForKeyboard();
|
|
Update();
|
|
SetFocus();
|
|
if ((mListView.GetRoot().FindFocusedItem() == null) && (mListView.GetRoot().GetChildCount() > 0))
|
|
{
|
|
mListView.GetRoot().GetChildAtIndex(0).Focused = true;
|
|
}
|
|
}
|
|
|
|
public void BreakpointsChanged()
|
|
{
|
|
mListDirty = true;
|
|
}
|
|
|
|
public void MarkStatsDirty()
|
|
{
|
|
// We only need to really refresh the hit count...
|
|
mListDirty = true;
|
|
}
|
|
|
|
public override void Serialize(StructuredData data)
|
|
{
|
|
base.Serialize(data);
|
|
|
|
data.Add("Type", "BreakpointPanel");
|
|
}
|
|
|
|
public override bool Deserialize(StructuredData data)
|
|
{
|
|
return base.Deserialize(data);
|
|
}
|
|
|
|
public void ConfigureBreakpoint(Breakpoint breakpoint, String condition, int threadId, String logging, bool breakAfterLogging, int targetHitCount, Breakpoint.HitCountBreakKind hitCountBreakKind)
|
|
{
|
|
/*for (int itemIdx < mListView.GetRoot().GetChildCount())
|
|
{
|
|
var listViewItem = (BreakpointListViewItem)mListView.GetRoot().GetChildAtIndex(itemIdx);
|
|
|
|
if (listViewItem.Selected)
|
|
{
|
|
var subItem = listViewItem.GetSubItem(2);
|
|
subItem.Label = condition;
|
|
listViewItem.mBreakpoint.SetCondition(condition);
|
|
listViewItem.mBreakpoint.SetThreadId(threadId);
|
|
listViewItem.mBreakpoint.SetLogging(logging, breakAfterLogging);
|
|
listViewItem.mBreakpoint.SetHitCountTarget(targetHitCount, hitCountBreakKind);
|
|
BreakpointsChanged();
|
|
}
|
|
}
|
|
gApp.MarkDirty();*/
|
|
|
|
breakpoint.SetCondition(condition);
|
|
breakpoint.SetThreadId(threadId);
|
|
breakpoint.SetLogging(logging, breakAfterLogging);
|
|
breakpoint.SetHitCountTarget(targetHitCount, hitCountBreakKind);
|
|
BreakpointsChanged();
|
|
gApp.MarkDirty();
|
|
}
|
|
|
|
public void ClearHitCounts()
|
|
{
|
|
mListView.GetRoot().WithSelectedItems(scope (item) =>
|
|
{
|
|
var listViewItem = (BreakpointListViewItem)item;
|
|
listViewItem.mBreakpoint.ClearHitCount();
|
|
mListDirty = true;
|
|
});
|
|
gApp.MarkDirty();
|
|
}
|
|
|
|
public void SetBreakpointDisabled(bool disabled)
|
|
{
|
|
mListView.GetRoot().WithSelectedItems(scope (item) =>
|
|
{
|
|
var listViewItem = (BreakpointListViewItem)item;
|
|
if (listViewItem.Selected)
|
|
{
|
|
gApp.mDebugger.SetBreakpointDisabled(listViewItem.mBreakpoint, disabled);
|
|
if (!disabled)
|
|
{
|
|
|
|
}
|
|
BreakpointsChanged();
|
|
gApp.MarkDirty();
|
|
}
|
|
});
|
|
gApp.MarkDirty();
|
|
}
|
|
|
|
public void DeleteBreakpoint()
|
|
{
|
|
mListView.GetRoot().WithSelectedItems(scope (item) =>
|
|
{
|
|
var listViewItem = (BreakpointListViewItem)item;
|
|
if (listViewItem.Selected)
|
|
{
|
|
gApp.mDebugger.DeleteBreakpoint(listViewItem.mBreakpoint);
|
|
BreakpointsChanged();
|
|
}
|
|
});
|
|
gApp.MarkDirty();
|
|
}
|
|
|
|
public void BindToThread()
|
|
{
|
|
int activeThreadId = gApp.mDebugger.GetActiveThread();
|
|
if (activeThreadId <= 0)
|
|
return;
|
|
|
|
mListView.GetRoot().WithSelectedItems(scope (item) =>
|
|
{
|
|
var listViewItem = (BreakpointListViewItem)item;
|
|
listViewItem.mBreakpoint.SetThreadId(activeThreadId);
|
|
mListDirty = true;
|
|
});
|
|
gApp.MarkDirty();
|
|
}
|
|
|
|
public void ConfigureBreakpoints(Widget relWidget)
|
|
{
|
|
mListView.GetRoot().WithSelectedItems(scope (item) =>
|
|
{
|
|
var listViewItem = (BreakpointListViewItem)item;
|
|
if (listViewItem.Selected)
|
|
{
|
|
mDeselectOnFocusLost = false;
|
|
ConditionDialog dialog = new ConditionDialog();
|
|
dialog.Init(listViewItem.mBreakpoint);
|
|
dialog.PopupWindow(relWidget.mWidgetWindow);
|
|
mDeselectOnFocusLost = true;
|
|
}
|
|
});
|
|
}
|
|
|
|
public void AddMemoryBreakpoint(WidgetWindow window)
|
|
{
|
|
NewBreakpointDialog dialog = new .(.Memory);
|
|
dialog.Init();
|
|
dialog.PopupWindow(window);
|
|
}
|
|
|
|
public void AddSymbolBreakpoint(WidgetWindow window)
|
|
{
|
|
NewBreakpointDialog dialog = new .(.Symbol);
|
|
dialog.Init();
|
|
dialog.PopupWindow(window);
|
|
}
|
|
|
|
public MenuWidget ShowRightClickMenu(Widget relWidget, float x, float y, bool isSpecific)
|
|
{
|
|
//mSelectedParentItem = (DarkListViewItem)GetSelectedParentItem();
|
|
|
|
mDeselectOnFocusLost = false;
|
|
defer:: { mDeselectOnFocusLost = true; }
|
|
|
|
Menu menu = new Menu();
|
|
|
|
Menu menuItem;
|
|
|
|
Breakpoint firstSelectedBreakpoint = null;
|
|
bool selectedEnabledBreakpoint = false;
|
|
bool selectedDisabledBreakpoint = false;
|
|
|
|
mListView.GetRoot().WithSelectedItems(scope [&] (listViewItem) =>
|
|
{
|
|
var breakpointListViewItem = (BreakpointListViewItem)listViewItem;
|
|
var breakpoint = breakpointListViewItem.mBreakpoint;
|
|
if (firstSelectedBreakpoint == null)
|
|
firstSelectedBreakpoint = breakpoint;
|
|
selectedEnabledBreakpoint |= !breakpoint.mDisabled;
|
|
selectedDisabledBreakpoint |= breakpoint.mDisabled;
|
|
});
|
|
|
|
if (firstSelectedBreakpoint != null)
|
|
{
|
|
menuItem = menu.AddItem("Configure Breakpoint");
|
|
menuItem.mOnMenuItemSelected.Add(new (evt) =>
|
|
{
|
|
ConfigureBreakpoints(relWidget);
|
|
});
|
|
menuItem = menu.AddItem("Delete Breakpoint");
|
|
menuItem.mOnMenuItemSelected.Add(new (evt) =>
|
|
{
|
|
DeleteBreakpoint();
|
|
});
|
|
if (selectedEnabledBreakpoint)
|
|
{
|
|
menuItem = menu.AddItem("Disable Breakpoint");
|
|
menuItem.mOnMenuItemSelected.Add(new (evt) => { SetBreakpointDisabled(true); });
|
|
}
|
|
if (selectedDisabledBreakpoint)
|
|
{
|
|
menuItem = menu.AddItem("Enable Breakpoint");
|
|
menuItem.mOnMenuItemSelected.Add(new (evt) => { SetBreakpointDisabled(false); });
|
|
}
|
|
if (gApp.mDebugger.IsPaused())
|
|
{
|
|
menuItem = menu.AddItem("Bind to Current Thread");
|
|
menuItem.mOnMenuItemSelected.Add(new (evt) => { BindToThread(); });
|
|
gApp.MarkDirty();
|
|
}
|
|
}
|
|
|
|
if (!isSpecific)
|
|
{
|
|
if (gApp.mDebugger.IsPaused())
|
|
{
|
|
if (firstSelectedBreakpoint != null)
|
|
menu.AddItem();
|
|
|
|
menuItem = menu.AddItem("Add Memory Breakpoint");
|
|
menuItem.mOnMenuItemSelected.Add(new (evt) =>
|
|
{
|
|
AddMemoryBreakpoint(relWidget.mWidgetWindow);
|
|
});
|
|
}
|
|
|
|
menuItem = menu.AddItem("Add Symbol Breakpoint");
|
|
menuItem.mOnMenuItemSelected.Add(new (evt) =>
|
|
{
|
|
AddSymbolBreakpoint(relWidget.mWidgetWindow);
|
|
});
|
|
}
|
|
|
|
if (menu.mItems.IsEmpty)
|
|
{
|
|
delete menu;
|
|
return null;
|
|
}
|
|
MenuWidget menuWidget = ThemeFactory.mDefault.CreateMenuWidget(menu);
|
|
|
|
menuWidget.Init(relWidget, x, y);
|
|
|
|
return menuWidget;
|
|
//menuWidget.mWidgetWindow.mWindowClosedHandler += DeselectFolder;
|
|
}
|
|
|
|
protected override void ShowRightClickMenu(Widget relWidget, float x, float y)
|
|
{
|
|
ShowRightClickMenu(mListView.GetRoot(), x, y, false);
|
|
}
|
|
|
|
public void ListViewItemMouseDown(MouseEvent theEvent)
|
|
{
|
|
var clickedItem = (BreakpointListViewItem)theEvent.mSender;
|
|
var item = (BreakpointListViewItem)clickedItem.GetSubItem(0);
|
|
|
|
if (theEvent.mBtn == 1)
|
|
{
|
|
if (!item.Selected)
|
|
mListView.GetRoot().SelectItem(item, true);
|
|
}
|
|
else
|
|
mListView.GetRoot().SelectItem(item, true);
|
|
|
|
SetFocus();
|
|
|
|
if ((theEvent.mBtn == 0) && (theEvent.mBtnCount == 2))
|
|
{
|
|
var breakpoint = item.mBreakpoint;
|
|
if (breakpoint.mFileName != null)
|
|
{
|
|
gApp.RecordHistoryLocation();
|
|
gApp.ShowSourceFileLocation(breakpoint.mFileName, -1, -1, breakpoint.mLineNum, breakpoint.mColumn, LocatorType.Always, true);
|
|
}
|
|
}
|
|
|
|
|
|
/*if ((theEvent.mBtn == 0) && (theEvent.mBtnCount > 1))
|
|
{
|
|
for (int childIdx = 1; childIdx < mListView.GetRoot().GetChildCount(); childIdx++)
|
|
{
|
|
var checkListViewItem = mListView.GetRoot().GetChildAtIndex(childIdx);
|
|
checkListViewItem.IconImage = null;
|
|
}
|
|
|
|
int selectedIdx = item.mVirtualIdx;
|
|
IDEApp.sApp.mDebugger.mSelectedCallStackIdx = selectedIdx;
|
|
IDEApp.sApp.ShowPCLocation(selectedIdx, false, true);
|
|
IDEApp.sApp.StackPositionChanged();
|
|
}*/
|
|
}
|
|
|
|
void ListViewItemClicked(MouseEvent theEvent)
|
|
{
|
|
var anItem = (BreakpointListViewItem)theEvent.mSender;
|
|
if (anItem.mColumnIdx != 0)
|
|
anItem = (BreakpointListViewItem)anItem.GetSubItem(0);
|
|
|
|
if (theEvent.mBtn == 1)
|
|
{
|
|
float aX, aY;
|
|
theEvent.GetRootCoords(out aX, out aY);
|
|
ShowRightClickMenu(mWidgetWindow.mRootWidget, aX, aY, false);
|
|
}
|
|
else
|
|
{
|
|
//if (anItem.IsParent)
|
|
//anItem.Selected = false;
|
|
}
|
|
}
|
|
|
|
void ListViewMouseDown(MouseEvent theEvent)
|
|
{
|
|
mListView.GetRoot().WithSelectedItems(scope (item) => { item.Selected = false; });
|
|
}
|
|
|
|
void ListViewClicked(MouseEvent theEvent)
|
|
{
|
|
if (theEvent.mBtn == 1)
|
|
{
|
|
float aX, aY;
|
|
theEvent.GetRootCoords(out aX, out aY);
|
|
ShowRightClickMenu(mWidgetWindow.mRootWidget, aX, aY, false);
|
|
}
|
|
}
|
|
|
|
public enum MemoryBreakpointResult
|
|
{
|
|
Failure,
|
|
Success,
|
|
Pending
|
|
}
|
|
|
|
void PendingExprDone(String result)
|
|
{
|
|
int addr = 0;
|
|
int32 byteCount = 0;
|
|
String addrType = scope .();
|
|
|
|
if (result != null)
|
|
{
|
|
if (HandleMemoryBreakpointResult(mPendingEvalStr, result, out addr, out byteCount, addrType))
|
|
{
|
|
}
|
|
}
|
|
|
|
mOnPendingMemoryBreakpoint(addr, byteCount, addrType);
|
|
DeleteAndNullify!(mOnPendingMemoryBreakpoint);
|
|
DeleteAndNullify!(mPendingEvalStr);
|
|
}
|
|
|
|
void ExistingPendingExprDone(int addr, int byteCount, String addrType)
|
|
{
|
|
if (!mPendingMemoryBreakpoint.mIsDead)
|
|
{
|
|
if (addr != 0)
|
|
SetMemoryBreakpoint(mPendingMemoryBreakpoint, addr, byteCount, addrType);
|
|
}
|
|
mPendingMemoryBreakpoint.Deref();
|
|
mPendingMemoryBreakpoint = null;
|
|
}
|
|
|
|
public void CancelPending()
|
|
{
|
|
DeleteAndNullify!(mPendingEvalStr);
|
|
DeleteAndNullify!(mOnPendingMemoryBreakpoint);
|
|
if (mPendingMemoryBreakpoint != null)
|
|
{
|
|
mPendingMemoryBreakpoint.Deref();
|
|
mPendingMemoryBreakpoint = null;
|
|
}
|
|
DeleteAndNullify!(gApp.mPendingDebugExprHandler);
|
|
}
|
|
|
|
public bool HandleMemoryBreakpointResult(String evalStr, String val, out int addr, out int32 byteCount, String addrType)
|
|
{
|
|
if (val.StartsWith("!", StringComparison.Ordinal))
|
|
{
|
|
String errorString = scope String();
|
|
DebugManager.GetFailString(val, evalStr, errorString);
|
|
IDEApp.sApp.Fail(errorString);
|
|
return false;
|
|
}
|
|
|
|
var vals = scope List<StringView>(val.Split('\n'));
|
|
addr = (int)int64.Parse(scope String(vals[0]), System.Globalization.NumberStyles.HexNumber);
|
|
byteCount = int32.Parse(scope String(vals[1]));
|
|
addrType.Append(vals[2]);
|
|
return true;
|
|
}
|
|
|
|
public MemoryBreakpointResult TryCreateMemoryBreakpoint(String evalStr, out int addr, out int32 byteCount, String addrType, Action<int, int, String> pendingHandler)
|
|
{
|
|
addr = 0;
|
|
byteCount = 0;
|
|
String val = scope String();
|
|
//gApp.mDebugger.Evaluate(evalStr, val, -1);
|
|
let result = gApp.DebugEvaluate(null, evalStr, val, -1, .NotSet, .MemoryWatch | .AllowSideEffects | .AllowCalls, new => PendingExprDone);
|
|
if (result == .Pending)
|
|
{
|
|
Debug.Assert(mOnPendingMemoryBreakpoint == null);
|
|
mOnPendingMemoryBreakpoint = pendingHandler;
|
|
mPendingEvalStr = new String(evalStr);
|
|
return .Pending;
|
|
}
|
|
|
|
delete pendingHandler;
|
|
|
|
return HandleMemoryBreakpointResult(evalStr, val, out addr, out byteCount, addrType) ? .Success : .Failure;
|
|
}
|
|
|
|
void DoCreateMemoryBreakpoint(int addr, int byteCount, String addrType)
|
|
{
|
|
if (addr != 0)
|
|
{
|
|
gApp.RefreshWatches();
|
|
var breakpoint = gApp.mDebugger.CreateMemoryBreakpoint(mCurEvalExpr, addr, byteCount, addrType);
|
|
if (!breakpoint.IsBound())
|
|
{
|
|
ShowMemoryBreakpointError();
|
|
gApp.mDebugger.DeleteBreakpoint(breakpoint);
|
|
}
|
|
else
|
|
breakpoint.mDeleteOnUnbind = true;
|
|
}
|
|
|
|
DeleteAndNullify!(mCurEvalExpr);
|
|
}
|
|
|
|
public void CreateMemoryBreakpoint(String evalStr)
|
|
{
|
|
if (mCurEvalExpr != null)
|
|
{
|
|
gApp.Fail("Already creating memory breakpoint");
|
|
return;
|
|
}
|
|
|
|
int addr = 0;
|
|
int32 byteCount = 0;
|
|
String addrType = scope String();
|
|
switch (gApp.mBreakpointPanel.TryCreateMemoryBreakpoint(evalStr, out addr, out byteCount, addrType, new => DoCreateMemoryBreakpoint))
|
|
{
|
|
case .Pending:
|
|
mCurEvalExpr = new String(evalStr);
|
|
return;
|
|
case .Failure:
|
|
//gApp.Fail("Failed to evaluate to memory address");
|
|
return;
|
|
case .Success:
|
|
mCurEvalExpr = new String(evalStr);
|
|
}
|
|
DoCreateMemoryBreakpoint(addr, byteCount, addrType);
|
|
MarkDirty();
|
|
gApp.RefreshWatches();
|
|
}
|
|
|
|
public void ShowMemoryBreakpointError()
|
|
{
|
|
IDEApp.sApp.Fail("The breakpoint cannot be set. The maximum number of data breakpoints have already been set.");
|
|
}
|
|
|
|
void SetMemoryBreakpoint(Breakpoint breakpoint, int addr, int byteCount, String addrType)
|
|
{
|
|
gApp.RefreshWatches();
|
|
breakpoint.MoveMemoryBreakpoint((int)addr, byteCount, addrType);
|
|
if (!breakpoint.IsBound())
|
|
ShowMemoryBreakpointError();
|
|
BreakpointsChanged();
|
|
}
|
|
|
|
public void RefreshBreakpoint(BreakpointListViewItem listViewItem)
|
|
{
|
|
//
|
|
if (!IDEApp.sApp.mDebugger.mIsRunning)
|
|
return; // Fail
|
|
|
|
var breakpoint = listViewItem.mBreakpoint;
|
|
|
|
int addr;
|
|
int32 byteCount;
|
|
String addrType = scope String();
|
|
switch (TryCreateMemoryBreakpoint(listViewItem.mBreakpoint.mMemoryWatchExpression, out addr, out byteCount, addrType, new => ExistingPendingExprDone))
|
|
{
|
|
case .Failure:
|
|
return;
|
|
case .Success:
|
|
case .Pending:
|
|
Debug.Assert(mPendingMemoryBreakpoint == null);
|
|
mPendingMemoryBreakpoint = breakpoint;
|
|
mPendingMemoryBreakpoint.AddRef();
|
|
return;
|
|
}
|
|
//if (newBreakpoint == null)
|
|
//return;
|
|
|
|
SetMemoryBreakpoint(breakpoint, addr, byteCount, addrType);
|
|
}
|
|
|
|
public void SelectBreakpoints(HashSet<Breakpoint> breakpoints)
|
|
{
|
|
mListView.GetRoot().WithItems(scope (listViewItem) =>
|
|
{
|
|
var breakListViewItem = (BreakpointListViewItem)listViewItem;
|
|
breakListViewItem.Selected = breakpoints.Contains(breakListViewItem.mBreakpoint);
|
|
if (breakListViewItem.Selected)
|
|
{
|
|
if (mWidgetWindow != null)
|
|
mListView.EnsureItemVisible(breakListViewItem, false);
|
|
}
|
|
});
|
|
mHasPendingSelectionClear = true;
|
|
}
|
|
|
|
public void Populate()
|
|
{
|
|
var root = mListView.GetRoot();
|
|
var debugger = IDEApp.sApp.mDebugger;
|
|
while (root.GetChildCount() > debugger.mBreakpointList.Count)
|
|
{
|
|
root.RemoveChildItemAt(debugger.mBreakpointList.Count);
|
|
}
|
|
|
|
for (int32 breakIdx = 0; breakIdx < debugger.mBreakpointList.Count; breakIdx++)
|
|
{
|
|
var breakpoint = debugger.mBreakpointList[breakIdx];
|
|
if (breakIdx >= root.GetChildCount())
|
|
{
|
|
var newItem = root.CreateChildItem();
|
|
newItem.mOnMouseDown.Add(new => ListViewItemMouseDown);
|
|
newItem.mOnMouseClick.Add(new => ListViewItemClicked);
|
|
|
|
var subItem = newItem.CreateSubItem(1);
|
|
subItem.mOnMouseDown.Add(new => ListViewItemMouseDown);
|
|
subItem.mOnMouseClick.Add(new => ListViewItemClicked);
|
|
|
|
subItem = newItem.CreateSubItem(2);
|
|
subItem.mOnMouseDown.Add(new => ListViewItemMouseDown);
|
|
subItem.mOnMouseClick.Add(new => ListViewItemClicked);
|
|
|
|
subItem = newItem.CreateSubItem(3);
|
|
subItem.mOnMouseDown.Add(new => ListViewItemMouseDown);
|
|
subItem.mOnMouseClick.Add(new => ListViewItemClicked);
|
|
|
|
subItem = newItem.CreateSubItem(4);
|
|
subItem.mOnMouseDown.Add(new => ListViewItemMouseDown);
|
|
subItem.mOnMouseClick.Add(new => ListViewItemClicked);
|
|
}
|
|
var listViewItem = (BreakpointListViewItem)root.GetChildAtIndex(breakIdx);
|
|
listViewItem.mTextColor = Color.White;
|
|
|
|
listViewItem.mIsBold = breakpoint.IsActiveBreakpoint();
|
|
|
|
var locString = scope String();
|
|
breakpoint.ToString_Location(locString);
|
|
listViewItem.Label = locString;
|
|
if (breakpoint.IsBound())
|
|
listViewItem.mTextColor = 0xFFFFFFFF;
|
|
else
|
|
listViewItem.mTextColor = 0x80FFFFFF;
|
|
|
|
// Condition
|
|
var subItem = listViewItem.GetSubItem(2);
|
|
if (breakpoint == gApp.mDebugger.mRunToCursorBreakpoint)
|
|
subItem.Label = "Run to cursor";
|
|
else if (breakpoint.mCondition != null)
|
|
subItem.Label = breakpoint.mCondition;
|
|
else
|
|
subItem.Label = "";
|
|
|
|
// Hit count
|
|
subItem = listViewItem.GetSubItem(3);
|
|
let hitCountLabel = scope String();
|
|
breakpoint.ToString_HitCount(hitCountLabel);
|
|
subItem.Label = hitCountLabel;
|
|
|
|
// Logging
|
|
subItem = listViewItem.GetSubItem(4);
|
|
if (breakpoint.mLogging != null)
|
|
subItem.Label = breakpoint.mLogging;
|
|
else
|
|
subItem.Label = "";
|
|
|
|
listViewItem.Bind(breakpoint);
|
|
|
|
if (breakpoint.mIsMemoryBreakpoint && (!breakpoint.IsBound()))
|
|
{
|
|
if (listViewItem.mWatchRefreshButton == null)
|
|
{
|
|
var watchRefreshButton = new WatchRefreshButton();
|
|
watchRefreshButton.Resize(GS!(-16), 0, GS!(20), GS!(20));
|
|
watchRefreshButton.mOnMouseDown.Add(new (evt) => RefreshBreakpoint(listViewItem));
|
|
var typeSubItem = listViewItem.GetSubItem(1);
|
|
typeSubItem.AddWidget(watchRefreshButton);
|
|
listViewItem.mWatchRefreshButton = watchRefreshButton;
|
|
listViewItem.mTextAreaLengthOffset = -16;
|
|
}
|
|
}
|
|
else if (listViewItem.mWatchRefreshButton != null)
|
|
{
|
|
listViewItem.mTextAreaLengthOffset = 0;
|
|
defer delete listViewItem.mWatchRefreshButton;
|
|
listViewItem.mWatchRefreshButton.RemoveSelf();
|
|
listViewItem.mWatchRefreshButton = null;
|
|
}
|
|
|
|
/*else if (breakpoint.GetAddress() != 0)
|
|
listViewItem.Label = String.Format("{0}", Path.GetFileName(breakpoint.mFileName), breakpoint.mLineNum);*/
|
|
}
|
|
}
|
|
|
|
public override void Update()
|
|
{
|
|
base.Update();
|
|
if (mListDirty)
|
|
{
|
|
Populate();
|
|
mListDirty = false;
|
|
}
|
|
|
|
if ((mHasPendingSelectionClear) && (!mHasFocus) && (!gApp.HasPopupMenus()) && (!gApp.HasModalDialogs()))
|
|
{
|
|
// Don't clear focus if there's a dialog or something else with focus
|
|
mListView.GetRoot().SelectItemExclusively(null);
|
|
mHasPendingSelectionClear = false;
|
|
}
|
|
|
|
if (mWidgetWindow == null)
|
|
{
|
|
mListView.mListSizeDirty = true;
|
|
}
|
|
}
|
|
|
|
public override void Resize(float x, float y, float width, float height)
|
|
{
|
|
base.Resize(x, y, width, height);
|
|
mListView.Resize(0, 0, width, height);
|
|
mListView.ScrollPositionChanged();
|
|
}
|
|
|
|
public override void KeyDown(KeyCode keyCode, bool isRepeat)
|
|
{
|
|
mListView.KeyDown(keyCode, isRepeat);
|
|
|
|
base.KeyDown(keyCode, isRepeat);
|
|
|
|
switch (keyCode)
|
|
{
|
|
case .Apps:
|
|
ShowRightClickMenu(mListView);
|
|
case KeyCode.Delete:
|
|
mListView.GetRoot().WithSelectedItems(scope (listViewItem) =>
|
|
{
|
|
var breakpointListViewItem = (BreakpointListViewItem)listViewItem;
|
|
BfLog.LogDbg("Manually deleting breakpoint\n");
|
|
IDEApp.sApp.mDebugger.DeleteBreakpoint(breakpointListViewItem.mBreakpoint);
|
|
});
|
|
default:
|
|
}
|
|
}
|
|
|
|
public override void LostFocus()
|
|
{
|
|
base.LostFocus();
|
|
if (mDeselectOnFocusLost)
|
|
mListView.GetRoot().SelectItemExclusively(null);
|
|
}
|
|
|
|
public override void DrawAll(Graphics g)
|
|
{
|
|
base.DrawAll(g);
|
|
}
|
|
}
|
|
}
|