2019-08-23 11:56:54 -07:00
using System ;
2020-04-29 06:40:03 -07:00
using System.Collections ;
2019-08-23 11:56:54 -07:00
using System.Diagnostics ;
using System.Text ;
using System.Threading.Tasks ;
using Beefy ;
using Beefy.widgets ;
using Beefy.theme ;
using Beefy.gfx ;
using Beefy.theme.dark ;
using Beefy.events ;
using Beefy.utils ;
using IDE.Debugger ;
2022-05-21 11:58:01 -07:00
using Beefy.geom ;
2019-08-23 11:56:54 -07:00
namespace IDE.ui
{
public enum WatchResultType
{
2019-12-24 13:13:04 -08:00
None = 0 ,
Value = 1 ,
Int = 2 ,
2020-06-19 06:42:52 -07:00
Float = 4 ,
MM128 = 8 ,
Object = 0x10 ,
2020-09-03 09:31:22 -07:00
Interface = 0x20 ,
Pointer = 0x40 ,
TypeClass = 0x80 ,
TypeValueType = 0x100 ,
Namespace = 0x200 ,
2021-02-25 10:14:22 -08:00
Text = 0x400 ,
2022-05-18 13:23:10 -07:00
RawText = 0x800 ,
2019-08-23 11:56:54 -07:00
}
public class WatchEntry
{
public bool mIsDeleted ;
public bool mIsAppendAlloc ;
public bool mIsStackAlloc ;
public WatchResultType mResultType ;
public DebugManager . Language mLanguage = . NotSet ;
public String mName ~ delete _ ;
2022-05-21 11:58:01 -07:00
public String mStackFrameId ~ delete _ ;
public bool mWantsStackFrameId ;
2019-08-23 11:56:54 -07:00
public String mEvalStr ~ delete _ ;
2022-05-23 08:48:55 -07:00
public String mAddrValueExpr ~ delete _ ;
public String mPointeeExpr ~ delete _ ;
2019-08-23 11:56:54 -07:00
public bool mCanEdit ;
2024-11-20 11:32:56 -05:00
public String mPointer ~ delete _ ;
public String mEditInitialize ~ delete _ ;
2019-08-23 11:56:54 -07:00
public bool mHadValue ;
public bool mHasValue ;
public bool mIsNewExpression ;
public bool mIsPending ;
2022-05-21 11:58:01 -07:00
public bool mUsedLock ;
2024-12-31 13:17:53 -08:00
public bool? mAutoRefresh ;
public int32 mDebuggerStateIdx ;
2022-05-21 11:58:01 -07:00
public int32 mCurStackIdx ;
2019-08-23 11:56:54 -07:00
public int mMemoryBreakpointAddr ;
public int32 mHadStepCount ;
2022-05-18 13:23:10 -07:00
public String mStringView ~ delete _ ;
2019-08-23 11:56:54 -07:00
public String mReferenceId ~ delete _ ;
public String mResultTypeStr ~ delete _ ;
public String mAction ~ delete _ ;
public List < String > mWarnings ~ DeleteContainerAndItems ! ( _ ) ;
2019-10-09 16:18:11 -07:00
public int32 mSeriesFirstVersion = - 1 ;
public int32 mSeriesVersion = - 1 ;
2019-08-23 11:56:54 -07:00
2024-12-31 13:17:53 -08:00
public bool AutoRefresh
{
get
{
if ( mAutoRefresh ! = null )
return mAutoRefresh . Value ;
return gApp . mSettings . mDebuggerSettings . mAutoRefreshWatches ;
}
set
{
if ( value = = gApp . mSettings . mDebuggerSettings . mAutoRefreshWatches )
mAutoRefresh = null ;
else
mAutoRefresh = value ;
}
}
2019-12-24 13:13:04 -08:00
public bool IsConstant
{
get
{
if ( mEvalStr . IsEmpty )
return true ;
if ( mEvalStr [ 0 ] . IsNumber )
return true ;
return false ;
}
}
2019-08-23 11:56:54 -07:00
public bool ParseCmd ( List < StringView > cmd )
{
switch ( scope String ( cmd [ 0 ] ) )
{
2020-06-19 06:42:52 -07:00
case ":type" :
switch ( scope String ( cmd [ 1 ] ) )
{
case "object" :
mResultType | = WatchResultType . Object ;
return true ;
case "pointer" :
mResultType | = WatchResultType . Pointer ;
return true ;
case "class" :
mResultType | = WatchResultType . TypeClass ;
return true ;
case "valuetype" :
mResultType | = WatchResultType . TypeValueType ;
2019-08-23 11:56:54 -07:00
return true ;
2020-06-19 06:42:52 -07:00
case "namespace" :
mResultType | = WatchResultType . Namespace ;
2019-08-23 11:56:54 -07:00
return true ;
2020-06-19 06:42:52 -07:00
case "int" :
mResultType | = WatchResultType . Int ;
return true ;
2020-09-03 09:31:22 -07:00
case "interface" :
mResultType | = WatchResultType . Interface ;
return true ;
2020-06-19 06:42:52 -07:00
case "float" :
mResultType | = WatchResultType . Float ;
return true ;
case "mm128" :
mResultType | = WatchResultType . MM128 ;
return true ;
}
break ;
case ":appendAlloc" :
mIsAppendAlloc = true ;
return true ;
case ":stack" :
mIsStackAlloc = true ;
return true ;
case ":deleted" :
mIsDeleted = true ;
return true ;
2019-08-23 11:56:54 -07:00
}
return false ;
}
}
public interface IWatchOwner
{
WatchListView GetWatchListView ( ) ;
void UpdateWatch ( WatchListViewItem watchEntry ) ;
void SetupListViewItem ( WatchListViewItem listViewItem , String name , String evalStr ) ;
}
public class WatchListView : IDEListView
{
2024-03-25 06:18:50 -04:00
public class FindState
{
public int32 mDir ;
public int32 mItr ;
public int32 mPrevId ;
2024-03-26 07:30:54 -04:00
public HashSet < int32 > InitialOpenIds ~ delete _ ;
public double mScrollPos ;
public HashSet < String > mOpenedExprs ~ DeleteContainerAndItems ! ( _ ) ;
2024-03-25 06:18:50 -04:00
}
public class CloseButton : ButtonWidget
{
public override void Draw ( Graphics g )
{
base . Draw ( g ) ;
if ( mMouseOver )
{
using ( g . PushColor ( mMouseDown ? 0xFFFF0000 : Color . White ) )
g . Draw ( DarkTheme . sDarkTheme . GetImage ( DarkTheme . ImageIdx . CloseOver ) , GS ! ( 0 ) , GS ! ( 0 ) ) ;
}
else
{
g . Draw ( DarkTheme . sDarkTheme . GetImage ( DarkTheme . ImageIdx . Close ) , GS ! ( 0 ) , GS ! ( 0 ) ) ;
}
}
public override void MouseClicked ( float x , float y , float origX , float origY , int32 btn )
{
base . MouseClicked ( x , y , origX , origY , btn ) ;
var watchListView = ( WatchListView ) mParent . mParent ;
watchListView . HideFind ( ) ;
}
public override void MouseMove ( float x , float y )
{
base . MouseMove ( x , y ) ;
MarkDirty ( ) ;
}
public override void MouseLeave ( )
{
base . MouseLeave ( ) ;
MarkDirty ( ) ;
}
}
2024-03-26 07:30:54 -04:00
public enum FindFlags
{
None ,
Active = 1 ,
Filtering = 2 ,
Selection = 4 ,
Deep = 8 ,
}
2019-08-23 11:56:54 -07:00
public IWatchOwner mWatchOwner ;
public static int32 sCurDynReferenceId ;
2024-03-25 06:18:50 -04:00
public DarkEditWidget mFindWidget ;
public CloseButton mCloseButton ;
public ToggleButton mFilterButton ;
2024-03-26 07:30:54 -04:00
public ToggleButton mSelectionButton ;
public ToggleButton mDeepButton ;
2024-03-25 06:18:50 -04:00
public String mFindString ~ delete _ ;
public int32 mFindIdx ;
2024-03-26 07:30:54 -04:00
public FindFlags mFindFlags ;
public HashSet < int > mFindSelection ~ delete _ ;
public HashSet < int > mFindParents ~ delete _ ;
public HashSet < int > mFindDeepOpened ~ delete _ ;
public HashSet < String > mFindOpenedExprs ~ DeleteContainerAndItems ! ( _ ) ;
public FindState mFindState ;
public Stopwatch mItrStopwatch ;
public int32 mMaxFindDepth = 256 ;
public int32 mMakeFocusVisibleDelay ;
2024-03-25 06:18:50 -04:00
public int32 mLastWorkTick ;
public int32 mWorkTicks ;
2019-08-23 11:56:54 -07:00
public this ( IWatchOwner IWatchOwner )
{
mWatchOwner = IWatchOwner ;
}
protected override ListViewItem CreateListViewItem ( )
{
if ( mWatchOwner = = null ) // For root node, mWatchOwner not set yet
return new IDEListViewItem ( ) ;
WatchListViewItem anItem = new WatchListViewItem ( mWatchOwner , this ) ;
return anItem ;
}
public override void MouseDown ( float x , float y , int32 btn , int32 btnCount )
{
base . MouseDown ( x , y , btn , btnCount ) ;
if ( var watchPanel = mParent as WatchPanel )
{
watchPanel . SetFocus ( ) ;
}
}
2024-03-25 06:18:50 -04:00
protected override void SetScaleData ( )
{
base . SetScaleData ( ) ;
if ( mFindWidget ! = null )
{
mScrollbarInsets . mTop + = GS ! ( 23 ) ;
mFindWidget . mEditWidgetContent . mTextInsets . mLeft = GS ! ( 20 ) ;
}
mIconX = GS ! ( 4 ) ;
mOpenButtonX = GS ! ( 4 ) ;
mLabelX = GS ! ( 44 ) ;
mChildIndent = GS ! ( 16 ) ;
mHiliteOffset = GS ! ( - 2 ) ;
}
2024-03-26 07:30:54 -04:00
public void RehupListView ( )
2024-03-25 06:18:50 -04:00
{
SetScaleData ( ) ;
RehupSize ( ) ;
UpdateScrollbars ( ) ;
}
2024-03-26 07:30:54 -04:00
void RehupSelected ( )
{
if ( mSelectionButton ? . mToggled ! = true )
{
DeleteAndNullify ! ( mFindSelection ) ;
DeleteAndNullify ! ( mFindParents ) ;
return ;
}
if ( mFindSelection = = null )
mFindSelection = new HashSet < int > ( ) ;
else
mFindSelection . Clear ( ) ;
if ( mFindParents = = null )
mFindParents = new HashSet < int > ( ) ;
else
mFindParents . Clear ( ) ;
mRoot . WithSelectedItems ( scope ( listViewItem ) = >
{
ListViewItem checkItem = listViewItem ;
while ( ( checkItem ! = null ) & & ( checkItem ! = mRoot ) )
{
var watchListViewItem = ( WatchListViewItem ) checkItem ;
if ( watchListViewItem = = listViewItem )
mFindSelection . Add ( watchListViewItem . mId ) ;
else
mFindParents . Add ( watchListViewItem . mId ) ;
checkItem = checkItem . mParentItem ;
}
} , true ) ;
}
public void RehupFind ( )
{
if ( mFindWidget = = null )
return ;
if ( mSelectionButton ? . mToggled ! = true )
{
Debug . Assert ( mFindSelection = = null ) ;
// Rebuild this "sticky open list" whenever any options change
DeleteAndNullify ! ( mFindParents ) ;
}
DeleteAndNullify ! ( mFindDeepOpened ) ;
mFindOpenedExprs ? . ClearAndDelete ( ) ;
DeleteAndNullify ! ( mFindOpenedExprs ) ;
mFindIdx + + ;
if ( mFindString = = null )
{
mFindFlags = . None ;
}
else
{
mFindFlags = . Active ;
if ( mFilterButton . mToggled )
mFindFlags | = . Filtering ;
if ( mSelectionButton . mToggled )
mFindFlags | = . Selection ;
if ( mDeepButton . mToggled )
{
mFindDeepOpened = new . ( ) ;
mFindOpenedExprs = new . ( ) ;
mFindFlags | = . Deep ;
}
}
// Do one iteration to stabilize drawing
UpdateAll ( ) ;
}
2024-03-25 06:18:50 -04:00
public void ShowFind ( )
{
if ( mFindWidget = = null )
{
mFindWidget = new DarkEditWidget ( ) ;
mFindWidget . mOnKeyDown . Add ( new ( keyboardEvent ) = >
{
if ( keyboardEvent . mKeyCode = = . Escape )
{
2024-03-26 07:30:54 -04:00
Cancel ( ) ;
2024-03-25 06:18:50 -04:00
}
if ( keyboardEvent . mKeyCode = = . Tab )
{
mFilterButton . SetFocus ( ) ;
}
if ( keyboardEvent . mKeyCode = = . Return )
{
FindNext ( 1 ) ;
}
} ) ;
mFindWidget . mOnContentChanged . Add ( new ( evt ) = >
{
if ( mFindString = = null )
mFindString = new . ( ) ;
mFindString . Clear ( ) ;
mFindWidget . GetText ( mFindString ) ;
if ( mFindString . IsEmpty )
{
DeleteAndNullify ! ( mFindString ) ;
}
2024-03-26 07:30:54 -04:00
RehupFind ( ) ;
2024-03-25 06:18:50 -04:00
} ) ;
AddWidget ( mFindWidget ) ;
var watchListView = this ;
mCloseButton = new CloseButton ( ) ;
mFindWidget . AddWidget ( mCloseButton ) ;
mFilterButton = new ToggleButton ( ) ;
mFilterButton . mOnKeyDown . Add ( new ( keyboardEvent ) = >
{
if ( keyboardEvent . mKeyCode = = . Escape )
{
2024-03-26 07:30:54 -04:00
Cancel ( ) ;
2024-03-25 06:18:50 -04:00
}
if ( keyboardEvent . mKeyCode = = . Tab )
{
if ( keyboardEvent . mKeyFlags . HasFlag ( . Shift ) )
mFindWidget . SetFocus ( ) ;
2024-03-26 07:30:54 -04:00
else
mSelectionButton . SetFocus ( ) ;
}
} ) ;
mFilterButton . Label = "Filter" ;
mFilterButton . HoverText = "Hide items that don't match search criteria" ;
mFilterButton . mOnMouseDown . Add ( new [ & ] ( mouseArgs ) = >
{
if ( ! mFilterButton . mToggled )
mMakeFocusVisibleDelay = 3 ;
RehupFind ( ) ;
} ) ;
mFindWidget . AddWidget ( mFilterButton ) ;
mSelectionButton = new ToggleButton ( ) ;
mSelectionButton . mOnKeyDown . Add ( new ( keyboardEvent ) = >
{
if ( keyboardEvent . mKeyCode = = . Escape )
{
Cancel ( ) ;
}
if ( keyboardEvent . mKeyCode = = . Tab )
{
if ( keyboardEvent . mKeyFlags . HasFlag ( . Shift ) )
mFilterButton . SetFocus ( ) ;
else
mDeepButton . SetFocus ( ) ;
}
} ) ;
mSelectionButton . Label = "Selection" ;
mSelectionButton . HoverText = "Only search in selected items" ;
mSelectionButton . mOnMouseDown . Add ( new [ & ] ( mouseArgs ) = >
{
RehupSelected ( ) ;
RehupFind ( ) ;
} ) ;
mFindWidget . AddWidget ( mSelectionButton ) ;
if ( mRoot . FindFirstSelectedItem ( ) ! = null )
mSelectionButton . mToggled = true ;
mDeepButton = new ToggleButton ( ) ;
mDeepButton . mOnKeyDown . Add ( new ( keyboardEvent ) = >
{
if ( keyboardEvent . mKeyCode = = . Escape )
{
Cancel ( ) ;
}
if ( keyboardEvent . mKeyCode = = . Tab )
{
if ( keyboardEvent . mKeyFlags . HasFlag ( . Shift ) )
mSelectionButton . SetFocus ( ) ;
2024-03-25 06:18:50 -04:00
else
{
watchListView . mParent . SetFocus ( ) ;
2024-03-26 07:30:54 -04:00
var selectedItem = watchListView . mRoot . FindFirstSelectedItem ( ) ;
if ( selectedItem ! = null )
2024-03-25 06:18:50 -04:00
{
2024-03-26 07:30:54 -04:00
SetFocus ( ) ;
}
else
{
var widget = watchListView . FindWidgetByCoords ( mWidth - GS ! ( 30 ) , mFindWidget . mY + mFindWidget . mHeight + GS ! ( 10 ) ) ;
if ( var listViewItem = widget as ListViewItem )
{
listViewItem . GetSubItem ( 0 ) . Focused = true ;
}
2024-03-25 06:18:50 -04:00
}
}
}
} ) ;
2024-03-26 07:30:54 -04:00
mDeepButton . Label = "Deep" ;
mDeepButton . HoverText = "Search in closed items" ;
mDeepButton . mOnMouseDown . Add ( new [ & ] ( mouseArgs ) = >
2024-03-25 06:18:50 -04:00
{
2024-03-26 07:30:54 -04:00
RehupFind ( ) ;
2024-03-25 06:18:50 -04:00
} ) ;
2024-03-26 07:30:54 -04:00
mFindWidget . AddWidget ( mDeepButton ) ;
2024-03-25 06:18:50 -04:00
}
// Doing it twice allows us to lose focus of editing an item and then refocus ourselves
mFindWidget . SetFocus ( ) ;
2024-03-26 07:30:54 -04:00
mFindWidget . mEditWidgetContent . SelectAll ( ) ;
2024-03-25 06:18:50 -04:00
mFindWidget . SetFocus ( ) ;
2024-03-26 07:30:54 -04:00
RehupListView ( ) ;
RehupSelected ( ) ;
2024-03-25 06:18:50 -04:00
RehupFind ( ) ;
}
public bool WithNextItems ( ListViewItem item , int32 dir , List < ListViewItem > fromList , delegate bool ( WatchListViewItem item , int idx ) dlg )
{
if ( item . mChildItems = = null )
return true ;
2024-03-26 07:30:54 -04:00
var watchListViewItem = item as WatchListViewItem ;
2024-03-25 06:18:50 -04:00
if ( ( item . mParentItem ! = null ) & & ( ! item . IsOpen ) )
2024-03-26 07:30:54 -04:00
{
bool wantOpen = false ;
if ( mFindFlags . HasFlag ( . Deep ) )
{
if ( mFindFlags . HasFlag ( . Selection ) )
{
ListViewItem checkItem = item ;
while ( checkItem ! = mRoot )
{
var checkWatchListViewItem = ( WatchListViewItem ) checkItem ;
if ( mFindSelection . Contains ( checkWatchListViewItem . mId ) )
wantOpen = true ;
checkItem = checkItem . mParentItem ;
}
}
else if ( item . mDepth < mMaxFindDepth )
wantOpen = true ;
if ( wantOpen )
{
if ( ( mFindState . mOpenedExprs ! = null ) & & ( watchListViewItem ! = null ) )
{
if ( watchListViewItem . mWatchEntry ! = null )
{
if ( ( watchListViewItem . mWatchEntry . mLanguage = = . Beef ) & & ( watchListViewItem . mWatchEntry . mResultTypeStr = = "System.String" ) )
{
// Optimization to avoid inspecting string members, particularly the [RawChars]
wantOpen = false ;
}
else
{
wantOpen = mFindState . mOpenedExprs . TryAdd ( watchListViewItem . mWatchEntry . mEvalStr , var exprPtr ) ;
if ( wantOpen )
{
* exprPtr = new . ( watchListViewItem . mWatchEntry . mEvalStr ) ;
}
}
}
}
}
}
if ( ( wantOpen ) | | ( mFindSelection ? . Contains ( ( watchListViewItem ? . mId ) . GetValueOrDefault ( ) ) = = true ) )
{
item . Open ( true , true ) ;
}
else
return true ;
}
2024-03-25 06:18:50 -04:00
int idx = ( dir > 0 ) ? - 1 : item . mChildItems . Count ;
if ( ! fromList . IsEmpty )
{
idx = item . mChildItems . IndexOf ( fromList . PopBack ( ) ) ;
if ( idx = = - 1 )
{
// Failed
fromList . Clear ( ) ;
}
else if ( ( dir < 0 ) & & ( fromList . IsEmpty ) )
{
// Don't do anything
}
else
{
var childItem = ( WatchListViewItem ) item . mChildItems [ idx ] ;
if ( ! WithNextItems ( childItem , dir , fromList , dlg ) )
return false ;
if ( dir < 0 )
{
if ( ! dlg ( childItem , idx ) )
return false ;
}
}
}
while ( true )
{
idx + = dir ;
if ( ( idx < 0 ) | | ( idx > = item . mChildItems . Count ) )
break ;
var childItem = ( WatchListViewItem ) item . mChildItems [ idx ] ;
if ( dir > 0 )
{
if ( ! dlg ( childItem , idx ) )
return false ;
}
if ( ! WithNextItems ( childItem , dir , fromList , dlg ) )
return false ;
if ( dir < 0 )
{
if ( ! dlg ( childItem , idx ) )
return false ;
}
}
return true ;
}
void ClearFindState ( )
{
if ( mFindState = = null )
return ;
2024-03-26 07:30:54 -04:00
if ( mFindState . InitialOpenIds ! = null )
{
// Add selected items (and parents) to open list to make sure we don't close them
mRoot . WithSelectedItems ( scope ( listViewItem ) = >
2024-03-25 06:18:50 -04:00
{
2024-03-26 07:30:54 -04:00
ListViewItem checkItem = listViewItem ;
while ( ( checkItem ! = null ) & & ( checkItem ! = mRoot ) )
{
var watchListViewItem = ( WatchListViewItem ) checkItem ;
mFindState . InitialOpenIds . Add ( watchListViewItem . mId ) ;
checkItem = checkItem . mParentItem ;
}
} ) ;
mRoot . WithItems ( scope ( listViewItem ) = >
{
var watchListViewItem = ( WatchListViewItem ) listViewItem ;
if ( ( listViewItem . IsParent ) & & ( ! mFindState . InitialOpenIds . Contains ( watchListViewItem . mId ) ) )
{
listViewItem . Open ( false , true ) ;
mMakeFocusVisibleDelay = 3 ;
}
} ) ;
}
2024-03-25 06:18:50 -04:00
DeleteAndNullify ! ( mFindState ) ;
}
void CreateFindState ( )
{
ClearFindState ( ) ;
mFindState = new FindState ( ) ;
2024-03-26 07:30:54 -04:00
if ( mFindFlags . HasFlag ( . Deep ) )
{
mFindState . InitialOpenIds = new . ( ) ;
mRoot . WithItems ( scope ( listViewItem ) = >
{
var watchListViewItem = ( WatchListViewItem ) listViewItem ;
if ( watchListViewItem . IsOpen )
mFindState . InitialOpenIds . Add ( watchListViewItem . mId ) ;
} ) ;
mFindState . mOpenedExprs = new HashSet < String > ( ) ;
}
mFindState . mScrollPos = mVertPos . v ;
2024-03-25 06:18:50 -04:00
}
public bool UpdateFind ( )
{
if ( mRoot . GetChildCount ( ) = = 0 )
return false ;
mFindIdx + + ;
WatchListViewItem selectedItem = null ;
if ( mFindState . mPrevId ! = 0 )
{
mRoot . WithItems ( scope [ & ] ( listViewItem ) = >
{
var watchListViewItem = ( WatchListViewItem ) listViewItem ;
if ( watchListViewItem . mId = = mFindState . mPrevId )
selectedItem = watchListViewItem ;
} ) ;
}
else
{
selectedItem = ( WatchListViewItem ) mRoot . FindFirstSelectedItem ( ) ;
2024-03-26 07:30:54 -04:00
if ( ( selectedItem = = null ) & & ( mFindSelection ! = null ) )
{
mRoot . WithItems ( scope [ & ] ( listViewItem ) = >
{
if ( selectedItem = = null )
{
var watchListViewItem = ( WatchListViewItem ) listViewItem ;
if ( mFindSelection . Contains ( watchListViewItem . mId ) )
selectedItem = watchListViewItem ;
}
} ) ;
}
2024-03-25 06:18:50 -04:00
}
List < ListViewItem > selectList = scope . ( ) ;
ListViewItem checkItem = selectedItem ;
while ( ( checkItem ! = null ) & & ( checkItem ! = mRoot ) )
{
selectList . Add ( checkItem ) ;
checkItem = checkItem . mParentItem ;
}
mFindState . mPrevId = 0 ;
float? wantY = null ;
WatchSeriesInfo curSeriesInfo = null ;
WatchListViewItem prevSeriesItem = null ;
WatchListViewItem nextItem = null ;
WithNextItems ( mRoot , mFindState . mDir , selectList , scope [ & ] ( listViewItem , idx ) = >
{
void ContinueFromItem ( WatchListViewItem item , bool atEnd )
{
var atEnd ;
if ( mFindState . mDir < 0 )
atEnd = ! atEnd ;
mFindState . mPrevId = item . mId ;
item . SelfToOtherTranslate ( mScrollContent , 0 , atEnd ? ( item . mHeight - 1 ) : 0 , ? , var transY ) ;
wantY = transY ;
if ( mFindState . mDir < 0 )
wantY - = mScrollContentContainer . mHeight ;
}
2024-03-26 07:30:54 -04:00
if ( mItrStopwatch . ElapsedMilliseconds > = 20 )
{
ContinueFromItem ( listViewItem , true ) ;
return false ;
}
if ( listViewItem . mLastFindIdx ! = mFindIdx )
{
listViewItem . CheckFindString ( ) ;
}
2024-03-25 06:18:50 -04:00
if ( ! listViewItem . mFindMismatch )
{
nextItem = listViewItem ;
return false ;
}
if ( listViewItem . mWatchSeriesInfo ! = curSeriesInfo )
{
if ( curSeriesInfo ! = null )
{
if ( ( prevSeriesItem . mSeriesMemberIdx ! = curSeriesInfo . mCount - 1 ) & &
( prevSeriesItem . mSeriesMemberIdx ! = curSeriesInfo . mShowPages * curSeriesInfo . mShowPageSize - 1 ) )
{
// We didn't finish the previous series
ContinueFromItem ( prevSeriesItem , true ) ;
return false ;
}
}
curSeriesInfo = listViewItem . mWatchSeriesInfo ;
}
else if ( ( curSeriesInfo ! = null ) & & ( prevSeriesItem ! = null ) & & ( listViewItem . mSeriesMemberIdx ! = prevSeriesItem . mSeriesMemberIdx + mFindState . mDir ) )
{
// Not in sequence
ContinueFromItem ( prevSeriesItem , true ) ;
return false ;
}
prevSeriesItem = listViewItem ;
2024-03-26 07:30:54 -04:00
if ( idx = = listViewItem . mParentItem . mChildItems . Count - 1 )
2024-03-25 06:18:50 -04:00
{
2024-03-26 07:30:54 -04:00
if ( ( listViewItem . mWatchSeriesInfo ! = null ) & & ( listViewItem . mWatchSeriesInfo . mCount > 1 ) & & ( listViewItem . mSeriesMemberIdx = = 0 ) )
2024-03-25 06:18:50 -04:00
{
2024-03-26 07:30:54 -04:00
// This was just opened, give it an update to populate items
ContinueFromItem ( listViewItem , false ) ;
2024-03-25 06:18:50 -04:00
return false ;
}
2024-03-26 07:30:54 -04:00
}
2024-03-25 06:18:50 -04:00
return true ;
} ) ;
if ( wantY ! = null )
{
2024-03-26 07:30:54 -04:00
UpdateListSize ( ) ;
2024-03-25 06:18:50 -04:00
mVertScrollbar . ScrollTo ( wantY . Value ) ;
return false ;
}
mFindState . mDir = 0 ;
if ( nextItem ! = null )
{
mRoot . SelectItemExclusively ( nextItem ) ;
EnsureItemVisible ( nextItem , false ) ;
if ( mFindIdx > 1 )
{
nextItem . SelfToOtherTranslate ( mScrollContent , 0 , nextItem . mHeight / 2 , ? , var transY ) ;
mVertScrollbar . ScrollTo ( Math . Max ( transY - mScrollContentContainer . mHeight / 2 , 0 ) ) ;
}
}
else
{
2024-03-26 07:30:54 -04:00
mVertScrollbar . ScrollTo ( mFindState . mScrollPos ) ;
2024-03-25 06:18:50 -04:00
IDEApp . Beep ( IDEApp . MessageBeepType . Information ) ;
IDEApp . sApp . MessageDialog ( "Search Done" , "Find reached the starting point of the search." ) ;
mRoot . SelectItemExclusively ( null ) ;
}
return true ;
}
public void FindNext ( int32 dir )
{
if ( mFindString = = null )
return ;
CreateFindState ( ) ;
mFindState . mDir = dir ;
}
public void HideFind ( )
{
2024-03-26 07:30:54 -04:00
ClearFindState ( ) ;
2024-03-25 06:18:50 -04:00
DeleteAndNullify ! ( mFindString ) ;
mFindIdx + + ;
mFindWidget . RemoveSelf ( ) ;
gApp . DeferDelete ( mFindWidget ) ;
mFindWidget = null ;
mCloseButton = null ;
2024-03-26 07:30:54 -04:00
RehupListView ( ) ;
2024-03-25 06:18:50 -04:00
mParent . SetFocus ( ) ;
2024-03-26 07:30:54 -04:00
DeleteAndNullify ! ( mFindSelection ) ;
DeleteAndNullify ! ( mFindParents ) ;
DeleteAndNullify ! ( mFindDeepOpened ) ;
2024-03-26 12:10:15 -04:00
mFindOpenedExprs ? . ClearAndDelete ( ) ;
2024-03-26 07:30:54 -04:00
DeleteAndNullify ! ( mFindOpenedExprs ) ;
mFindFlags = . None ;
}
void Cancel ( )
{
if ( mFindState ! = null )
ClearFindState ( ) ;
else
HideFind ( ) ;
2024-03-25 06:18:50 -04:00
}
void ResizeComponenets ( )
{
if ( mFindWidget ! = null )
{
mFindWidget . Resize ( 0 , GS ! ( 20 ) , mWidth , GS ! ( 23 ) ) ;
mCloseButton . Resize ( mWidth - GS ! ( 20 ) , GS ! ( 1 ) , GS ! ( 20 ) , GS ! ( 20 ) ) ;
2024-03-26 07:30:54 -04:00
float btnX = mWidth - GS ! ( 50 ) - GS ! ( 70 ) - GS ! ( 50 ) - GS ! ( 20 ) ;
mFilterButton . Resize ( btnX , GS ! ( 1 ) , GS ! ( 50 ) , GS ! ( 21 ) ) ;
btnX + = GS ! ( 50 ) ;
mSelectionButton . Resize ( btnX , GS ! ( 1 ) , GS ! ( 70 ) , GS ! ( 21 ) ) ;
btnX + = GS ! ( 70 ) ;
mDeepButton . Resize ( btnX , GS ! ( 1 ) , GS ! ( 50 ) , GS ! ( 21 ) ) ;
2024-03-25 06:18:50 -04:00
}
}
public override void Resize ( float x , float y , float width , float height )
{
base . Resize ( x , y , width , height ) ;
ResizeComponenets ( ) ;
}
public override void KeyDown ( KeyCode keyCode , bool isRepeat )
{
if ( ( keyCode = = . Escape ) & & ( mFindWidget ! = null ) )
{
2024-03-26 07:30:54 -04:00
Cancel ( ) ;
2024-03-25 06:18:50 -04:00
}
if ( keyCode = = . Tab )
{
if ( mFindWidget ! = null )
mFindWidget . SetFocus ( ) ;
}
base . KeyDown ( keyCode , isRepeat ) ;
}
public override void DrawAll ( Graphics g )
{
base . DrawAll ( g ) ;
if ( mFindWidget ! = null )
{
g . Draw ( DarkTheme . sDarkTheme . GetImage ( . Search ) , mFindWidget . mX + GS ! ( 1 ) , mFindWidget . mY + GS ! ( 1 ) ) ;
if ( mWorkTicks > = 60 )
{
2024-03-26 07:30:54 -04:00
IDEUtils . DrawWait ( g , mFilterButton . mX - GS ! ( 16 ) , mFindWidget . CenterY , gApp . mUpdateCnt ) ;
2024-03-25 06:18:50 -04:00
}
}
}
public void DidWork ( )
{
mLastWorkTick = mUpdateCnt ;
}
public override void Update ( )
{
base . Update ( ) ;
if ( mUpdateCnt - mLastWorkTick < 10 )
{
MarkDirty ( ) ;
mWorkTicks + + ;
}
else if ( mWorkTicks > 0 )
{
MarkDirty ( ) ;
mWorkTicks = 0 ;
}
2024-03-26 07:30:54 -04:00
if ( ( mWorkTicks = = 0 ) & & ( mMakeFocusVisibleDelay > 0 ) & & ( - - mMakeFocusVisibleDelay = = 0 ) )
{
var focusedItem = mRoot . FindFocusedItem ( ) ;
if ( focusedItem ! = null )
EnsureItemVisible ( focusedItem , false ) ;
}
2024-03-25 06:18:50 -04:00
}
public override void UpdateAll ( )
{
2024-03-26 07:30:54 -04:00
mItrStopwatch = scope . ( ) . . Start ( ) ;
2024-03-25 06:18:50 -04:00
for ( int pass = 0 ; true ; pass + + )
{
base . UpdateAll ( ) ;
2024-03-26 07:30:54 -04:00
if ( ( mFindState = = null ) & & ( mWorkTicks = = 0 ) )
2024-03-25 06:18:50 -04:00
break ;
if ( ! gApp . mIsUpdateBatchStart )
break ;
2024-03-26 07:30:54 -04:00
if ( ( pass > 0 ) & & ( mItrStopwatch . ElapsedMilliseconds > = 10 ) )
2024-03-25 06:18:50 -04:00
break ;
2024-03-26 07:30:54 -04:00
if ( ( mFindState ! = null ) & & ( mFindState . mDir ! = 0 ) )
2024-03-25 06:18:50 -04:00
{
if ( UpdateFind ( ) )
ClearFindState ( ) ; // Done
}
2024-03-26 07:30:54 -04:00
mFindWidget ? . mEditWidgetContent . mCursorBlinkTicks = 0 ;
2024-03-25 06:18:50 -04:00
}
}
2019-08-23 11:56:54 -07:00
}
public class ExpressionEditWidgetContent : SourceEditWidgetContent
{
public this ( )
{
SetFont ( DarkTheme . sDarkTheme . mSmallFont , false , false ) ;
mTextInsets . Set ( GS ! ( - 1 ) , GS ! ( 2 ) , 0 , GS ! ( 2 ) ) ;
}
public override void Draw ( Graphics g )
{
base . Draw ( g ) ;
ExpressionEditWidget watchEditWidget = ( ExpressionEditWidget ) mEditWidget ;
if ( watchEditWidget . mErrorEnd ! = 0 )
{
var text = scope String ( ) ;
watchEditWidget . GetText ( text ) ;
if ( watchEditWidget . mErrorStart < text . Length )
{
float indent = mTextInsets . mLeft ;
float strStarts = indent + g . mFont . GetWidth ( scope String ( text , 0 , watchEditWidget . mErrorStart ) ) ;
float strEnds = indent + g . mFont . GetWidth ( scope String ( text , 0 , Math . Min ( watchEditWidget . mErrorEnd , text . Length ) ) ) ;
using ( g . PushColor ( 0xFFFF4040 ) )
IDEApp . sApp . DrawSquiggle ( g , strStarts , GS ! ( 2 ) , strEnds - strStarts ) ;
}
}
}
public override float GetLineHeight ( int line )
{
return GS ! ( 21 ) ;
}
}
public class ExpressionEditWidget : DarkEditWidget
{
public int32 mErrorStart ;
public int32 mErrorEnd ;
int32 mLastTextVersionId ;
public bool mIsAddress ;
public bool mIsSymbol ;
public int mEvalAtAddress ;
public DebugManager . Language mLanguage ;
public String mExprPre ~ delete _ ;
public String mExprPost ~ delete _ ;
public String mLastError ~ delete _ ;
public bool mIgnoreErrors ;
public String mExpectingType ;
//public AutoComplete mAutoComplete;
public this ( )
: base ( new ExpressionEditWidgetContent ( ) )
{
var editWidgetContent = ( ExpressionEditWidgetContent ) mEditWidgetContent ;
2019-09-07 06:40:03 -07:00
editWidgetContent . mOnGenerateAutocomplete = new ( keyChar , options ) = >
{
if ( ( editWidgetContent . mAutoComplete ? . mIsDocumentationPass ) . GetValueOrDefault ( ) )
return ;
UpdateText ( keyChar , true ) ;
} ;
2019-08-23 11:56:54 -07:00
editWidgetContent . mScrollToStartOnLostFocus = true ;
mScrollContentInsets . Set ( GS ! ( 4 ) , GS ! ( 3 ) , GS ! ( 1 ) , GS ! ( 3 ) ) ;
mOnKeyDown . Add ( new = > EditKeyDownHandler ) ;
}
public override void Resize ( float x , float y , float width , float height )
{
base . Resize ( x , y , width , height ) ;
if ( height < = GS ! ( 24 ) )
mScrollContentInsets . Set ( GS ! ( 2 ) , GS ! ( 3 ) , GS ! ( 1 ) , GS ! ( 3 ) ) ;
else
mScrollContentInsets . Set ( GS ! ( 4 ) , GS ! ( 3 ) , GS ! ( 1 ) , GS ! ( 3 ) ) ;
}
void EditKeyDownHandler ( KeyDownEvent evt )
{
if ( evt . mKeyCode = = . Escape )
{
var editWidgetContent = ( ExpressionEditWidgetContent ) mEditWidgetContent ;
if ( editWidgetContent . mAutoComplete ! = null )
{
editWidgetContent . mAutoComplete . Close ( ) ;
evt . mHandled = true ;
return ;
}
}
}
public void ResizeAround ( float targetX , float targetY , float width )
{
Resize ( targetX - GS ! ( 1 ) , targetY - GS ! ( 1 ) , width + GS ! ( 2 ) , GS ! ( 23 ) ) ;
}
public override void LostFocus ( )
{
base . LostFocus ( ) ;
//var sourceEditWidgetContent = (SourceEditWidgetContent)mEditWidgetContent;
//TODO: This was causing autocomplete to close when you clicked on the scroll thumb. Why did we need this?
//if (sourceEditWidgetContent.mAutoComplete != null)
//sourceEditWidgetContent.mAutoComplete.Close();
}
public override void KeyDown ( KeyCode keyCode , bool isRepeat )
{
/ * if ( ( keyCode = = KeyCode . Escape ) & & ( mAutoComplete ! = null ) )
{
mAutoComplete . Close ( ) ;
return ;
} * /
base . KeyDown ( keyCode , isRepeat ) ;
}
public virtual EditSelection GetCurExprRange ( )
{
return EditSelection ( 0 , Content . mData . mTextLength ) ;
}
public virtual void SetAutoCompleteInfo ( String autoCompleteInfo , int textOffset )
{
var editWidgetContent = ( ExpressionEditWidgetContent ) mEditWidgetContent ;
editWidgetContent . mAutoComplete . SetInfo ( autoCompleteInfo , true , ( . ) textOffset ) ;
}
public AutoComplete GetAutoComplete ( )
{
var editWidgetContent = ( ExpressionEditWidgetContent ) mEditWidgetContent ;
if ( editWidgetContent . mAutoComplete = = null )
{
editWidgetContent . mAutoComplete = new AutoComplete ( this ) ;
editWidgetContent . mAutoComplete . mOnAutoCompleteInserted . Add ( new ( ) = > UpdateText ( 0 , true ) ) ;
editWidgetContent . mAutoComplete . mOnClosed . Add ( new ( ) = > { editWidgetContent . mAutoComplete = null ; } ) ;
}
return editWidgetContent . mAutoComplete ;
}
public bool IsShowingAutoComplete ( )
{
let autoComplete = GetAutoComplete ( ) ;
if ( autoComplete = = null )
return false ;
return autoComplete . IsShowing ( ) ;
}
public virtual void UpdateText ( char32 keyChar , bool doAutoComplete )
{
scope AutoBeefPerf ( "ExpressionEditWidget.UpdateText" ) ;
2020-01-23 07:43:44 -08:00
if ( ( keyChar = = 0 ) & & ( doAutoComplete ) )
2019-08-23 11:56:54 -07:00
return ; // Is documentation pass
DeleteAndNullify ! ( mLastError ) ;
var editWidgetContent = ( ExpressionEditWidgetContent ) mEditWidgetContent ;
let exprRange = GetCurExprRange ( ) ;
if ( exprRange . Length = = 0 )
{
if ( editWidgetContent . mAutoComplete ! = null )
editWidgetContent . mAutoComplete . Close ( ) ;
mErrorStart = 0 ;
mErrorEnd = 0 ;
return ;
}
String text = scope String ( ) ;
int32 cursorOfs = 0 ;
if ( mExprPre ! = null )
{
text . Append ( mExprPre ) ;
cursorOfs = ( . ) mExprPre . Length ;
}
editWidgetContent . ExtractString ( exprRange . MinPos , exprRange . Length , text ) ;
if ( mExprPost ! = null )
text . Append ( mExprPost ) ;
String val = scope String ( ) ;
if ( mEvalAtAddress ! = ( int ) 0 )
IDEApp . sApp . mDebugger . EvaluateAtAddress ( text , mEvalAtAddress , val , mEditWidgetContent . CursorTextPos - 1 - exprRange . mStartPos + cursorOfs ) ;
else if ( mIsAddress )
{
gApp . mDebugger . Evaluate ( text , val , mEditWidgetContent . CursorTextPos - 1 - exprRange . mStartPos + cursorOfs , - 1 , . MemoryWatch ) ;
}
else if ( mIsSymbol )
{
gApp . mDebugger . Evaluate ( text , val , mEditWidgetContent . CursorTextPos - 1 - exprRange . mStartPos + cursorOfs , - 1 , . Symbol ) ;
}
else
gApp . DebugEvaluate ( mExpectingType , text , val , mEditWidgetContent . CursorTextPos - 1 - exprRange . mStartPos + cursorOfs ) ;
var vals = scope List < StringView > ( val . Split ( '\n' ) ) ;
if ( doAutoComplete )
{
int32 idx = ( int32 ) val . IndexOf ( ":autocomplete\n" ) ;
if ( idx ! = - 1 )
{
GetAutoComplete ( ) ;
var autoCompleteInfo = scope String ( 256 ) ;
autoCompleteInfo . Append ( val , idx + ":autocomplete\n" . Length ) ;
SetAutoCompleteInfo ( autoCompleteInfo , exprRange . mStartPos - cursorOfs ) ;
}
else if ( editWidgetContent . mAutoComplete ! = null )
editWidgetContent . mAutoComplete . Close ( ) ;
}
mErrorStart = 0 ;
mErrorEnd = 0 ;
String result = scope String ( vals [ 0 ] ) ;
if ( ( result . StartsWith ( "!" , StringComparison . Ordinal ) ) & & ( ! mIgnoreErrors ) )
{
result . Remove ( 0 , 1 ) ;
var errorVals = scope List < StringView > ( result . Split ( '\t' ) ) ;
if ( errorVals . Count > 1 )
{
mErrorStart = int32 . Parse ( scope String ( errorVals [ 0 ] ) ) . Get ( ) + exprRange . mStartPos - cursorOfs ;
mErrorEnd = mErrorStart + int32 . Parse ( scope String ( errorVals [ 1 ] ) ) . Get ( ) ;
mLastError = new String ( errorVals [ 2 ] ) ;
if ( ( mErrorEnd > 0 ) & & ( mErrorStart < text . Length ) & & ( mErrorEnd < = text . Length ) )
mLastError . Append ( ": " , scope String ( text , mErrorStart , mErrorEnd - mErrorStart ) ) ;
}
else
{
mLastError = new String ( errorVals [ 0 ] ) ;
}
}
mLastTextVersionId = mEditWidgetContent . mData . mCurTextVersionId ;
}
public override void RemovedFromParent ( Widget previousParent , WidgetWindow previousWidgetWindow )
{
base . RemovedFromParent ( previousParent , previousWidgetWindow ) ;
var editWidgetContent = ( ExpressionEditWidgetContent ) mEditWidgetContent ;
if ( editWidgetContent . mAutoComplete ! = null )
editWidgetContent . mAutoComplete . Close ( ) ;
}
public override void Update ( )
{
base . Update ( ) ;
if ( mLastTextVersionId ! = mEditWidgetContent . mData . mCurTextVersionId )
{
mLastTextVersionId = mEditWidgetContent . mData . mCurTextVersionId ;
UpdateText ( 0 , false ) ;
}
}
public override void DrawAll ( Graphics g )
{
base . DrawAll ( g ) ;
if ( Content . mIsReadOnly )
{
using ( g . PushColor ( 0x60404040 ) )
g . FillRect ( 0 , 0 , mWidth , mHeight ) ;
2022-05-18 13:23:10 -07:00
}
2019-08-23 11:56:54 -07:00
}
}
/ * class RefCounted
{
int32 mRefCount = 1 ;
public this ( )
{
//Debug.WriteLine("RefCount (this) {0} {1}", this, mRefCount);
}
public ~ this ( )
{
//Debug.WriteLine("RefCount (~this) {0} {1}", this, mRefCount);
Debug . Assert ( mRefCount = = 0 ) ;
}
public void AddRef ( )
{
mRefCount + + ;
//Debug.WriteLine("RefCount (AddRef) {0} {1}", this, mRefCount);
}
public void Release ( )
{
//Debug.WriteLine("RefCount (Release) {0} {1}", this, mRefCount - 1);
if ( - - mRefCount = = 0 )
delete this ;
}
} * /
public class WatchSeriesInfo : RefCounted
{
public String mDisplayTemplate ~ delete _ ;
public String mEvalTemplate ~ delete _ ;
public int32 mStartMemberIdx ;
2019-12-09 10:28:56 -08:00
public int mStartIdx ;
public int mCount ;
public int mCurCount ; // When counting up unsized series
2019-08-23 11:56:54 -07:00
public int32 mShowPages ;
public int32 mShowPageSize ;
public String mAddrs ~ delete _ ;
public int32 mAddrsEntrySize ;
public String mContinuationData ~ delete _ ;
public DarkButton mMoreButton ;
public DarkButton mLessButton ;
public static int32 sIdx ;
2019-10-09 16:18:11 -07:00
public int32 mSeriesVersion = + + sIdx ;
public int32 mSeriesFirstVersion = mSeriesVersion ;
2024-03-26 07:30:54 -04:00
public int32 mLastFindIdx ;
public bool mFindHadMatches ;
public HashSet < int32 > mFindFilteredIndices ~ delete _ ;
2019-08-23 11:56:54 -07:00
}
public class WatchRefreshButton : ButtonWidget
{
public override void Draw ( Graphics g )
{
base . Draw ( g ) ;
g . Draw ( DarkTheme . sDarkTheme . GetImage ( DarkTheme . ImageIdx . RefreshArrows ) ) ;
}
}
public class ActionButton : ButtonWidget
{
public override void Draw ( Graphics g )
{
base . Draw ( g ) ;
if ( mX < mParent . mWidth - GS ! ( 10 ) )
g . Draw ( DarkTheme . sDarkTheme . GetImage ( DarkTheme . ImageIdx . GotoButton ) ) ;
}
}
public class WatchStringEditWidgetContent : DarkEditWidgetContent
{
public WatchStringEdit mWatchStringEdit ;
public this ( )
{
mHiliteColor = 0xFF384858 ;
mUnfocusedHiliteColor = 0x80384858 ;
}
public override bool AllowChar ( char32 theChar )
{
return true ;
}
public override void KeyDown ( KeyCode keyCode , bool isRepeat )
{
base . KeyDown ( keyCode , isRepeat ) ;
if ( keyCode = = KeyCode . Escape )
DarkTooltipManager . CloseTooltip ( ) ;
}
2022-05-18 13:23:10 -07:00
public override void CheckLineCoords ( )
{
bool changed = ( mLineCoordTextVersionId ! = mData . mCurTextVersionId ) ;
base . CheckLineCoords ( ) ;
if ( ( changed ) & & ( ! mLineCoords . IsEmpty ) & & ( mWatchStringEdit . mMoreButton ! = null ) )
{
mLineCoords . Back + = GS ! ( 32 ) ;
var dewc = mEditWidget . mEditWidgetContent as DarkEditWidgetContent ;
dewc . mHeight = mLineCoords . Back ;
mWatchStringEdit . RehupSize ( ) ;
}
2019-08-23 11:56:54 -07:00
}
public override void CursorToEnd ( )
{
base . CursorToEnd ( ) ;
if ( mWatchStringEdit . mMoreButton ! = null )
{
mEditWidget . VertScrollTo ( mEditWidget . mVertPos . mDest + GS ! ( 32 ) ) ;
mEditWidget . HorzScrollTo ( 0 ) ;
}
}
public override uint32 GetSelectionColor ( uint8 flags )
{
bool hasFocus = mEditWidget . mHasFocus ;
if ( ( mWatchStringEdit ! = null ) & & ( mWatchStringEdit . mQuickFind ! = null ) )
hasFocus | = mWatchStringEdit . mQuickFind . mFindEditWidget . mHasFocus ;
if ( ( flags & ( uint8 ) SourceElementFlags . Find_Matches ) ! = 0 )
{
return 0x50FFE0B0 ;
}
return hasFocus ? mHiliteColor : mUnfocusedHiliteColor ;
}
public override void DrawSectionFlagsOver ( Graphics g , float x , float y , float width , uint8 flags )
{
if ( ( flags & ( uint8 ) SourceElementFlags . Find_Matches ) ! = 0 )
{
using ( g . PushColor ( 0x34FFE0B0 ) )
g . FillRect ( x , y , width , mFont . GetLineSpacing ( ) ) ;
DrawSectionFlagsOver ( g , x , y , width , ( uint8 ) ( flags & ~ ( uint8 ) SourceElementFlags . Find_Matches ) ) ;
return ;
}
}
2022-05-18 13:23:10 -07:00
public override void MouseClicked ( float x , float y , float origX , float origY , int32 btn )
{
base . MouseClicked ( x , y , origX , origY , btn ) ;
if ( btn = = 1 )
{
SelfToOtherTranslate ( mWatchStringEdit , x , y , var transX , var transY ) ;
mWatchStringEdit . [ Friend ] ShowMenu ( transX , transY ) ;
}
}
2019-08-23 11:56:54 -07:00
}
public class WatchStringEditWidget : DarkEditWidget
{
public this ( WatchStringEditWidgetContent content ) : base ( content )
{
}
public override void DrawAll ( Graphics g )
{
using ( g . PushColor ( 0xD0FFFFFF ) )
base . DrawAll ( g ) ;
}
}
public class WatchStringEdit : Widget
{
public const int cWordWrapMax = 512 * 1024 ;
public const int cMoreBlockSize = 1024 * 1024 ;
public WatchStringEditWidget mEditWidget ;
public String mEvalString = new String ( ) ~ delete _ ;
public String mOrigContent ~ delete _ ;
public int mMaxShowSize = cMoreBlockSize ;
public DarkButton mMoreButton ;
public QuickFind mQuickFind ;
2020-03-02 06:24:21 -08:00
public DarkTabbedView . DarkTabMenuButton mMenuButton ;
public bool mViewWhiteSpace ;
2022-05-18 13:23:10 -07:00
public bool mIsEmbedded ;
public bool mShowStatusBar ;
2019-08-23 11:56:54 -07:00
2022-05-18 13:23:10 -07:00
public this ( String text , String evalStr , bool isEmbedded = false )
2019-08-23 11:56:54 -07:00
{
scope AutoBeefPerf ( "WatchStringEdit.this" ) ;
2022-05-18 13:23:10 -07:00
mIsEmbedded = isEmbedded ;
mShowStatusBar = ! mIsEmbedded ;
2019-08-23 11:56:54 -07:00
let editWidgetContent = new WatchStringEditWidgetContent ( ) ;
editWidgetContent . mWatchStringEdit = this ;
mEditWidget = new WatchStringEditWidget ( editWidgetContent ) ;
mEditWidget . Content . mIsMultiline = true ;
mEditWidget . Content . mIsReadOnly = true ;
mEditWidget . Content . mWordWrap = text . Length < cWordWrapMax ;
mEditWidget . Content . mAllowMaximalScroll = false ;
2022-05-18 13:23:10 -07:00
if ( mIsEmbedded )
mEditWidget . InitScrollbars ( false , true ) ;
2019-08-23 11:56:54 -07:00
bool needsStrCleaning = false ;
for ( let c in text . RawChars )
if ( c < = ' \ x02 ' )
needsStrCleaning = true ;
if ( needsStrCleaning )
{
mOrigContent = new String ( text ) ;
String cleanedStr = scope String ( ) . . Append ( text ) ;
for ( let c in cleanedStr . RawChars )
{
if ( c < = ' \ x02 ' )
@c . Current = ' \ x03 ' ;
}
mEditWidget . SetText ( cleanedStr ) ;
}
else
mEditWidget . SetText ( text ) ;
AddWidget ( mEditWidget ) ;
if ( text . Length > = mMaxShowSize )
{
ShowMoreButton ( ) ;
}
if ( evalStr ! = null )
mEvalString . Set ( evalStr ) ;
2020-03-02 06:24:21 -08:00
2022-05-18 13:23:10 -07:00
if ( ! mIsEmbedded )
{
mMenuButton = new DarkTabbedView . DarkTabMenuButton ( ) ;
AddWidget ( mMenuButton ) ;
2020-03-02 06:24:21 -08:00
2022-05-18 13:23:10 -07:00
mMenuButton . mOnMouseDown . Add ( new ( evt ) = >
{
float x = mMenuButton . mX + GS ! ( 14 ) ;
float y = mMenuButton . mY + GS ! ( 6 ) ;
ShowMenu ( x , y ) ;
//menuWidget.mWidgetWindow.mOnWindowClosed.Add(new => MenuClosed);
} ) ;
}
}
void ShowMenu ( float x , float y )
{
Menu menu = new Menu ( ) ;
var menuItem = menu . AddItem ( "Show Whitespace" ) ;
if ( mViewWhiteSpace )
menuItem . mIconImage = DarkTheme . sDarkTheme . GetImage ( . Check ) ;
menuItem . mOnMenuItemSelected . Add ( new ( menu ) = >
2020-03-02 06:24:21 -08:00
{
2022-05-18 13:23:10 -07:00
mViewWhiteSpace = ! mViewWhiteSpace ;
var darkEditWidgetContent = ( DarkEditWidgetContent ) mEditWidget . Content ;
darkEditWidgetContent . mViewWhiteSpaceColor = mViewWhiteSpace ? SourceEditWidgetContent . sTextColors [ ( int ) SourceElementType . VisibleWhiteSpace ] : 0 ;
} ) ;
2020-03-02 06:24:21 -08:00
2022-05-18 13:23:10 -07:00
if ( mIsEmbedded )
{
menuItem = menu . AddItem ( "Show Status Bar" ) ;
if ( mShowStatusBar )
menuItem . mIconImage = DarkTheme . sDarkTheme . GetImage ( . Check ) ;
menuItem . mOnMenuItemSelected . Add ( new ( menu ) = >
{
mShowStatusBar = ! mShowStatusBar ;
MarkDirty ( ) ;
RehupSize ( ) ;
} ) ;
}
2020-03-02 06:24:21 -08:00
2022-05-18 13:23:10 -07:00
MenuWidget menuWidget = DarkTheme . sDarkTheme . CreateMenuWidget ( menu ) ;
menuWidget . Init ( this , x , y , . AllowScrollable ) ;
menu . mOnMenuClosed . Add ( new ( menu , itemSelected ) = >
{
if ( DarkTooltipManager . sTooltip ! = null )
DarkTooltipManager . sTooltip . mAutoCloseDelay = 90 ;
2020-03-02 06:24:21 -08:00
} ) ;
2022-05-18 13:23:10 -07:00
}
public void UpdateString ( String str )
{
var dewc = ( DarkEditWidgetContent ) mEditWidget . mEditWidgetContent ;
String oldText = scope . ( ) ;
mEditWidget . GetText ( oldText ) ;
if ( oldText = = str )
{
dewc . mFont = DarkTheme . sDarkTheme . mSmallFont ;
return ;
}
bool scrollbarAtBottom = ( mEditWidget . mVertPos . mDest > 0 ) & & ( mEditWidget . mVertPos . mDest > = ( mEditWidget . mVertScrollbar . mContentSize - mEditWidget . mVertScrollbar . mPageSize - 0.1f ) ) ;
mEditWidget . SetText ( str ) ;
if ( scrollbarAtBottom )
mEditWidget . VertScrollTo ( mEditWidget . mVertScrollbar . mContentSize - mEditWidget . mVertScrollbar . mPageSize ) ;
dewc . mFont = DarkTheme . sDarkTheme . mSmallBoldFont ;
}
2019-08-23 11:56:54 -07:00
public void ShowQuickFind ( bool isReplace )
{
if ( mQuickFind ! = null )
{
mQuickFind . Close ( ) ;
delete mQuickFind ;
}
mQuickFind = new QuickFind ( this , mEditWidget , isReplace ) ;
mWidgetWindow . SetFocus ( mQuickFind . mFindEditWidget ) ;
RehupSize ( ) ;
}
public void FindNext ( int32 dir )
{
if ( mQuickFind = = null )
return ;
mQuickFind . FindNext ( dir , false ) ;
}
void ShowMore ( )
{
mMoreButton . RemoveSelf ( ) ;
gApp . DeferDelete ( mMoreButton ) ;
mMoreButton = null ;
mMaxShowSize * = 2 ;
String str = scope String ( ) ;
String evalStr = scope : : String ( ) ;
evalStr . AppendF ( "{0}, rawStr, maxcount={1}" , mEvalString , mMaxShowSize ) ;
// We purposely don't add mResultTypeStr here because the parse fails on std::basic_string and we know this will never be needed for an short enum name anyway
gApp . DebugEvaluate ( null , evalStr , str ) ;
mEditWidget . SetText ( str ) ;
if ( str . Length > = mMaxShowSize )
{
ShowMoreButton ( ) ;
mEditWidget . Content . RecalcSize ( ) ;
}
}
void ShowMoreButton ( )
{
let editWidgetContent = ( WatchStringEditWidgetContent ) mEditWidget . Content ;
var contentHeight = mEditWidget . Content . GetLineCount ( ) * editWidgetContent . mFont . GetLineSpacing ( ) ;
mMoreButton = ( DarkButton ) DarkTheme . sDarkTheme . CreateButton ( editWidgetContent , "More" , mX + GS ! ( 4 ) , contentHeight + GS ! ( 4 ) , GS ! ( 68 ) , GS ! ( 20 ) ) ;
mMoreButton . mOnMouseClick . Add ( new ( evt ) = >
{
ShowMore ( ) ;
} ) ;
2022-05-18 13:23:10 -07:00
var dewc = mEditWidget . mEditWidgetContent as DarkEditWidgetContent ;
if ( ! dewc . mLineCoords . IsEmpty )
{
dewc . mLineCoords . Back + = GS ! ( 32 ) ;
dewc . mHeight + = GS ! ( 32 ) ;
}
2019-08-23 11:56:54 -07:00
}
2022-05-24 07:56:31 -07:00
void DoDrawAll ( Graphics g )
2019-08-23 11:56:54 -07:00
{
g . SetFont ( DarkTheme . sDarkTheme . mSmallFont ) ;
var editWidgetContent = mEditWidget . Content ;
int cursorTextPos = mEditWidget . Content . CursorTextPos ;
int line ;
int lineChar ;
mEditWidget . Content . GetLineCharAtIdx ( mEditWidget . Content . CursorTextPos , out line , out lineChar ) ;
var textY = mHeight - GS ! ( 16 ) ;
String textPosString = scope String ( ) ;
if ( mEditWidget . Content . HasSelection ( ) )
{
var selection = mEditWidget . Content . mSelection ;
textPosString . AppendF ( "Start {0} Len {1}" , selection . Value . MinPos , selection . Value . MaxPos - selection . Value . MinPos ) ;
}
else
{
textPosString . AppendF ( "Index {0}" , cursorTextPos ) ;
}
int lineStart ;
int lineEnd ;
editWidgetContent . GetLinePosition ( line , out lineStart , out lineEnd ) ;
int col = 0 ;
int checkTextPos = lineStart ;
while ( checkTextPos < cursorTextPos )
{
let c32 = editWidgetContent . mData . GetChar32 ( ref checkTextPos ) ;
if ( ! c32 . IsCombiningMark )
col + + ;
}
String charStr = null ;
checkTextPos = cursorTextPos ;
while ( true )
{
bool isFirst = checkTextPos = = cursorTextPos ;
char32 c32 ;
int encodeLen ;
if ( mOrigContent ! = null )
{
if ( checkTextPos > = mOrigContent . Length )
break ;
( c32 , encodeLen ) = mOrigContent . GetChar32 ( checkTextPos ) ;
}
else
{
if ( checkTextPos > = editWidgetContent . mData . mTextLength )
break ;
( c32 , encodeLen ) = editWidgetContent . GetChar32 ( checkTextPos ) ;
}
if ( ( c32 = = 0 ) | | ( ( ! c32 . IsCombiningMark ) & & ( ! isFirst ) ) )
break ;
if ( charStr = = null )
charStr = scope : : String ( " " ) ;
if ( encodeLen > 1 )
{
charStr . AppendF ( "\\u{{{0:X}}} " , ( int64 ) c32 ) ;
}
for ( int ofs < encodeLen )
{
if ( mOrigContent ! = null )
charStr . AppendF ( "\\x{0:X2}" , ( uint8 ) mOrigContent [ checkTextPos + ofs ] ) ;
else
charStr . AppendF ( "\\x{0:X2}" , ( int64 ) editWidgetContent . mData . mText [ checkTextPos + ofs ] . mChar ) ;
}
checkTextPos + = encodeLen ;
}
if ( charStr ! = null )
{
textPosString . Append ( charStr ) ;
}
2022-05-18 13:23:10 -07:00
if ( mShowStatusBar )
{
g . DrawString ( textPosString , 16 , textY , . Left , mWidth - GS ! ( 140 ) , . Ellipsis ) ;
2024-12-31 14:15:12 -08:00
g . DrawString ( scope String ( ) . . AppendF ( "Ln {0}" , line + 1 ) , mWidth - GS ! ( 130 ) , textY ) ;
g . DrawString ( scope String ( ) . . AppendF ( "Col {0}" , col + 1 ) , mWidth - GS ! ( 70 ) , textY ) ;
2022-05-18 13:23:10 -07:00
}
2019-08-23 11:56:54 -07:00
//using (g.PushColor(0xD0FFFFFF))
base . DrawAll ( g ) ;
}
2022-05-24 07:56:31 -07:00
public override void DrawAll ( Graphics g )
{
uint32 color = Color . White ;
if ( var lvItem = mParent as WatchListViewItem )
{
var headItem = lvItem . GetSubItem ( 0 ) as WatchListViewItem ;
if ( ( headItem . mDisabled ) | | ( lvItem . mFailed ) )
2022-05-24 08:39:57 -07:00
color = 0x80FFFFFF ;
2022-05-24 07:56:31 -07:00
}
using ( g . PushColor ( color ) )
DoDrawAll ( g ) ;
}
2019-08-23 11:56:54 -07:00
public override void Resize ( float x , float y , float width , float height )
{
base . Resize ( x , y , width , height ) ;
2022-05-18 13:23:10 -07:00
mEditWidget . Resize ( 0 , 0 , width , height - ( mShowStatusBar ? GS ! ( 16 ) : GS ! ( 0 ) ) ) ;
2019-08-23 11:56:54 -07:00
if ( mQuickFind ! = null )
mQuickFind . ResizeSelf ( ) ;
2020-03-02 06:24:21 -08:00
2022-05-18 13:23:10 -07:00
if ( mIsEmbedded )
mMenuButton ? . Resize ( width + GS ! ( - 4 ) , height - GS ! ( 18 ) , GS ! ( 16 ) , GS ! ( 16 ) ) ;
else
mMenuButton ? . Resize ( width - GS ! ( 26 ) , height - GS ! ( 12 ) , GS ! ( 16 ) , GS ! ( 16 ) ) ;
var dewc = mEditWidget . mEditWidgetContent as DarkEditWidgetContent ;
mMoreButton ? . Resize ( GS ! ( 4 ) , dewc . mHeight - GS ! ( 24 ) , GS ! ( 68 ) , GS ! ( 20 ) ) ;
2019-08-23 11:56:54 -07:00
}
public float GetWantHeight ( float wantWidth )
{
mEditWidget . Resize ( 0 , 0 , wantWidth , mEditWidget . mHeight ) ;
mEditWidget . Content . RecalcSize ( ) ;
return mEditWidget . mScrollContent . mHeight + mEditWidget . mScrollContentInsets . mTop + mEditWidget . mScrollContentInsets . mBottom + GS ! ( 20 ) ;
}
public bool Close ( )
{
if ( mQuickFind ! = null )
{
mQuickFind . Close ( ) ;
DeleteAndNullify ! ( mQuickFind ) ;
return false ;
}
return true ;
}
2019-09-10 11:26:14 -07:00
protected override void RemovedFromWindow ( )
{
base . RemovedFromWindow ( ) ;
}
2019-08-23 11:56:54 -07:00
}
2022-05-18 13:23:10 -07:00
public class ResizeHandleWidget : Widget
{
public float mDownX ;
public float mDownY ;
public override void Draw ( Graphics g )
{
g . Draw ( DarkTheme . sDarkTheme . GetImage ( . ResizeGrabber ) , 0 , 0 ) ;
}
public override void MouseEnter ( )
{
base . MouseEnter ( ) ;
gApp . SetCursor ( . SizeNWSE ) ;
}
public override void MouseLeave ( )
{
base . MouseLeave ( ) ;
if ( ! mMouseDown )
gApp . SetCursor ( . Pointer ) ;
}
public override void RehupScale ( float oldScale , float newScale )
{
base . RehupScale ( oldScale , newScale ) ;
mWidth = GS ! ( 20 ) ;
mHeight = GS ! ( 20 ) ;
}
public override void MouseDown ( float x , float y , int32 btn , int32 btnCount )
{
base . MouseDown ( x , y , btn , btnCount ) ;
mDownX = x ;
mDownY = y ;
}
public override void MouseMove ( float x , float y )
{
base . MouseMove ( x , y ) ;
if ( mMouseDown )
{
var listViewItem = mParent as WatchListViewItem ;
SelfToOtherTranslate ( listViewItem . mListView , x , y , var lvX , var lvY ) ;
listViewItem . mListView . mColumns [ 1 ] . mWidth = Math . Max ( GS ! ( 40 ) , lvX - mDownX - listViewItem . mListView . mColumns [ 0 ] . mWidth + GS ! ( 4 ) ) ;
listViewItem . mListView . mListSizeDirty = true ;
var rootItem = listViewItem . GetSubItem ( 0 ) as WatchListViewItem ;
rootItem . mSelfHeight = Math . Max ( GS ! ( 40 ) , mY + y - mDownY + GS ! ( 20 ) ) ;
}
}
public override void MouseUp ( float x , float y , int32 btn )
{
base . MouseUp ( x , y , btn ) ;
if ( ! mMouseOver )
gApp . SetCursor ( . Pointer ) ;
}
}
2019-08-23 11:56:54 -07:00
public class WatchListViewItem : IDEListViewItem
{
2024-03-25 06:18:50 -04:00
public int32 mId ;
2019-11-07 06:53:32 -08:00
public IWatchOwner mWatchOwner ;
2019-08-23 11:56:54 -07:00
public WatchEntry mWatchEntry ~ delete _ ;
public bool mFailed ;
public int32 mErrorStart ;
public int32 mErrorEnd ;
public WatchSeriesInfo mWatchSeriesInfo ;
public int32 mSeriesMemberIdx ;
public WatchListViewItem mPrevPlaceholder ;
public int32 mPlaceholderStartIdx ;
public bool mIsPlaceholder ;
public bool mDisabled = false ;
public bool mAllowRefresh = false ;
2024-03-25 06:18:50 -04:00
public bool mValueChanged = false ;
public int mLastFindIdx ;
public bool mFindMismatch ;
public bool mChildHasMatch ;
public String mColoredLabel ~ delete _ ;
2025-01-18 10:05:56 -08:00
public bool mWantRemoveSelf ;
public bool mFreezeHeight ;
2019-08-23 11:56:54 -07:00
public WatchRefreshButton mWatchRefreshButton ;
public ActionButton mActionButton ;
public String mTextAction ~ delete _ ;
2019-11-07 06:53:32 -08:00
public bool mMustUpdateBeforeEvaluate ;
2022-05-18 13:23:10 -07:00
public Widget mCustomContentWidget ;
2019-08-23 11:56:54 -07:00
public override bool Selected
{
get
{
return base . Selected ;
}
set
{
2019-09-28 12:15:36 -07:00
/ * if ( value )
mParent . UpdateAll ( ) ; * /
2019-08-23 11:56:54 -07:00
base . Selected = value ;
}
}
public bool Failed
{
get
{
return ( ( WatchListViewItem ) GetSubItem ( 1 ) ) . mFailed ;
}
}
public this ( IWatchOwner watchOwner , IDEListView listView )
{
2024-03-25 06:18:50 -04:00
mId = + + listView . mCurId ;
2019-08-23 11:56:54 -07:00
mWatchOwner = watchOwner ;
}
public ~ this ( )
{
if ( mWatchSeriesInfo ! = null )
2019-10-01 12:46:38 -07:00
{
2019-08-23 11:56:54 -07:00
mWatchSeriesInfo . ReleaseRef ( ) ;
}
2022-05-18 13:23:10 -07:00
if ( mCustomContentWidget ! = null )
{
mCustomContentWidget . RemoveSelf ( ) ;
delete mCustomContentWidget ;
}
2019-08-23 11:56:54 -07:00
}
public virtual WatchListViewItem GetWatchListViewItemParent ( )
{
return mParentItem as WatchListViewItem ;
}
protected bool WatchIsString ( )
{
var mainWatchListViewItem = ( WatchListViewItem ) GetSubItem ( 0 ) ;
if ( ( mainWatchListViewItem . mWatchEntry . mResultType = = WatchResultType . TypeClass ) | | ( mainWatchListViewItem . mWatchEntry . mResultType = = WatchResultType . TypeValueType ) )
return false ;
String resultTypeStr = mainWatchListViewItem . mWatchEntry . mResultTypeStr ;
return ( resultTypeStr = = "System.String" ) | |
( resultTypeStr = = "std::string" ) | |
( resultTypeStr = = "char8*" ) | |
( resultTypeStr = = "const char8*" ) ;
}
public override bool WantsTooltip ( float mouseX , float mouseY )
{
if ( mColumnIdx = = 1 )
{
//if (WatchIsString())
return true ;
}
return base . WantsTooltip ( mouseX , mouseY ) ;
}
public override void ShowTooltip ( float mouseX , float mouseY )
{
scope AutoBeefPerf ( "WatchPanel.ShowTooltip" ) ;
if ( mColumnIdx ! = 1 )
{
base . ShowTooltip ( mouseX , mouseY ) ;
return ;
}
var mainWatchListViewItem = ( WatchListViewItem ) GetSubItem ( 0 ) ;
String evalStr = null ;
String str = scope String ( ) ;
if ( mColumnIdx = = 1 )
{
evalStr = scope : : String ( ) ;
evalStr . AppendF ( "{0}, rawStr, maxcount={1}" , mainWatchListViewItem . mWatchEntry . mEvalStr , WatchStringEdit . cMoreBlockSize ) ;
// We purposely don't add mResultTypeStr here because the parse fails on std::basic_string and we know this will never be needed for an short enum name anyway
gApp . DebugEvaluate ( null , evalStr , str ) ;
if ( ( str . Length = = 0 ) | | ( str . StartsWith ( "!" ) ) )
{
if ( ! base . WantsTooltip ( mouseX , mouseY ) )
return ;
}
}
if ( str . Length > 0 )
{
if ( DarkTooltipManager . IsTooltipShown ( this ) )
return ;
//Profiler.StartSampling();
float x = 8 ;
if ( mColumnIdx = = 0 )
x = LabelX + GS ! ( 8 ) ;
//string str = "This is a really long string, I want to see if we can do a scrollable mouseover view of this string. We can even see if we can\nembed\r\nsome lines...";
//str = "Hey\nDef\nEfg\nzzap";
if ( str . Length = = 0 )
return ;
float parentX ;
float parentY ;
SelfToOtherTranslate ( mListView . mScrollContentContainer , x , 0 , out parentX , out parentY ) ;
float wantWidth = Math . Max ( GS ! ( 320 ) , mListView . mScrollContentContainer . mWidth - parentX - GS ! ( 8 ) ) ;
var watchStringEdit = new WatchStringEdit ( str , evalStr ) ;
let ewc = watchStringEdit . mEditWidget . Content ;
float wantHeight = watchStringEdit . GetWantHeight ( wantWidth - GS ! ( 6 ) * 2 ) ;
float maxHeight = GS ! ( 78 ) ;
if ( ! ewc . mWordWrap )
maxHeight + = GS ! ( 20 ) ;
if ( wantHeight > maxHeight + 0.5f )
{
watchStringEdit . mEditWidget . InitScrollbars ( ! ewc . mWordWrap , true ) ;
wantHeight = maxHeight ;
}
wantHeight + = GS ! ( 6 ) * 2 ;
var tooltip = DarkTooltipManager . ShowTooltip ( "" , this , x , mSelfHeight + mBottomPadding , wantWidth , wantHeight , true , true ) ;
if ( tooltip ! = null )
{
tooltip . mRelWidgetMouseInsets = new Insets ( 0 , 0 , GS ! ( - 8 ) , 0 ) ;
2024-12-29 09:00:06 -08:00
tooltip . mAllowMouseInsideInsets = new . ( GS ! ( - 12 ) , GS ! ( - 12 ) , GS ! ( - 4 ) , GS ! ( - 4 ) ) ;
2019-08-23 11:56:54 -07:00
tooltip . AddWidget ( watchStringEdit ) ;
tooltip . mOnResized . Add ( new ( widget ) = > watchStringEdit . Resize ( GS ! ( 6 ) , GS ! ( 6 ) , widget . mWidth - GS ! ( 6 ) * 2 , widget . mHeight - GS ! ( 6 ) * 2 ) ) ;
tooltip . mOnResized ( tooltip ) ;
tooltip . mWidgetWindow . mOnWindowKeyDown . Add ( new = > gApp . [ Friend ] SysKeyDown ) ;
tooltip . mOnKeyDown . Add ( new ( evt ) = >
{
if ( ( evt . mKeyCode = = . Escape ) & & ( ! watchStringEdit . Close ( ) ) )
evt . mHandled = true ;
} ) ;
}
//Profiler.StopSampling();
return ;
}
base . ShowTooltip ( mouseX , mouseY ) ;
}
public void AddRefreshButton ( )
{
2020-06-15 09:01:49 -07:00
int columnIdx = 2 ;
if ( ( mWatchRefreshButton = = null ) & & ( mColumnIdx = = 0 ) & & ( columnIdx < mSubItems . Count ) )
2019-08-23 11:56:54 -07:00
{
mWatchRefreshButton = new WatchRefreshButton ( ) ;
2020-06-15 09:01:49 -07:00
mWatchRefreshButton . Resize ( GS ! ( - 16 ) , 0 , GS ! ( 20 ) , GS ! ( 20 ) ) ;
2024-12-31 13:17:53 -08:00
mWatchRefreshButton . mOnMouseDown . Add ( new ( evt ) = >
{
if ( evt . mBtn = = 0 )
RefreshWatch ( ) ;
if ( evt . mBtn = = 1 )
{
Menu menu = new Menu ( ) ;
Menu anItem ;
anItem = menu . AddItem ( "Refresh" ) ;
anItem . mOnMenuItemSelected . Add ( new ( item ) = > { RefreshWatch ( ) ; } ) ;
anItem = menu . AddItem ( "Auto Refresh" ) ;
if ( mWatchEntry . AutoRefresh )
anItem . mIconImage = DarkTheme . sDarkTheme . GetImage ( . Check ) ;
anItem . mOnMenuItemSelected . Add ( new ( item ) = >
{
mWatchEntry . AutoRefresh = ! mWatchEntry . AutoRefresh ;
if ( mWatchEntry . AutoRefresh )
RefreshWatch ( ) ;
} ) ;
MenuWidget menuWidget = ThemeFactory . mDefault . CreateMenuWidget ( menu ) ;
menuWidget . Init ( mWatchRefreshButton , evt . mX , mHeight + GS ! ( 2 ) ) ;
}
} ) ;
2020-06-15 09:01:49 -07:00
var typeSubItem = GetSubItem ( columnIdx ) ;
2019-08-23 11:56:54 -07:00
typeSubItem . AddWidget ( mWatchRefreshButton ) ;
mListView . mListSizeDirty = true ;
}
}
public void AddActionButton ( )
{
if ( ( mActionButton = = null ) & & ( mColumnIdx = = 0 ) )
{
if ( mWatchEntry . mAction = = "ShowCodeAddr 0x'00000000" )
return ;
if ( mWatchEntry . mAction = = "ShowCodeAddr 0x00000000" )
return ;
mActionButton = new ActionButton ( ) ;
//var darkListView = (DarkListView)mListView;
mActionButton . mOnMouseDown . Add ( new ( evt ) = >
{
gApp . PerformAction ( mWatchEntry . mAction ) ;
} ) ;
var typeSubItem = ( WatchListViewItem ) GetSubItem ( 1 ) ;
typeSubItem . AddWidget ( mActionButton ) ;
mActionButton . Resize ( typeSubItem . Font . GetWidth ( typeSubItem . mLabel ) + 8 , 0 , 20 , 20 ) ;
mListView . mListSizeDirty = true ;
}
}
public override void RehupScale ( float oldScale , float newScale )
{
base . RehupScale ( oldScale , newScale ) ;
if ( mActionButton ! = null )
{
//var darkListView = (DarkListView)mListView;
var typeSubItem = ( WatchListViewItem ) GetSubItem ( 1 ) ;
mActionButton . Resize ( typeSubItem . Font . GetWidth ( typeSubItem . mLabel ) + 8 , 0 , 20 , 20 ) ;
}
2022-05-18 13:23:10 -07:00
if ( mColumnIdx = = 0 )
{
var dataItem = ( WatchListViewItem ) GetSubItem ( 1 ) ;
if ( dataItem . mCustomContentWidget ! = null )
mSelfHeight = dataItem . mCustomContentWidget . mHeight ;
}
2019-08-23 11:56:54 -07:00
}
public void SetDisabled ( bool disabled , bool allowRefresh )
{
if ( ( mDisabled = = disabled ) & & ( mAllowRefresh = = allowRefresh ) )
return ;
mDisabled = disabled ;
mAllowRefresh = allowRefresh ;
if ( ( mDisabled ) & & ( allowRefresh ) )
{
2024-12-31 13:17:53 -08:00
AddRefreshButton ( ) ;
2019-08-23 11:56:54 -07:00
}
else if ( mWatchRefreshButton ! = null )
{
Widget . RemoveAndDelete ( mWatchRefreshButton ) ;
mWatchRefreshButton = null ;
}
if ( mOpenButton ! = null )
mOpenButton . mAllowOpen = ( ! disabled ) | | ( mOpenButton . mIsOpen ) ;
if ( mChildItems ! = null )
{
for ( WatchListViewItem childItem in mChildItems )
childItem . SetDisabled ( disabled , allowRefresh ) ;
}
}
public override float ResizeComponents ( float xOffset )
{
float retVal = base . ResizeComponents ( xOffset ) ;
if ( ( mColumnIdx = = 1 ) & & ( ( ( WatchListViewItem ) GetSubItem ( 0 ) ) . mWatchRefreshButton ! = null ) )
mTextAreaLengthOffset = - 16 ;
else
mTextAreaLengthOffset = 0 ;
2022-05-18 13:23:10 -07:00
if ( mCustomContentWidget ! = null )
{
if ( mColumnIdx = = 1 )
mCustomContentWidget . Resize ( 0 , 0 , mWidth , mHeight ) ;
else
mCustomContentWidget . Resize ( - GS ! ( 6 ) , mHeight - mCustomContentWidget . mHeight , mCustomContentWidget . mWidth , mCustomContentWidget . mHeight ) ;
}
2019-08-23 11:56:54 -07:00
return retVal ;
}
2024-12-31 13:17:53 -08:00
public void RefreshWatch ( )
2019-08-23 11:56:54 -07:00
{
var parentWatchListViewItem = mParentItem as WatchListViewItem ;
if ( parentWatchListViewItem ! = null )
{
parentWatchListViewItem . RefreshWatch ( ) ;
return ;
}
mWatchEntry . mIsNewExpression = true ;
mWatchOwner . UpdateWatch ( this ) ;
}
2024-03-25 06:18:50 -04:00
void CheckValue ( )
{
if ( ( mWatchEntry ! = null ) & & ( ! mWatchEntry . mHasValue ) )
{
var parentWatchListViewItem = mParentItem as WatchListViewItem ;
if ( ( ! mDisabled ) | | ( parentWatchListViewItem = = null ) | | ( mWatchEntry . mIsNewExpression ) )
{
mWatchOwner . UpdateWatch ( this ) ;
}
else if ( mColumnIdx = = 0 )
{
var valSubItem = GetSubItem ( 1 ) ;
if ( valSubItem . Label = = "" )
valSubItem . Label = "???" ;
}
}
}
2019-08-23 11:56:54 -07:00
public override void DrawAll ( Graphics g )
{
if ( mParentItem . mChildAreaHeight = = 0 )
return ;
2019-11-07 06:53:32 -08:00
if ( mMustUpdateBeforeEvaluate )
{
Update ( ) ;
}
2019-08-23 11:56:54 -07:00
if ( ! IsVisible ( g ) )
return ;
if ( ( mWatchEntry ! = null ) & & ( ! mWatchEntry . mHasValue ) )
{
if ( mParentItem . mChildAreaHeight > 0 )
{
2024-03-25 06:18:50 -04:00
CheckValue ( ) ;
2019-08-23 11:56:54 -07:00
}
}
2022-05-21 11:58:01 -07:00
if ( mColumnIdx = = 1 )
{
var headItem = GetSubItem ( 0 ) as WatchListViewItem ;
if ( headItem . mWatchEntry ? . mStackFrameId ! = null )
{
float drawX = mWidth - GS ! ( 16 ) ;
if ( headItem . mWatchRefreshButton ! = null )
drawX - = GS ! ( 16 ) ;
uint32 color = Color . White ;
if ( headItem . mDisabled )
color = 0x80FFFFFF ;
else if ( mFailed )
color = 0xFFFF4040 ;
else if ( headItem . mWatchEntry . mUsedLock )
color = 0xFFE39C39 ;
using ( g . PushColor ( color ) )
g . Draw ( DarkTheme . sDarkTheme . GetImage ( . LockIcon ) , drawX , GS ! ( - 1 ) ) ;
}
}
2019-08-23 11:56:54 -07:00
base . DrawAll ( g ) ;
}
public bool IsBold
{
get
{
var headItem = ( WatchListViewItem ) GetSubItem ( 0 ) ;
return ( mValueChanged ) & & ( ! headItem . mDisabled ) & & ( ! mFailed ) ;
}
}
public Font Font
{
get
{
return IsBold ? DarkTheme . sDarkTheme . mSmallBoldFont : DarkTheme . sDarkTheme . mSmallFont ;
}
}
2024-03-26 07:30:54 -04:00
public void CheckFindString ( )
2024-03-25 06:18:50 -04:00
{
var watchListView = ( WatchListView ) mListView ;
if ( mLastFindIdx = = watchListView . mFindIdx )
return ;
if ( watchListView . mFindString ! = null )
{
CheckValue ( ) ;
}
2024-03-26 07:30:54 -04:00
bool isEligible = true ;
if ( watchListView . mFindSelection ! = null )
{
isEligible = false ;
ListViewItem checkItem = this ;
while ( checkItem ! = watchListView . [ Friend ] mRoot )
{
var watchListViewItem = ( WatchListViewItem ) checkItem ;
if ( watchListView . mFindSelection . Contains ( watchListViewItem . mId ) )
{
isEligible = true ;
break ;
}
checkItem = checkItem . mParentItem ;
}
}
2024-03-25 06:18:50 -04:00
bool findMismatch = true ;
2024-03-26 07:30:54 -04:00
2024-03-25 06:18:50 -04:00
if ( mColumnIdx = = 0 )
{
for ( var subItem in mSubItems )
{
if ( subItem = = this )
continue ;
var watchSubItem = ( WatchListViewItem ) subItem ;
watchSubItem . CheckFindString ( ) ;
if ( ! watchSubItem . mFindMismatch )
findMismatch = false ;
}
}
2024-03-26 07:30:54 -04:00
if ( ( watchListView . mFindString ! = null ) | | ( ! isEligible ) )
2024-03-25 06:18:50 -04:00
{
if ( mColoredLabel = = null )
mColoredLabel = new String ( mLabel . Length ) ;
else
mColoredLabel . Clear ( ) ;
var findStr = watchListView . mFindString ;
uint32 disableColor = 0xFF808080 ;
uint32 enableColor = 0xFFF0F0FF ;
int checkIdx = 0 ;
while ( true )
{
2024-03-26 07:30:54 -04:00
int foundIdx = - 1 ;
if ( isEligible )
foundIdx = mLabel . IndexOf ( findStr , checkIdx , true ) ;
2024-03-25 06:18:50 -04:00
if ( foundIdx = = - 1 )
{
gfx . Font . StrEncodeColor ( disableColor , mColoredLabel ) ;
mColoredLabel . Append ( mLabel , checkIdx ) ;
break ;
}
gfx . Font . StrEncodeColor ( disableColor , mColoredLabel ) ;
mColoredLabel . Append ( mLabel , checkIdx , foundIdx - checkIdx ) ;
gfx . Font . StrEncodeColor ( enableColor , mColoredLabel ) ;
mColoredLabel . Append ( mLabel , foundIdx , findStr . Length ) ;
checkIdx = foundIdx + findStr . Length ;
}
if ( checkIdx ! = 0 )
findMismatch = false ;
}
else
{
findMismatch = false ;
DeleteAndNullify ! ( mColoredLabel ) ;
}
if ( findMismatch ! = mFindMismatch )
{
mFindMismatch = findMismatch ;
watchListView . mListSizeDirty = true ;
}
mLastFindIdx = watchListView . mFindIdx ;
}
2024-03-26 07:30:54 -04:00
public override void DrawSelect ( Graphics g )
{
var watchListView = ( WatchListView ) mListView ;
var watchPanel = watchListView . mParent as WatchPanel ;
using ( g . PushColor ( ( watchPanel ? . HasFocus ! = false ) ? 0xFFFFFFFF : 0x80FFFFFF ) )
base . DrawSelect ( g ) ;
}
2019-08-23 11:56:54 -07:00
public override void Draw ( Graphics g )
{
2024-03-25 06:18:50 -04:00
var watchListView = ( WatchListView ) mListView ;
uint32 color = Color . White ;
2019-08-23 11:56:54 -07:00
var headItem = ( WatchListViewItem ) GetSubItem ( 0 ) ;
var valueItem = ( WatchListViewItem ) GetSubItem ( 1 ) ;
2024-03-25 06:18:50 -04:00
CheckFindString ( ) ;
2024-03-26 07:30:54 -04:00
if ( ( watchListView . mFindSelection ! = null ) & & ( watchListView . mFindSelection . Contains ( mId ) & & ( ! Selected ) & & ( ! mMouseDown ) ) )
{
mFocusColor = gApp . mSettings . mUISettings . mColors . mWorkspaceDisabledText ;
mSelectColor = gApp . mSettings . mUISettings . mColors . mWorkspaceDisabledText ;
using ( g . PushColor ( 0x80FFFFFF ) )
base . DrawSelect ( g ) ;
mFocusColor = DarkTheme . COLOR_MENU_FOCUSED ;
mSelectColor = DarkTheme . COLOR_MENU_SELECTED ;
}
bool findHide = mSelfHeight = = 0 ;
2024-03-25 06:18:50 -04:00
if ( mChildWidgets ! = null )
{
for ( var widget in mChildWidgets )
{
if ( widget is ListViewItem )
continue ;
widget . mVisible = ! findHide ;
}
}
if ( findHide )
return ;
2019-08-23 11:56:54 -07:00
if ( headItem . mDisabled )
color = 0x80FFFFFF ;
else if ( mFailed )
color = 0xFFFF4040 ;
if ( IsBold )
watchListView . mFont = DarkTheme . sDarkTheme . mSmallBoldFont ;
2024-03-25 06:18:50 -04:00
var prevLabel = mLabel ;
if ( mColoredLabel ! = null )
mLabel = mColoredLabel ;
2019-08-23 11:56:54 -07:00
using ( g . PushColor ( color ) )
{
2024-03-25 06:18:50 -04:00
base . Draw ( g ) ;
2019-08-23 11:56:54 -07:00
}
2024-03-25 06:18:50 -04:00
mLabel = prevLabel ;
2019-08-23 11:56:54 -07:00
watchListView . mFont = DarkTheme . sDarkTheme . mSmallFont ;
if ( ( this = = headItem ) & & ( mWatchEntry . mResultType ! = WatchResultType . None ) )
{
DarkTheme . ImageIdx imageIdx = . IconValue ;
if ( mWatchEntry . mMemoryBreakpointAddr ! = 0 )
{
imageIdx = . RedDot ;
}
2019-12-24 13:13:04 -08:00
else if ( mWatchEntry . mResultType . HasFlag ( WatchResultType . Object ) )
2019-08-23 11:56:54 -07:00
{
if ( mWatchEntry . mIsDeleted )
imageIdx = . IconObjectDeleted ;
else
imageIdx = . IconObject ;
}
2019-12-24 13:13:04 -08:00
else if ( mWatchEntry . mResultType . HasFlag ( WatchResultType . TypeClass ) )
2019-08-23 11:56:54 -07:00
{
imageIdx = . Type_Class ;
}
2020-09-03 09:31:22 -07:00
else if ( mWatchEntry . mResultType . HasFlag ( WatchResultType . Interface ) )
{
imageIdx = . Interface ;
}
2019-12-24 13:13:04 -08:00
else if ( mWatchEntry . mResultType . HasFlag ( WatchResultType . TypeValueType ) )
2019-08-23 11:56:54 -07:00
{
2020-10-10 10:11:39 -07:00
imageIdx = . IconValue ;
2019-08-23 11:56:54 -07:00
}
2019-12-24 13:13:04 -08:00
else if ( mWatchEntry . mResultType . HasFlag ( WatchResultType . Namespace ) )
2019-08-23 11:56:54 -07:00
{
imageIdx = . Namespace ;
}
2019-12-24 13:13:04 -08:00
else if ( mWatchEntry . mResultType . HasFlag ( WatchResultType . Pointer ) )
2019-08-23 11:56:54 -07:00
{
imageIdx = . IconPointer ;
}
if ( valueItem . mFailed )
imageIdx = . IconError ;
2024-03-26 07:30:54 -04:00
float checkWidth = watchListView . mColumns [ 0 ] . mWidth ;
if ( mColumnIdx = = 0 )
checkWidth - = ( mDepth - 1 ) * watchListView . mChildIndent ;
2019-08-23 11:56:54 -07:00
2024-03-26 07:30:54 -04:00
if ( checkWidth > GS ! ( 32 ) )
{
var listView = ( WatchListView ) mListView ;
using ( g . PushColor ( headItem . mDisabled ? 0x80FFFFFF : Color . White ) )
{
g . Draw ( DarkTheme . sDarkTheme . GetImage ( imageIdx ) , listView . mLabelX - GS ! ( 22 ) , 0 ) ;
if ( mWatchEntry . mIsAppendAlloc )
g . Draw ( DarkTheme . sDarkTheme . GetImage ( . IconObjectAppend ) , listView . mLabelX - GS ! ( 22 ) , 0 ) ;
if ( mWatchEntry . mIsStackAlloc )
g . Draw ( DarkTheme . sDarkTheme . GetImage ( . IconObjectStack ) , listView . mLabelX - GS ! ( 22 ) , 0 ) ;
}
}
2019-08-23 11:56:54 -07:00
}
if ( mErrorEnd ! = 0 )
{
float labelX = 44 ;
String subStr = scope String ( ) ;
subStr . Append ( mLabel , 0 , Math . Min ( mErrorStart , mLabel . Length ) ) ;
float strStarts = labelX + g . mFont . GetWidth ( subStr ) ;
subStr . Clear ( ) ;
subStr . Append ( mLabel , 0 , Math . Min ( mErrorEnd , mLabel . Length ) ) ;
float strEnds = labelX + g . mFont . GetWidth ( subStr ) ;
strEnds = Math . Min ( mListView . mColumns [ 0 ] . mWidth - LabelX + labelX , strEnds ) ;
using ( g . PushColor ( 0xFFFF4040 ) )
IDEApp . sApp . DrawSquiggle ( g , strStarts , GS ! ( 2 ) , strEnds - strStarts ) ;
}
}
public override void Update ( )
{
2024-03-25 06:18:50 -04:00
var watchListView = ( WatchListView ) mListView ;
bool didWork = false ;
2019-11-07 06:53:32 -08:00
mMustUpdateBeforeEvaluate = false ;
2019-08-23 11:56:54 -07:00
if ( ( mWatchEntry ! = null ) & & ( mWatchEntry . mIsPending ) )
{
if ( ! gApp . mDebugger . mIsRunning )
{
mWatchEntry . mIsPending = false ;
}
else
{
gApp . mDebugger . EvaluateContinueKeep ( ) ;
if ( gApp . mDebugger . GetRunState ( ) = = . DebugEval_Done )
{
mWatchOwner . UpdateWatch ( this ) ;
}
}
}
if ( mParentItem . mChildAreaHeight ! = 0 )
{
2024-03-25 06:18:50 -04:00
float fullItemHeight = watchListView . mFont . GetLineSpacing ( ) ;
2019-08-23 11:56:54 -07:00
int32 addrSize = IDEApp . sApp . mDebugger . GetAddrSize ( ) * 2 ;
int32 dbgContinuationCount = 0 ;
2024-03-26 07:30:54 -04:00
bool findFiltering = watchListView . mFindFlags . HasFlag ( . Filtering ) ;
2019-08-23 11:56:54 -07:00
if ( ( mWatchSeriesInfo ! = null ) & & ( addrSize ! = 0 ) & & ( mSeriesMemberIdx = = 0 ) )
{
2024-03-26 07:30:54 -04:00
if ( mWatchSeriesInfo . mLastFindIdx ! = watchListView . mFindIdx )
{
mWatchSeriesInfo . mFindHadMatches = false ;
mWatchSeriesInfo . mFindFilteredIndices ? . Clear ( ) ;
}
if ( ( findFiltering ) & & ( mWatchSeriesInfo . mFindFilteredIndices = = null ) )
mWatchSeriesInfo . mFindFilteredIndices = new HashSet < int32 > ( ) ;
mWatchSeriesInfo . mLastFindIdx = watchListView . mFindIdx ;
2019-08-23 11:56:54 -07:00
/ * Stopwatch sw = new Stopwatch ( ) ;
sw . Start ( ) ; * /
/ * float ofsX ;
float ofsY ;
mParent . SelfToOtherTranslate ( mListView , 0 , 0 , out ofsX , out ofsY ) ; * /
float ofsX ;
float ofsY ;
mParent . SelfToOtherTranslate ( mListView , 0 , 0 , out ofsX , out ofsY ) ;
ofsY - = ( float ) mListView . mVertPos . mDest + mListView . mScrollContent . mY ;
int32 curMemberIdx = mWatchSeriesInfo . mStartMemberIdx ;
WatchListViewItem prevWatchListViewItem = null ;
WatchListViewItem nextWatchListViewItem = ( WatchListViewItem ) mParentItem . mChildItems [ curMemberIdx ] ;
int entryAddrSize = addrSize * mWatchSeriesInfo . mAddrsEntrySize ;
int addrsCount = 0 ;
if ( mWatchSeriesInfo . mAddrs ! = null )
addrsCount = mWatchSeriesInfo . mAddrs . Length / entryAddrSize ;
int totalCount = mWatchSeriesInfo . mCount ;
2021-12-16 07:49:39 -05:00
if ( ( totalCount = = - 1 ) & & ( mWatchSeriesInfo . mContinuationData ! = null ) )
2019-08-23 11:56:54 -07:00
{
//int wantNewCount = Math.Min(idx + 32, mWatchSeriesInfo.mCount) - addrsCount;
bool continuationDone = false ;
if ( BFApp . sApp . mIsUpdateBatchStart )
{
String continuationResult = scope String ( ) ;
IDEApp . sApp . mDebugger . GetCollectionContinuation ( mWatchSeriesInfo . mContinuationData , 256 , continuationResult ) ;
var continuationResultVals = scope List < StringView > ( continuationResult . Split ( '\n' ) ) ;
String extraAddrs = scope String ( continuationResultVals [ 0 ] ) ;
mWatchSeriesInfo . mAddrs . Append ( extraAddrs ) ;
if ( continuationResultVals . Count > 1 )
{
delete mWatchSeriesInfo . mContinuationData ;
mWatchSeriesInfo . mContinuationData = new String ( continuationResultVals [ 1 ] ) ;
}
if ( extraAddrs . Length = = 0 )
continuationDone = true ;
dbgContinuationCount + + ;
}
addrsCount = mWatchSeriesInfo . mAddrs . Length / entryAddrSize ;
totalCount = addrsCount ;
if ( continuationDone )
{
// We finally have the count
2019-12-09 10:28:56 -08:00
mWatchSeriesInfo . mCount = totalCount ;
2019-08-23 11:56:54 -07:00
}
}
2019-12-09 10:28:56 -08:00
mWatchSeriesInfo . mCurCount = totalCount ;
2019-08-23 11:56:54 -07:00
int showCount = Math . Min ( totalCount , mWatchSeriesInfo . mShowPages * mWatchSeriesInfo . mShowPageSize ) ;
float curY = mY ;
float prevY = curY ;
float lastBottomPadding = 0 ;
for ( int32 idx = 0 ; idx < showCount ; idx + + )
ShowBlock :
{
WatchListViewItem curWatchListViewItem = null ;
if ( ( nextWatchListViewItem ! = null ) & & ( idx = = nextWatchListViewItem . mSeriesMemberIdx ) )
{
curWatchListViewItem = nextWatchListViewItem ;
curMemberIdx + + ;
if ( curMemberIdx < mParentItem . mChildItems . Count )
{
nextWatchListViewItem = ( WatchListViewItem ) mParentItem . mChildItems [ curMemberIdx ] ;
if ( nextWatchListViewItem . mWatchSeriesInfo = = null )
nextWatchListViewItem = null ;
if ( nextWatchListViewItem ! = null )
lastBottomPadding = nextWatchListViewItem . mBottomPadding ;
}
else
nextWatchListViewItem = null ;
}
2024-03-25 06:18:50 -04:00
float itemHeight = fullItemHeight ;
2024-03-26 07:30:54 -04:00
float fillHeight = mListView . mHeight ;
if ( findFiltering )
{
// Over-fill to help us trim the filtered-out items
fillHeight * = 3 ;
}
bool wantsFillIn = ( curY + ofsY + itemHeight > = 0 ) & & ( curY + ofsY < fillHeight ) ;
2019-08-23 11:56:54 -07:00
bool wantsDelete = ! wantsFillIn ;
bool forceDelete = false ;
2019-10-09 16:18:11 -07:00
bool forceFillIn = false ;
2019-08-23 11:56:54 -07:00
2024-03-26 07:30:54 -04:00
bool wantItemFiltered = false ;
if ( ( findFiltering ) & & ( curWatchListViewItem ! = null ) )
{
wantItemFiltered = true ;
if ( ( ! curWatchListViewItem . mFindMismatch ) | | ( curWatchListViewItem . mChildHasMatch ) )
wantItemFiltered = false ;
else if ( ( watchListView . mFindParents ! = null ) & & ( watchListView . mFindParents . Contains ( curWatchListViewItem . mId ) ) )
wantItemFiltered = false ;
}
if ( wantItemFiltered )
itemHeight = 0 ;
if ( mWatchSeriesInfo . mFindFilteredIndices ? . Contains ( idx ) = = true )
{
2024-03-25 06:18:50 -04:00
itemHeight = 0 ;
2024-03-26 07:30:54 -04:00
wantsFillIn = false ;
}
2024-03-25 06:18:50 -04:00
2019-08-23 11:56:54 -07:00
if ( mDisabled )
{
wantsFillIn = false ;
wantsDelete = false ;
}
2019-10-09 16:18:11 -07:00
if ( ( curWatchListViewItem ! = null ) & & ( idx > 0 ) & & ( curWatchListViewItem . mWatchEntry . mSeriesFirstVersion ! = mWatchSeriesInfo . mSeriesFirstVersion ) )
2019-08-23 11:56:54 -07:00
{
// This logic gets invoked for Beef array views....
forceDelete = true ;
wantsFillIn = true ;
}
2019-10-09 16:18:11 -07:00
if ( ( curWatchListViewItem ! = null ) & & ( idx > 0 ) & & ( curWatchListViewItem . mWatchEntry . mSeriesVersion ! = mWatchSeriesInfo . mSeriesVersion ) )
{
forceFillIn = true ;
}
2024-03-26 07:30:54 -04:00
if ( ( findFiltering ) & & ( curWatchListViewItem ! = null ) & & ( ! wantItemFiltered ) )
{
mWatchSeriesInfo . mFindHadMatches = true ;
}
if ( ( findFiltering ) & & ( curWatchListViewItem ! = null ) & & ( wantItemFiltered ) & & ( idx ! = 0 ) )
{
// Filtered out!
mWatchSeriesInfo . mFindFilteredIndices . Add ( curWatchListViewItem . mSeriesMemberIdx ) ;
forceDelete = true ;
}
2024-03-25 06:18:50 -04:00
2019-08-23 11:56:54 -07:00
if ( ( forceDelete ) | |
2024-03-26 07:30:54 -04:00
( ( wantsDelete ) & & ( idx ! = 0 ) & & ( curWatchListViewItem ! = null ) & & ( curWatchListViewItem . mChildAreaHeight = = 0 ) & & ( ! curWatchListViewItem . mIsSelected ) ) )
2019-08-23 11:56:54 -07:00
{
2024-03-25 06:18:50 -04:00
didWork = true ;
2019-11-07 06:53:32 -08:00
if ( curWatchListViewItem = = nextWatchListViewItem )
nextWatchListViewItem = null ;
2019-08-23 11:56:54 -07:00
curMemberIdx - - ;
mParentItem . RemoveChildItem ( curWatchListViewItem ) ;
curWatchListViewItem = null ;
}
2024-03-26 07:30:54 -04:00
if ( ( ( curWatchListViewItem = = null ) & & ( wantsFillIn ) ) | |
2019-10-09 16:18:11 -07:00
( forceFillIn ) )
2019-08-23 11:56:54 -07:00
{
2024-03-25 06:18:50 -04:00
didWork = true ;
2024-03-26 07:30:54 -04:00
prevWatchListViewItem . mBottomPadding = Math . Max ( ( curY - prevWatchListViewItem . mY ) - prevWatchListViewItem . mSelfHeight - prevWatchListViewItem . mChildAreaHeight , 0 ) ;
Debug . Assert ( prevWatchListViewItem . mBottomPadding > = 0 ) ;
2019-10-09 16:18:11 -07:00
if ( curWatchListViewItem = = null )
curWatchListViewItem = ( WatchListViewItem ) mParentItem . CreateChildItemAtIndex ( curMemberIdx ) ;
2019-08-23 11:56:54 -07:00
curWatchListViewItem . mX = mX ;
2019-10-09 16:18:11 -07:00
if ( curWatchListViewItem . mWatchSeriesInfo = = null )
{
curWatchListViewItem . mVisible = false ;
mWatchSeriesInfo . AddRef ( ) ;
curWatchListViewItem . mWatchSeriesInfo = mWatchSeriesInfo ;
curWatchListViewItem . mSeriesMemberIdx = idx ;
}
else
{
Debug . Assert ( curWatchListViewItem . mWatchSeriesInfo = = mWatchSeriesInfo ) ;
Debug . Assert ( curWatchListViewItem . mSeriesMemberIdx = = idx ) ;
}
2019-08-23 11:56:54 -07:00
Object [ ] formatParams = scope Object [ mWatchSeriesInfo . mAddrsEntrySize + 1 ] ;
formatParams [ 0 ] = idx ;
if ( mWatchSeriesInfo . mAddrs ! = null )
{
if ( idx > = addrsCount )
{
int wantNewCount = Math . Min ( idx + 32 , mWatchSeriesInfo . mCount ) - addrsCount ;
String continuationResult = scope String ( ) ;
IDEApp . sApp . mDebugger . GetCollectionContinuation ( mWatchSeriesInfo . mContinuationData , ( int32 ) wantNewCount , continuationResult ) ;
if ( ! continuationResult . IsEmpty )
{
var continuationResultVals = scope List < StringView > ( continuationResult . Split ( '\n' ) ) ;
mWatchSeriesInfo . mAddrs . Append ( scope String ( continuationResultVals [ 0 ] ) ) ;
mWatchSeriesInfo . mContinuationData . Set ( scope String ( continuationResultVals [ 1 ] ) ) ;
addrsCount = mWatchSeriesInfo . mAddrs . Length / entryAddrSize ;
dbgContinuationCount + + ;
}
}
for ( int32 i = 0 ; i < mWatchSeriesInfo . mAddrsEntrySize ; i + + )
{
if ( idx > = addrsCount )
{
formatParams [ i + 1 ] = "?" ;
}
else
{
var str = scope : ShowBlock String ( ) ;
str . Append ( mWatchSeriesInfo . mAddrs , idx * entryAddrSize + ( i * addrSize ) , addrSize ) ;
formatParams [ i + 1 ] = str ;
}
}
}
var dispStr = scope String ( ) ;
2024-12-31 07:48:03 -08:00
dispStr . AppendF ( mWatchSeriesInfo . mDisplayTemplate , params formatParams ) . IgnoreError ( ) ;
2019-08-23 11:56:54 -07:00
var evalStr = scope String ( ) ;
2024-12-31 07:48:03 -08:00
evalStr . AppendF ( mWatchSeriesInfo . mEvalTemplate , params formatParams ) . IgnoreError ( ) ;
2019-08-23 11:56:54 -07:00
watchListView . mWatchOwner . SetupListViewItem ( curWatchListViewItem , dispStr , evalStr ) ;
2019-10-09 16:18:11 -07:00
curWatchListViewItem . mWatchEntry . mSeriesFirstVersion = mWatchSeriesInfo . mSeriesFirstVersion ;
curWatchListViewItem . mWatchEntry . mSeriesVersion = mWatchSeriesInfo . mSeriesVersion ;
if ( ! forceFillIn )
curMemberIdx + + ;
2019-08-23 11:56:54 -07:00
}
if ( prevWatchListViewItem ! = null )
{
if ( mDisabled )
prevWatchListViewItem . mBottomPadding = 0 ;
else
2024-03-26 07:30:54 -04:00
prevWatchListViewItem . mBottomPadding = Math . Max ( ( curY - prevY ) - prevWatchListViewItem . mSelfHeight - prevWatchListViewItem . mChildAreaHeight , 0 ) ;
Debug . Assert ( prevWatchListViewItem . mBottomPadding > = 0 ) ;
2019-08-23 11:56:54 -07:00
}
if ( curWatchListViewItem ! = null )
prevY = curY ;
2022-05-18 13:23:10 -07:00
if ( curWatchListViewItem ! = null )
{
var dataItem = curWatchListViewItem . GetSubItem ( 1 ) as WatchListViewItem ;
if ( dataItem . mCustomContentWidget ! = null )
curY + = curWatchListViewItem . mSelfHeight ;
else
curY + = itemHeight ;
}
else
curY + = itemHeight ;
2019-08-23 11:56:54 -07:00
if ( curWatchListViewItem ! = null )
{
curY + = curWatchListViewItem . mChildAreaHeight ;
prevWatchListViewItem = curWatchListViewItem ;
}
}
if ( totalCount > mWatchSeriesInfo . mShowPageSize )
{
if ( mWatchSeriesInfo . mMoreButton = = null )
{
mWatchSeriesInfo . mMoreButton = ( DarkButton ) DarkTheme . sDarkTheme . CreateButton ( mParent , "More" , mX + GS ! ( 26 ) , 0 , GS ! ( 68 ) , GS ! ( 20 ) ) ;
mWatchSeriesInfo . mMoreButton . mOnMouseClick . Add ( new ( evt ) = >
{
if ( mWatchSeriesInfo . mMoreButton . mDisabled )
return ;
2019-12-09 10:28:56 -08:00
mWatchSeriesInfo . mShowPages = ( int32 ) Math . Min ( mWatchSeriesInfo . mShowPages + 1 , 1 + ( mWatchSeriesInfo . mCurCount + mWatchSeriesInfo . mShowPageSize - 1 ) / mWatchSeriesInfo . mShowPageSize ) ;
2019-08-23 11:56:54 -07:00
mWatchSeriesInfo . mMoreButton . mVisible = false ;
mWatchSeriesInfo . mLessButton . mVisible = false ;
} ) ;
mWatchSeriesInfo . mMoreButton . mOnDeleted . Add ( new ( widget ) = >
{ NOP ! ( ) ; } ) ;
mWatchSeriesInfo . mLessButton = ( DarkButton ) DarkTheme . sDarkTheme . CreateButton ( mParent , "Less" , mX + GS ! ( 26 + 68 + 2 ) , 0 , GS ! ( 68 ) , GS ! ( 20 ) ) ;
mWatchSeriesInfo . mLessButton . mOnMouseClick . Add ( new ( evt ) = > { mWatchSeriesInfo . mShowPages = Math . Max ( 1 , mWatchSeriesInfo . mShowPages - 1 ) ; } ) ;
}
float xOfs = 16 ;
float absX ;
float absY ;
SelfToOtherTranslate ( mListView , xOfs , 0 , out absX , out absY ) ;
float btnX = mX + xOfs ;
float buttonAreaWidth = ( mListView . mColumns [ 0 ] . mWidth + mListView . mColumns [ 1 ] . mWidth - absX * 2 ) ;
float btnWidth = ( buttonAreaWidth - 4 ) / 2 ;
curY + = 3 ;
btnWidth = 62 ;
mWatchSeriesInfo . mMoreButton . mVisible = ! mDisabled ;
mWatchSeriesInfo . mMoreButton . mDisabled = showCount > = totalCount ;
mWatchSeriesInfo . mMoreButton . Resize ( btnX , curY , btnWidth , 20 ) ;
mWatchSeriesInfo . mLessButton . mVisible = ! mDisabled ;
mWatchSeriesInfo . mLessButton . mVisible = mWatchSeriesInfo . mShowPages > 1 ;
mWatchSeriesInfo . mLessButton . Resize ( btnX + btnWidth + 2 , curY , btnWidth , 20 ) ;
curY + = 21 ;
}
else
{
if ( mWatchSeriesInfo . mMoreButton ! = null )
{
Widget . RemoveAndDelete ( mWatchSeriesInfo . mMoreButton ) ;
mWatchSeriesInfo . mMoreButton = null ;
Widget . RemoveAndDelete ( mWatchSeriesInfo . mLessButton ) ;
mWatchSeriesInfo . mLessButton = null ;
}
}
if ( prevWatchListViewItem ! = null )
{
if ( mDisabled )
prevWatchListViewItem . mBottomPadding = 0 ;
else
2024-03-26 07:30:54 -04:00
prevWatchListViewItem . mBottomPadding = Math . Max ( ( curY - prevY ) - prevWatchListViewItem . mSelfHeight - prevWatchListViewItem . mChildAreaHeight , 0 ) ;
Debug . Assert ( prevWatchListViewItem . mBottomPadding > = 0 ) ;
2019-08-23 11:56:54 -07:00
if ( prevWatchListViewItem . mBottomPadding ! = lastBottomPadding )
mListView . mListSizeDirty = true ;
}
while ( curMemberIdx < mParentItem . mChildItems . Count )
{
var curWatchListViewItem = ( WatchListViewItem ) mParentItem . mChildItems [ curMemberIdx ] ;
if ( curWatchListViewItem . mWatchSeriesInfo = = null )
break ;
if ( curWatchListViewItem = = this )
{
mWantRemoveSelf = true ;
return ;
}
mParentItem . RemoveChildItem ( curWatchListViewItem ) ;
/ * if ( mParentItem = = null )
return ; * /
}
/ * sw . Stop ( ) ;
int elapsedMs = ( int ) sw . ElapsedMilliseconds ;
if ( elapsedMs > 50 )
{
Console . WriteLine ( "WatchPanel Update: {0}ms Cont:{1}" , elapsedMs , dbgContinuationCount ) ;
} * /
}
}
2022-05-21 11:58:01 -07:00
if ( mColumnIdx = = 1 )
{
var nameItem = GetSubItem ( 0 ) as WatchListViewItem ;
if ( nameItem . mWatchEntry ? . mStackFrameId ! = null )
{
if ( DarkTooltipManager . CheckMouseover ( this , 20 , var mousePoint ) )
{
float drawX = mWidth - GS ! ( 16 ) ;
if ( nameItem . mWatchRefreshButton ! = null )
drawX - = GS ! ( 16 ) ;
if ( Rect ( drawX , 0 , GS ! ( 16 ) , GS ! ( 20 ) ) . Contains ( mousePoint ) )
{
String tooltip = scope String ( ) ;
tooltip . Append ( nameItem . mWatchEntry . mStackFrameId ) ;
int lastColon = nameItem . mWatchEntry . mStackFrameId . LastIndexOf ( ':' ) ;
if ( ( lastColon > - 1 ) & & ( var addr = int64 . Parse ( nameItem . mWatchEntry . mStackFrameId . Substring ( lastColon + 1 ) , . HexNumber ) ) )
{
tooltip . Append ( "\n" ) ;
gApp . mDebugger . GetAddressSymbolName ( addr , true , tooltip ) ;
}
DarkTooltipManager . ShowTooltip ( tooltip , this , mousePoint . x , mousePoint . y ) ;
}
}
}
}
2024-03-25 06:18:50 -04:00
if ( didWork )
watchListView . DidWork ( ) ;
2019-08-23 11:56:54 -07:00
base . Update ( ) ;
}
2024-03-26 07:30:54 -04:00
public void ChildHasMatch ( )
2019-08-23 11:56:54 -07:00
{
2024-03-26 07:30:54 -04:00
if ( mChildHasMatch )
return ;
2024-03-25 06:18:50 -04:00
var watchListView = ( WatchListView ) mListView ;
2024-03-26 07:30:54 -04:00
if ( ( ! IsOpen ) & & ( watchListView . mFindFlags . HasFlag ( . Filtering ) ) & & ( ! watchListView . mFindFlags . HasFlag ( . Deep ) ) )
return ;
2024-03-25 06:18:50 -04:00
2024-03-26 07:30:54 -04:00
mChildHasMatch = true ;
if ( watchListView . mFindFlags . HasFlag ( . Filtering ) )
2024-03-25 06:18:50 -04:00
{
2024-03-26 07:30:54 -04:00
// Make sure we don't close a previously-opened parent even if we close a parent and hide the actual child match
if ( watchListView . mFindParents = = null )
watchListView . mFindParents = new . ( ) ;
watchListView . mFindParents . Add ( mId ) ;
2024-03-25 06:18:50 -04:00
}
2024-03-26 07:30:54 -04:00
var parentWatchItem = mParentItem as WatchListViewItem ;
if ( parentWatchItem ! = null )
parentWatchItem . ChildHasMatch ( ) ;
}
public override void UpdateAll ( )
{
var watchListView = ( WatchListView ) mListView ;
2024-03-25 06:18:50 -04:00
mChildHasMatch = false ;
2024-03-26 07:30:54 -04:00
// Check to see if we need to open this up for a deep filter
// Do this before UpdateAll to ensure tha the "highest level" instance of mEvalStr is the one we open
if ( ( ( watchListView . mFindFlags . HasFlag ( . Deep ) ) & & ( watchListView . mFindFlags . HasFlag ( . Filtering ) ) ) & & ( IsParent ) & & ( mDepth < watchListView . mMaxFindDepth ) & &
( mWatchEntry ! = null ) & & ( watchListView . mFindOpenedExprs . TryAdd ( mWatchEntry . mEvalStr , var evalStrPtr ) ) )
{
* evalStrPtr = new . ( mWatchEntry . mEvalStr ) ;
if ( IsOpen )
{
// Nothing to do
}
else if ( ( mWatchEntry . mLanguage = = . Beef ) & & ( mWatchEntry . mResultTypeStr = = "System.String" ) )
{
// Optimization to avoid inspecting string members, particularly the [RawChars]
}
else if ( watchListView . mItrStopwatch . ElapsedMilliseconds > = 20 )
{
// Open this up next time...
watchListView . DidWork ( ) ;
return ;
}
else
{
Open ( true , true ) ;
watchListView . DidWork ( ) ;
}
}
2019-08-23 11:56:54 -07:00
base . UpdateAll ( ) ;
if ( mWantRemoveSelf )
2025-01-27 09:17:45 -08:00
{
2024-08-25 09:30:49 -04:00
mParentItem ? . RemoveChildItem ( this ) ;
2025-01-27 09:17:45 -08:00
return ;
}
2024-03-25 06:18:50 -04:00
if ( mColumnIdx = = 0 )
{
var parentWatchItem = mParentItem as WatchListViewItem ;
2024-03-26 07:30:54 -04:00
if ( mWatchSeriesInfo ! = null )
{
if ( ( mWatchSeriesInfo . mFindHadMatches ) & & ( mWatchSeriesInfo . mLastFindIdx = = watchListView . mFindIdx ) )
parentWatchItem ? . ChildHasMatch ( ) ;
}
2024-03-25 06:18:50 -04:00
float wantHeight ;
CheckFindString ( ) ;
2024-03-26 07:30:54 -04:00
bool wantsFiltered = false ;
if ( ( watchListView . mFindFlags . HasFlag ( . Filtering ) ) & & ( mFindMismatch ) & & ( ! mChildHasMatch ) )
{
if ( ( watchListView . mFindParents ! = null ) & & ( watchListView . mFindParents . Contains ( mId ) ) )
{
// In list, don't close
}
else
wantsFiltered = true ;
}
if ( wantsFiltered )
2024-03-25 06:18:50 -04:00
wantHeight = 0 ;
else
wantHeight = watchListView . mFont . GetLineSpacing ( ) ;
2025-01-18 10:05:56 -08:00
if ( ( mSelfHeight ! = wantHeight ) & & ( ! mFreezeHeight ) )
2024-03-25 06:18:50 -04:00
{
mSelfHeight = wantHeight ;
watchListView . mListSizeDirty = true ;
}
if ( ! mFindMismatch )
2024-03-26 07:30:54 -04:00
{
parentWatchItem ? . ChildHasMatch ( ) ;
}
2024-03-25 06:18:50 -04:00
}
2019-08-23 11:56:54 -07:00
}
}
public class WatchPanel : Panel , IWatchOwner
2024-03-26 07:30:54 -04:00
{
2019-08-23 11:56:54 -07:00
public WatchListView mListView ;
public WatchListViewItem mSelectedParentItem ;
bool mCancelingEdit ;
bool mWatchesDirty ;
bool mHadStep ;
bool mClearHadStep ;
bool mDisabled = true ;
bool mIsAuto ;
int32 mDisabledTicks ;
bool mDeselectOnFocusLost = true ;
public WatchListViewItem mEditingItem ;
public ExpressionEditWidget mEditWidget ;
2024-03-26 07:30:54 -04:00
public bool HasFocus
{
get
{
if ( mHasFocus )
return true ;
if ( ( mWidgetWindow . mFocusWidget ! = null ) & & ( mWidgetWindow . mFocusWidget . HasParent ( this ) ) )
return true ;
return false ;
}
}
2019-08-23 11:56:54 -07:00
public this ( bool isAuto )
{
mIsAuto = isAuto ;
mListView = new WatchListView ( this ) ;
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 ( ) ;
AddWidget ( mListView ) ;
mListView . mOnMouseClick . Add ( new = > ListViewClicked ) ;
mListView . mOnMouseDown . Add ( new = > ListViewMouseDown ) ;
mListView . mOnItemMouseClicked . Add ( new = > ValueClicked ) ;
mListView . mOnItemMouseDown . Add ( new = > ValueMouseDown ) ;
ListViewColumn column = mListView . AddColumn ( GS ! ( 200 ) , "Name" ) ;
column . mMinWidth = GS ! ( 40 ) ;
column = mListView . AddColumn ( GS ! ( 200 ) , "Value" ) ;
column . mMinWidth = GS ! ( 40 ) ;
column = mListView . AddColumn ( GS ! ( 200 ) , "Type" ) ;
mListView . mOnDragEnd . Add ( new = > HandleDragEnd ) ;
mListView . mOnDragUpdate . Add ( new = > HandleDragUpdate ) ;
SetScaleData ( ) ;
//RebuildUI();
}
public void Reset ( )
{
mListView . GetRoot ( ) . Clear ( ) ;
}
void SetScaleData ( )
{
2024-03-25 06:18:50 -04:00
2019-08-23 11:56:54 -07:00
}
public override void RehupScale ( float oldScale , float newScale )
{
2020-03-28 14:26:59 -07:00
base . RehupScale ( oldScale , newScale ) ;
2020-03-29 10:17:28 -07:00
SetScaleData ( ) ;
2019-08-23 11:56:54 -07:00
}
public void Serialize ( StructuredData data , bool includeItems )
{
data . Add ( "Type" , mIsAuto ? "AutoWatchPanel" : "WatchPanel" ) ;
IDEUtils . SerializeListViewState ( data , mListView ) ;
if ( includeItems & & ! mIsAuto )
{
using ( data . CreateArray ( "Items" ) )
{
var childItems = mListView . GetRoot ( ) . mChildItems ;
if ( childItems ! = null )
{
for ( WatchListViewItem watchListViewItem in childItems )
{
var watchEntry = watchListViewItem . mWatchEntry ;
2024-12-31 13:17:53 -08:00
using ( data . CreateObject ( ) )
{
data . Add ( "EvalStr" , watchEntry . mEvalStr ) ;
if ( watchEntry . mAutoRefresh ! = null )
data . Add ( "AutoRefresh" , watchEntry . mAutoRefresh . Value ) ;
}
2019-08-23 11:56:54 -07:00
}
}
}
}
}
public override void Serialize ( StructuredData data )
{
base . Serialize ( data ) ;
Serialize ( data , true ) ;
}
public override bool Deserialize ( StructuredData data )
{
base . Deserialize ( data ) ;
IDEUtils . DeserializeListViewState ( data , mListView ) ;
for ( let itemKey in data . Enumerate ( "Items" ) )
{
2024-12-31 13:17:53 -08:00
String watchEntry = scope String ( ) ;
data . GetCurString ( watchEntry ) ;
WatchListViewItem watchItem ;
if ( ! watchEntry . IsEmpty )
{
watchItem = AddWatch ( watchEntry ) ;
}
else
{
data . GetString ( "EvalStr" , watchEntry ) ;
watchItem = AddWatch ( watchEntry ) ;
if ( data . Contains ( "AutoRefresh" ) )
{
watchItem . mWatchEntry . mAutoRefresh = data . GetBool ( "AutoRefresh" ) ;
}
}
2019-08-23 11:56:54 -07:00
}
return true ;
}
public override void FocusForKeyboard ( )
{
var root = mListView . GetRoot ( ) ;
if ( root . GetChildCount ( ) > 0 )
{
var lastItem = root . GetChildAtIndex ( root . GetChildCount ( ) - 1 ) ;
root . SelectItemExclusively ( lastItem ) ;
mListView . EnsureItemVisible ( lastItem , false ) ;
}
}
static void CompactChildExpression ( WatchListViewItem listViewItem , String outExpr )
{
var parentItem = listViewItem . GetWatchListViewItemParent ( ) ;
if ( parentItem = = null )
{
outExpr . Append ( listViewItem . mWatchEntry . mEvalStr ) ;
return ;
}
String parentEvalStr = scope String ( ) ;
CompactChildExpression ( parentItem , parentEvalStr ) ;
String evalStr = listViewItem . mWatchEntry . mEvalStr ;
String compactEvalStr = scope String ( ) ;
IDEApp . sApp . mDebugger . CompactChildExpression ( evalStr , parentEvalStr , compactEvalStr ) ;
outExpr . Set ( compactEvalStr ) ;
}
void HandleDragUpdate ( DragEvent evt )
{
2021-01-03 11:51:53 -08:00
var dragKind = evt . mDragKind ;
evt . mDragKind = . None ;
2019-08-23 11:56:54 -07:00
if ( mIsAuto )
return ;
var dragSource = evt . mSender as WatchListViewItem ;
var dragTarget = evt . mDragTarget as WatchListViewItem ;
if ( dragSource = = null )
return ;
if ( dragTarget = = null )
return ;
if ( dragSource . mLabel = = "" )
return ;
2023-02-08 10:18:15 -05:00
if ( dragKind = = . Inside )
{
dragSource . SelfToRootTranslate ( evt . mX , evt . mY , var rootX , var rootY ) ;
dragTarget . RootToSelfTranslate ( rootX , rootY , var targetX , var targetY ) ;
//dragSource.SelfToOtherTranslate(dragTarget, evt.mX, evt.mY, var targetX, var targetY);
if ( targetY < dragTarget . mSelfHeight / 2 )
dragKind = . Before ;
else
dragKind = . After ;
}
2019-08-23 11:56:54 -07:00
while ( dragTarget . mParentItem ! = mListView . GetRoot ( ) )
{
// Check for if we're dragging after the last open child item. If so, treat it as if we're dragging to after the topmost parent
/ * if ( ( evt . mDragTargetDir ! = 1 ) | | ( dragTarget ! = dragTarget . mParentItem . mChildItems [ dragTarget . mParentItem . mChildItems . Count - 1 ] ) )
return ; * /
2021-01-03 11:51:53 -08:00
evt . mDragKind = . After ;
2019-08-23 11:56:54 -07:00
dragTarget = ( WatchListViewItem ) dragTarget . mParentItem ;
evt . mDragTarget = dragTarget ;
2021-02-25 10:14:22 -08:00
return ;
2019-08-23 11:56:54 -07:00
}
2021-01-03 11:51:53 -08:00
if ( ( dragTarget . mLabel = = "" ) & & ( dragKind = = . After ) )
dragKind = . Before ;
if ( dragKind = = . None )
2019-08-23 11:56:54 -07:00
return ;
2021-01-03 11:51:53 -08:00
evt . mDragKind = dragKind ;
2019-08-23 11:56:54 -07:00
}
void HandleDragEnd ( DragEvent theEvent )
{
2021-01-03 11:51:53 -08:00
if ( theEvent . mDragKind = = . None )
2019-08-23 11:56:54 -07:00
return ;
if ( theEvent . mDragTarget is IDEListViewItem )
{
var source = ( WatchListViewItem ) theEvent . mSender ;
var target = ( WatchListViewItem ) theEvent . mDragTarget ;
if ( source . mListView = = target . mListView )
{
if ( source = = target )
return ;
if ( source . mParentItem = = mListView . GetRoot ( ) )
{
// We're dragging a top-level item into a new position
source . mParentItem . RemoveChildItem ( source , false ) ;
2021-01-03 11:51:53 -08:00
if ( theEvent . mDragKind = = . Before ) // Before
2019-08-23 11:56:54 -07:00
target . mParentItem . InsertChild ( source , target ) ;
2021-01-03 11:51:53 -08:00
else if ( theEvent . mDragKind = = . After ) // After
2019-08-23 11:56:54 -07:00
target . mParentItem . AddChild ( source , target ) ;
}
else
{
String compactEvalStr = scope String ( ) ;
CompactChildExpression ( source , compactEvalStr ) ;
var rootItem = mListView . GetRoot ( ) ;
2019-12-21 05:48:44 -08:00
int idx = rootItem . mChildItems . IndexOf ( target ) ;
2021-01-03 11:51:53 -08:00
if ( theEvent . mDragKind = = . After )
idx + + ;
2019-08-23 11:56:54 -07:00
var listViewItem = ( WatchListViewItem ) rootItem . CreateChildItemAtIndex ( idx ) ;
listViewItem . mVisible = false ;
SetupListViewItem ( listViewItem , compactEvalStr , compactEvalStr ) ;
rootItem . SelectItemExclusively ( listViewItem ) ;
mListView . EnsureItemVisible ( listViewItem , true ) ;
}
}
}
}
WatchListView IWatchOwner . GetWatchListView ( )
{
return mListView ;
}
public void SetupListViewItem ( WatchListViewItem listViewItem , String name , String evalStr )
{
WatchEntry watchEntry = new WatchEntry ( ) ;
watchEntry . mName = new String ( name ) ;
watchEntry . mEvalStr = new String ( evalStr ? ? name ) ;
listViewItem . Label = name ;
listViewItem . AllowDragging = true ;
listViewItem . mOpenOnDoubleClick = false ;
2019-10-09 16:18:11 -07:00
var subViewItem = ( DarkListViewItem ) listViewItem . GetOrCreateSubItem ( 1 ) ;
2019-08-23 11:56:54 -07:00
subViewItem . Label = "" ;
subViewItem . AllowDragging = true ;
2019-10-09 16:18:11 -07:00
subViewItem = ( DarkListViewItem ) listViewItem . GetOrCreateSubItem ( 2 ) ;
2019-08-23 11:56:54 -07:00
subViewItem . Label = "" ;
subViewItem . AllowDragging = true ;
2019-10-09 16:18:11 -07:00
delete listViewItem . mWatchEntry ;
listViewItem . mWatchEntry = watchEntry ;
2019-08-23 11:56:54 -07:00
}
2019-11-07 06:53:32 -08:00
public WatchListViewItem AddWatchItem ( String name )
2019-08-23 11:56:54 -07:00
{
// This is the public interface to AddWatch, which uses the first available blank watch slot or appends a new one if necessary
var rootItem = mListView . GetRoot ( ) ;
int childCount = mListView . GetRoot ( ) . GetChildCount ( ) ;
for ( int iChild = 0 ; iChild < childCount ; + + iChild )
{
if ( rootItem . GetChildAtIndex ( iChild ) . mLabel . Length > 0 )
continue ;
rootItem . RemoveChildItem ( rootItem . GetChildAtIndex ( iChild ) ) ;
var listViewItem = ( WatchListViewItem ) rootItem . CreateChildItemAtIndex ( iChild ) ;
listViewItem . mVisible = false ;
SetupListViewItem ( listViewItem , name , null ) ;
rootItem . SelectItemExclusively ( listViewItem ) ;
mListView . EnsureItemVisible ( listViewItem , true ) ;
2019-11-07 06:53:32 -08:00
return listViewItem ;
2019-08-23 11:56:54 -07:00
}
2019-11-07 06:53:32 -08:00
return AddWatch ( name ) ;
2019-08-23 11:56:54 -07:00
}
WatchListViewItem AddWatch ( String name , String evalStr = null , ListViewItem parentItem = null )
{
MarkDirty ( ) ;
var useParentItem = parentItem ;
if ( useParentItem = = null )
useParentItem = mListView . GetRoot ( ) ;
var listViewItem = ( WatchListViewItem ) useParentItem . CreateChildItem ( ) ;
listViewItem . mVisible = false ;
SetupListViewItem ( listViewItem , name , evalStr ) ;
2019-09-28 12:15:36 -07:00
if ( ( parentItem ! = null ) & & ( parentItem . Selected ) )
{
// If the parentItem is selected and the next item after the parentItem is selected then we may have a selection span
// so we want to expand that selection to the newly-created item
int parentIdx = parentItem . mParentItem . GetIndexOfChild ( parentItem ) ;
if ( parentIdx + 1 < parentItem . mParentItem . mChildItems . Count )
{
let nextItem = parentItem . mParentItem . mChildItems [ parentIdx + 1 ] ;
if ( nextItem . Selected )
{
if ( ( parentItem . mChildItems . Count = = 1 ) | | ( parentItem . mChildItems [ parentItem . mChildItems . Count - 2 ] . Selected ) )
listViewItem . Selected = true ;
}
}
}
2019-08-23 11:56:54 -07:00
return listViewItem ;
}
public void SetDisabled ( bool disabled )
{
MarkDirty ( ) ;
mDisabled = disabled ;
mMouseVisible = ! disabled ;
mDisabledTicks = 0 ;
if ( ! gApp . mDebugger . mIsRunning )
mDisabledTicks = 9999 ; // Show immediately grey
}
public override void DrawAll ( Graphics g )
{
bool showDisabled = ( mDisabled ) & & ( mDisabledTicks > 40 ) ;
using ( g . PushColor ( showDisabled ? 0x80FFFFFF : Color . White ) )
base . DrawAll ( g ) ;
2024-03-26 07:30:54 -04:00
bool hasVisibleItem = false ;
bool hasHiddemItems = false ;
2024-03-26 11:03:40 -04:00
if ( mListView . GetRoot ( ) . GetChildCount ( ) > 0 )
2024-03-26 07:30:54 -04:00
{
2024-03-26 11:03:40 -04:00
for ( var item in mListView . GetRoot ( ) . mChildItems )
{
if ( item . mSelfHeight > 0 )
hasVisibleItem = true ;
else
hasHiddemItems = true ;
}
2024-03-26 07:30:54 -04:00
}
if ( ( hasHiddemItems ) & & ( ! hasVisibleItem ) )
{
g . SetFont ( DarkTheme . sDarkTheme . mSmallFont ) ;
using ( g . PushColor ( 0x80FFFFFF ) )
g . DrawString ( "No Results" , GS ! ( 24 ) , GS ! ( 48 ) ) ;
}
2019-08-23 11:56:54 -07:00
}
public void MarkWatchesDirty ( bool hadStep , bool clearHadStep = false )
{
MarkDirty ( ) ;
mWatchesDirty = true ;
if ( hadStep )
mHadStep = true ;
if ( clearHadStep )
mClearHadStep = true ;
2024-03-26 07:30:54 -04:00
mListView . RehupFind ( ) ;
2019-08-23 11:56:54 -07:00
}
public override void Resize ( float x , float y , float width , float height )
{
base . Resize ( x , y , width , height ) ;
mListView . Resize ( 0 , 0 , width , height ) ;
}
void HandleRenameCancel ( EditEvent theEvent )
{
mCancelingEdit = true ;
bool removedItem ;
DoHandleEditLostFocus ( ( EditWidget ) theEvent . mSender , out removedItem ) ;
if ( ( mHasFocus ) & & ( ! removedItem ) )
{
Update ( ) ;
/ * var lastItem = mListView . GetRoot ( ) . mChildItems [ mListView . GetRoot ( ) . mChildItems . Count - 1 ] ;
lastItem . Focused = true ; * /
}
}
void HandleRenameSubmit ( EditEvent theEvent )
{
var watchEditWidgetContent = ( ExpressionEditWidgetContent ) mEditWidget . Content ;
if ( ( watchEditWidgetContent . mAutoComplete ! = null ) & & ( watchEditWidgetContent . mAutoComplete . HasSelection ( ) ) )
watchEditWidgetContent . mAutoComplete . InsertSelection ( ( char8 ) 0 ) ;
HandleEditLostFocus ( ( EditWidget ) theEvent . mSender ) ;
}
void HandleEditLostFocus ( Widget widget )
{
bool removedItem ;
DoHandleEditLostFocus ( widget , out removedItem ) ;
}
void HandleEditKeyDown ( KeyDownEvent evt )
{
if ( ( ( evt . mKeyCode = = . Tab ) | | ( evt . mKeyCode = = . F2 ) ) & &
( evt . mKeyFlags = = 0 ) )
{
if ( ! mEditWidget . IsShowingAutoComplete ( ) )
{
let valueItem = ( WatchListViewItem ) mEditingItem . GetSubItem ( 1 ) ;
if ( ! valueItem . Label . IsEmpty )
{
EditEvent editEvent = scope . ( ) ;
editEvent . mSender = evt . mSender ;
HandleRenameCancel ( editEvent ) ;
EditListViewItem ( valueItem ) ;
}
}
}
}
void DoHandleEditLostFocus ( Widget widget , out bool removedItem )
{
removedItem = false ;
EditWidget editWidget = ( EditWidget ) widget ;
editWidget . mOnLostFocus . Remove ( scope = > HandleEditLostFocus , true ) ;
editWidget . mOnSubmit . Remove ( scope = > HandleRenameSubmit , true ) ;
editWidget . mOnCancel . Remove ( scope = > HandleRenameCancel , true ) ;
editWidget . mOnKeyDown . Remove ( scope = > HandleEditKeyDown , true ) ;
WidgetWindow . sOnMouseWheel . Remove ( scope = > HandleMouseWheel , true ) ;
if ( ! mEditWidget . Content . HasUndoData ( ) )
mCancelingEdit = true ;
String newValue = scope String ( ) ;
editWidget . GetText ( newValue ) ;
newValue . Trim ( ) ;
WatchListViewItem listViewItem = ( WatchListViewItem ) mEditingItem ;
int32 column = listViewItem . mColumnIdx ;
if ( column = = 0 )
{
var trimmedLabel = scope String ( listViewItem . mLabel ) ;
trimmedLabel . Trim ( ) ;
if ( trimmedLabel ! = newValue )
{
var watchEntry = listViewItem . mWatchEntry ;
watchEntry . mIsNewExpression = true ;
if ( ! mCancelingEdit )
listViewItem . Label = newValue ;
if ( listViewItem . mLabel . Length > 0 )
{
String . NewOrSet ! ( watchEntry . mName , listViewItem . mLabel ) ;
String . NewOrSet ! ( watchEntry . mEvalStr , watchEntry . mName ) ;
IDEApp . sApp . mMemoryPanel . MarkViewDirty ( ) ;
gApp . MarkWatchesDirty ( ) ;
}
else
{
mListView . GetRoot ( ) . RemoveChildItem ( listViewItem ) ;
removedItem = true ;
}
}
}
else if ( ( column = = 1 ) & & ( newValue . Length > 0 ) & & ( ! mCancelingEdit ) )
{
var headListViewItem = ( WatchListViewItem ) listViewItem . GetSubItem ( 0 ) ;
String evalStr = scope String ( headListViewItem . mWatchEntry . mEvalStr , ", assign=" , newValue ) ;
String val = scope String ( ) ;
gApp . DebugEvaluate ( headListViewItem . mWatchEntry . mResultTypeStr , evalStr , val , - 1 , . NotSet , . AllowSideEffects | . AllowCalls ) ;
headListViewItem . mWatchEntry . mIsNewExpression = true ;
//IDEApp.sApp.OutputLine(val);
if ( val . StartsWith ( "!" , StringComparison . Ordinal ) )
{
String errorString = scope String ( ) ;
errorString . Append ( val , 1 ) ;
var errorVals = scope List < StringView > ( errorString . Split ( '\t' ) ) ;
if ( errorVals . Count = = 3 )
{
int32 errorStart = int32 . Parse ( scope String ( errorVals [ 0 ] ) ) ;
int32 errorEnd = errorStart + int32 . Parse ( scope String ( errorVals [ 1 ] ) ) . Get ( ) ;
if ( errorEnd > evalStr . Length )
errorEnd = ( int32 ) evalStr . Length ;
errorString . Set ( errorVals [ 2 ] ) ;
if ( ( errorEnd > 0 ) & & ( errorStart < evalStr . Length ) & & ( ! errorString . Contains ( ':' ) ) )
{
String appendStr = scope String ( ) ;
appendStr . Append ( evalStr , errorStart , errorEnd - errorStart ) ;
errorString . Append ( ": " , appendStr ) ;
}
}
IDEApp . sApp . Fail ( errorString ) ;
}
IDEApp . sApp . mMemoryPanel . MarkViewDirty ( ) ;
gApp . MarkWatchesDirty ( ) ;
}
editWidget . RemoveSelf ( ) ;
BFApp . sApp . DeferDelete ( editWidget ) ;
mEditWidget = null ;
2024-03-03 06:29:47 -05:00
if ( mWidgetWindow ? . mFocusWidget = = null )
2019-08-23 11:56:54 -07:00
SetFocus ( ) ;
if ( ( mHasFocus ) & & ( ! removedItem ) )
listViewItem . GetSubItem ( 0 ) . Focused = true ;
}
public void EditListViewItem ( WatchListViewItem listViewItem )
{
if ( mEditWidget ! = null )
return ;
if ( ( listViewItem . mColumnIdx = = 0 ) & & ( mIsAuto ) )
return ;
if ( ( listViewItem . mColumnIdx = = 0 ) & & ( listViewItem . mParentItem . mParentItem ! = null ) )
return ;
//mListView.UpdateContentPosition();
mListView . UpdateListSize ( ) ;
var headListViewItem = ( WatchListViewItem ) listViewItem . GetSubItem ( 0 ) ;
if ( ( listViewItem . mColumnIdx > 0 ) & & ( headListViewItem . mWatchEntry ! = null ) & & ( ! headListViewItem . mWatchEntry . mCanEdit ) )
{
if ( headListViewItem . mActionButton ! = null )
headListViewItem . mActionButton . mOnMouseDown ( null ) ;
return ;
}
mCancelingEdit = false ;
ExpressionEditWidget editWidget = new ExpressionEditWidget ( ) ;
mEditWidget = editWidget ;
String editVal = listViewItem . mLabel ;
if ( ( listViewItem . mColumnIdx > 0 ) & & ( headListViewItem . mWatchEntry . mEditInitialize ! = null ) )
editVal = headListViewItem . mWatchEntry . mEditInitialize ;
editWidget . mExpectingType = headListViewItem . mWatchEntry . mResultTypeStr ;
editWidget . SetText ( editVal ) ;
editWidget . Content . SelectAll ( ) ;
editWidget . Content . ClearUndoData ( ) ;
float x ;
float y ;
listViewItem . SelfToOtherTranslate ( mListView , 0 , 0 , out x , out y ) ;
mEditingItem = ( WatchListViewItem ) listViewItem ;
bool isEmpty = ( mEditingItem . mWatchEntry ! = null ) & & ( mEditingItem . mWatchEntry . mEvalStr . IsEmpty ) ;
float width ;
if ( isEmpty )
{
x = GS ! ( 4 ) ;
width = mListView . mScrollContentContainer . mWidth - GS ! ( 8 ) ;
}
else
{
x = listViewItem . LabelX - GS ! ( 4 ) ;
width = listViewItem . LabelWidth + GS ! ( 6 ) ;
if ( listViewItem . mColumnIdx = = mListView . mColumns . Count - 1 )
width = mListView . mWidth - x - GS ! ( 20 ) ;
else
width = Math . Min ( width , mListView . mWidth - x - GS ! ( 20 ) ) ;
}
//editWidget.Resize(x - GS!(1), y - GS!(3), width, GS!(28));
editWidget . ResizeAround ( x , y , width ) ;
mListView . AddWidget ( editWidget ) ;
editWidget . mOnLostFocus . Add ( new = > HandleEditLostFocus ) ;
editWidget . mOnSubmit . Add ( new = > HandleRenameSubmit ) ;
editWidget . mOnCancel . Add ( new = > HandleRenameCancel ) ;
editWidget . mOnKeyDown . Add ( new = > HandleEditKeyDown ) ;
WidgetWindow . sOnMouseWheel . Add ( new = > HandleMouseWheel ) ;
editWidget . SetFocus ( ) ;
}
void HandleMouseWheel ( MouseEvent evt )
{
HandleEditLostFocus ( mEditWidget ) ;
}
void ValueClicked ( ListViewItem item , float x , float y , int32 btnNum )
{
if ( ( btnNum = = 1 ) & & ( ! mDisabled ) )
{
DarkListViewItem widget = ( DarkListViewItem ) item ;
float clickX = x ;
2022-05-18 13:23:10 -07:00
float clickY = Math . Max ( y + GS ! ( 2 ) , GS ! ( 19 ) ) ;
2019-08-23 11:56:54 -07:00
widget . SelfToOtherTranslate ( mListView . GetRoot ( ) , clickX , clickY , var aX , var aY ) ;
ShowRightClickMenu ( mListView , aX , aY ) ;
}
}
void ListViewItemMouseDown ( WatchListViewItem clickedItem , int32 btnCount )
{
if ( mDisabled )
return ;
WatchListViewItem item = ( WatchListViewItem ) clickedItem . GetSubItem ( 0 ) ;
mListView . GetRoot ( ) . SelectItem ( item , true ) ;
SetFocus ( ) ;
if ( ( mIsAuto ) & & ( clickedItem . mColumnIdx = = 0 ) )
return ;
if ( clickedItem . mColumnIdx > 1 )
return ;
if ( clickedItem . mColumnIdx > 0 )
{
if ( item . mDisabled )
return ;
}
if ( ( btnCount > 1 ) | |
( ( clickedItem . mLabel . Length = = 0 ) & & ( clickedItem . mColumnIdx = = 0 ) ) )
EditListViewItem ( clickedItem ) ;
}
void ValueMouseDown ( ListViewItem item , float x , float y , int32 btnNum , int32 btnCount )
{
WatchListViewItem clickedItem = ( WatchListViewItem ) item ;
if ( btnNum = = 0 )
ListViewItemMouseDown ( clickedItem , btnCount ) ;
else
2019-09-28 12:15:36 -07:00
{
if ( ! clickedItem . GetSubItem ( 0 ) . Selected )
ListViewItemMouseDown ( clickedItem , 1 ) ;
}
2019-08-23 11:56:54 -07:00
}
void ClearWatchValues ( ListViewItem parentListViewItem )
{
if ( parentListViewItem . mParentItem ! = null )
{
var watch = ( ( WatchListViewItem ) parentListViewItem ) . mWatchEntry ;
watch . mHasValue = false ;
if ( mHadStep )
watch . mHadStepCount + + ;
if ( mClearHadStep )
watch . mHadStepCount = 0 ;
}
if ( parentListViewItem . mChildItems ! = null )
{
for ( var listViewItem in parentListViewItem . mChildItems )
{
ClearWatchValues ( listViewItem ) ;
}
}
}
2022-06-01 12:28:04 -07:00
static void RemoveCustomContent ( WatchListViewItem listViewItem )
{
var dataItem = listViewItem . GetSubItem ( 1 ) as WatchListViewItem ;
var typeItem = listViewItem . GetSubItem ( 2 ) as WatchListViewItem ;
var listView = listViewItem . mListView as WatchListView ;
if ( dataItem . mCustomContentWidget ! = null )
{
dataItem . mCustomContentWidget . RemoveSelf ( ) ;
DeleteAndNullify ! ( dataItem . mCustomContentWidget ) ;
listView . mListSizeDirty = true ;
listViewItem . mSelfHeight = listView . mFont . GetLineSpacing ( ) ;
}
if ( typeItem . mCustomContentWidget ! = null )
{
typeItem . mCustomContentWidget . RemoveSelf ( ) ;
DeleteAndNullify ! ( typeItem . mCustomContentWidget ) ;
}
}
2019-08-23 11:56:54 -07:00
void IWatchOwner . UpdateWatch ( WatchListViewItem listViewItem )
{
if ( mDisabled )
return ;
bool isTopLevel = listViewItem . mParentItem = = mListView . GetRoot ( ) ;
listViewItem . mErrorStart = 0 ;
listViewItem . mErrorEnd = 0 ;
var watch = listViewItem . mWatchEntry ;
2022-05-18 13:23:10 -07:00
bool doProfile = false ; //watch.mResultType.HasFlag(.Text);
ProfileInstance pi = default ;
if ( doProfile )
pi = Profiler . StartSampling ( "UpdateWatch" ) . GetValueOrDefault ( ) ;
defer
{
if ( pi . HasValue )
pi . Dispose ( ) ;
}
2019-08-23 11:56:54 -07:00
bool wasNewExpression = watch . mIsNewExpression ;
String val = scope String ( ) ;
if ( watch . mIsPending )
{
IDEApp . sApp . mDebugger . EvaluateContinue ( val ) ;
}
else if ( watch . mEvalStr . Length > 0 )
{
2024-12-31 13:17:53 -08:00
if ( ! gApp . mDebugger . IsPaused ( ) )
{
// Keep waiting
return ;
}
2022-05-21 11:58:01 -07:00
String evalStr = scope String ( 1024 ) ;
if ( watch . mStackFrameId ! = null )
{
evalStr . Append ( "{" ) ;
evalStr . Append ( watch . mStackFrameId ) ;
evalStr . Append ( "}" ) ;
}
evalStr . Append ( watch . mEvalStr ) ;
2019-08-23 11:56:54 -07:00
if ( ( watch . mReferenceId ! = null ) & & ( watch . mReferenceId . StartsWith ( "0" , StringComparison . Ordinal ) ) )
evalStr . Append ( ",refid=" , watch . mReferenceId ) ;
//gApp.DebugEvaluate(watch.mResultTypeStr, evalStr, val, -1, watch.mIsNewExpression, watch.mIsNewExpression);
//TODO: Why did we have the mResultTypeStr in there?
2022-05-18 13:23:10 -07:00
DebugManager . EvalExpressionFlags flags = . AllowStringView ;
2019-08-23 11:56:54 -07:00
if ( watch . mIsNewExpression )
flags | = . AllowSideEffects | . AllowCalls ;
2024-12-31 13:17:53 -08:00
2019-08-23 11:56:54 -07:00
gApp . DebugEvaluate ( null , evalStr , val , - 1 , watch . mLanguage , flags ) ;
watch . mIsNewExpression = false ;
}
watch . mIsPending = false ;
2022-05-18 13:23:10 -07:00
DeleteAndNullify ! ( watch . mStringView ) ;
2019-08-23 11:56:54 -07:00
2022-05-18 13:23:10 -07:00
StringView valSV = val ;
2019-08-23 11:56:54 -07:00
2022-05-18 13:23:10 -07:00
var vals = scope List < StringView > ( valSV . Split ( '\n' ) ) ;
2019-08-23 11:56:54 -07:00
var valueSubItem = ( WatchListViewItem ) listViewItem . GetSubItem ( 1 ) ;
if ( vals [ 0 ] . StartsWith ( "!" , StringComparison . Ordinal ) )
{
if ( ( vals [ 0 ] = = "!pending" ) | | ( vals [ 0 ] = = "!Not paused" ) )
{
watch . mIsPending = true ;
return ;
}
var errStr = scope String ( vals [ 0 ] ) ;
errStr . Remove ( 0 ) ;
2020-06-15 09:01:49 -07:00
bool hadSideEffects = vals [ 0 ] = = "!sideeffects" ;
bool hadPropertyEval = vals [ 0 ] = = "!property" ;
2019-08-23 11:56:54 -07:00
if ( ( ! wasNewExpression ) & & ( isTopLevel ) )
{
2020-06-15 09:01:49 -07:00
if ( ( ( ! valueSubItem . mFailed ) & & ( watch . mHadValue ) ) | | ( hadSideEffects ) | | ( hadPropertyEval ) )
2019-08-23 11:56:54 -07:00
{
watch . mHasValue = true ;
2024-12-31 13:17:53 -08:00
if ( ( hadSideEffects ) & & ( watch . AutoRefresh ) )
{
if ( watch . mDebuggerStateIdx ! = gApp . mDebugger . mStateIdx )
listViewItem . RefreshWatch ( ) ;
return ;
}
2019-08-23 11:56:54 -07:00
listViewItem . SetDisabled ( true , hadSideEffects ) ;
return ;
}
}
listViewItem . SetDisabled ( false , false ) ;
var errorVals = scope List < StringView > ( errStr . Split ( '\t' ) ) ;
if ( errorVals . Count > 1 )
{
listViewItem . mErrorStart = int32 . Parse ( scope String ( errorVals [ 0 ] ) ) ;
listViewItem . mErrorEnd = listViewItem . mErrorStart + int32 . Parse ( scope String ( errorVals [ 1 ] ) ) . Get ( ) ;
valueSubItem . Label = errorVals [ 2 ] ;
2022-05-21 11:58:01 -07:00
if ( watch . mStackFrameId ! = null )
{
int32 idPrefixLen = ( . ) watch . mStackFrameId . Length + 2 ;
listViewItem . mErrorStart - = idPrefixLen ;
listViewItem . mErrorEnd - = idPrefixLen ;
}
2019-08-23 11:56:54 -07:00
}
else
valueSubItem . Label = errorVals [ 0 ] ;
valueSubItem . mFailed = true ;
watch . mHadStepCount = 0 ;
}
else
{
listViewItem . SetDisabled ( false , false ) ;
2022-05-18 13:23:10 -07:00
StringView newVal = vals [ 0 ] ;
2019-08-23 11:56:54 -07:00
if ( watch . mHadStepCount = = 1 )
valueSubItem . mValueChanged = ( newVal ! = valueSubItem . mLabel ) | | ( valueSubItem . mFailed ) ;
else if ( watch . mHadStepCount > 1 )
valueSubItem . mValueChanged = false ;
watch . mHadStepCount = 0 ;
valueSubItem . Label = newVal ;
valueSubItem . mFailed = false ;
}
2024-03-25 06:18:50 -04:00
listViewItem . mLastFindIdx = - 1 ;
valueSubItem . mLastFindIdx = - 1 ;
2019-08-23 11:56:54 -07:00
var typeSubItem = ( WatchListViewItem ) listViewItem . GetSubItem ( 2 ) ;
if ( vals . Count > 1 )
{
String . NewOrSet ! ( watch . mResultTypeStr , vals [ 1 ] ) ;
typeSubItem . Label = vals [ 1 ] ;
}
else
{
DeleteAndNullify ! ( watch . mResultTypeStr ) ;
typeSubItem . Label = "" ;
}
int cmdStringCount = Math . Max ( 0 , vals . Count - 2 ) ;
int memberCount = 0 ;
watch . mMemoryBreakpointAddr = 0 ;
watch . mResultType = WatchResultType . Value ;
watch . mIsDeleted = false ;
watch . mIsAppendAlloc = false ;
watch . mIsStackAlloc = false ;
2022-05-21 11:58:01 -07:00
watch . mUsedLock = false ;
watch . mCurStackIdx = - 1 ;
2024-12-31 13:17:53 -08:00
watch . mDebuggerStateIdx = gApp . mDebugger . mStateIdx ;
2019-08-23 11:56:54 -07:00
watch . mLanguage = . NotSet ;
DeleteAndNullify ! ( watch . mEditInitialize ) ;
DeleteAndNullify ! ( watch . mAction ) ;
2022-05-23 08:48:55 -07:00
DeleteAndNullify ! ( watch . mAddrValueExpr ) ;
DeleteAndNullify ! ( watch . mPointeeExpr ) ;
2019-08-23 11:56:54 -07:00
watch . mCanEdit = false ;
watch . mAction = null ;
if ( listViewItem . mActionButton ! = null )
{
Widget . RemoveAndDelete ( listViewItem . mActionButton ) ;
listViewItem . mActionButton = null ;
}
WatchSeriesInfo watchSeriesInfo = null ;
for ( int32 memberIdx = 0 ; memberIdx < cmdStringCount ; memberIdx + + )
{
var memberVals = scope List < StringView > ( vals [ memberIdx + 2 ] . Split ( '\t' ) ) ;
var memberVals0 = scope String ( memberVals [ 0 ] ) ;
if ( memberVals0 . StartsWith ( ":" ) )
{
if ( memberVals0 = = ":canEdit" )
{
watch . mCanEdit = true ;
if ( memberVals . Count > 1 )
String . NewOrSet ! ( watch . mEditInitialize , scope String ( memberVals [ 1 ] ) ) ;
}
if ( memberVals0 = = ":editVal" )
{
String . NewOrSet ! ( watch . mEditInitialize , scope String ( memberVals [ 1 ] ) ) ;
}
else if ( memberVals0 = = ":break" )
{
watch . mMemoryBreakpointAddr = ( int ) Int64 . Parse ( memberVals [ 1 ] , . HexNumber ) ;
}
else if ( memberVals0 = = ":sideeffects" )
{
listViewItem . AddRefreshButton ( ) ;
IDEApp . sApp . RefreshWatches ( ) ;
CheckClearDirtyWatches ( ) ;
watch . mHasValue = true ;
}
else if ( memberVals0 = = ":referenceId" )
{
String . NewOrSet ! ( watch . mReferenceId , scope String ( memberVals [ 1 ] ) ) ;
}
else if ( memberVals0 = = ":repeat" )
{
2019-12-09 10:28:56 -08:00
int startIdx = Int . Parse ( scope String ( memberVals [ 1 ] ) ) ;
int count = Int . Parse ( scope String ( memberVals [ 2 ] ) ) ;
int maxShow = Int . Parse ( scope String ( memberVals [ 3 ] ) ) ;
2019-08-23 11:56:54 -07:00
String displayStr = scope String ( memberVals [ 4 ] ) ;
String evalStr = scope String ( memberVals [ 5 ] ) ;
if ( count = = 0 )
continue ;
Object [ ] formatParams = scope Object [ 1 + memberVals . Count - 6 ] ;
formatParams [ 0 ] = startIdx ;
for ( int32 i = 6 ; i < memberVals . Count ; i + + )
formatParams [ 1 + i - 6 ] = scope : : String ( memberVals [ i ] ) ;
watchSeriesInfo = new WatchSeriesInfo ( ) ;
watchSeriesInfo . mStartMemberIdx = ( int32 ) memberCount ;
watchSeriesInfo . mDisplayTemplate = new String ( displayStr ) ;
watchSeriesInfo . mEvalTemplate = new String ( evalStr ) ;
watchSeriesInfo . mStartIdx = startIdx ;
watchSeriesInfo . mCount = count ;
2019-12-09 10:28:56 -08:00
watchSeriesInfo . mShowPageSize = ( int32 ) maxShow ;
2019-08-23 11:56:54 -07:00
watchSeriesInfo . mShowPages = 1 ;
WatchListViewItem memberItem ;
if ( memberCount > = listViewItem . GetChildCount ( ) )
memberItem = AddWatch ( "" , "" , listViewItem ) ;
else
{
memberItem = ( WatchListViewItem ) listViewItem . GetChildAtIndex ( memberCount ) ;
if ( memberItem . mWatchSeriesInfo ! = null )
{
var prevWatchSeriesInfo = memberItem . mWatchSeriesInfo ;
watchSeriesInfo . mShowPages = prevWatchSeriesInfo . mShowPages ;
watchSeriesInfo . mMoreButton = prevWatchSeriesInfo . mMoreButton ;
watchSeriesInfo . mLessButton = prevWatchSeriesInfo . mLessButton ;
// Only keep the series ID if it's the same display and evaluation -
// This keeps expanded items expanded when single stepping, but will cause them to refresh and close
// when we are actually evaluating a different value with the same name in a different context
if ( ( prevWatchSeriesInfo . mEvalTemplate = = watchSeriesInfo . mEvalTemplate ) & & ( prevWatchSeriesInfo . mDisplayTemplate = = watchSeriesInfo . mDisplayTemplate ) )
2019-10-09 16:18:11 -07:00
watchSeriesInfo . mSeriesFirstVersion = prevWatchSeriesInfo . mSeriesFirstVersion ;
2019-08-23 11:56:54 -07:00
memberItem . mWatchSeriesInfo . ReleaseRef ( ) ;
}
}
memberItem . mWatchSeriesInfo = watchSeriesInfo ;
//memberItem.mOwnsWatchSeriesInfo = true;
memberItem . mSeriesMemberIdx = 0 ;
memberCount + + ;
var memberWatch = ( ( WatchListViewItem ) memberItem ) . mWatchEntry ;
var formattedName = scope String ( ) ;
formattedName . AppendF ( displayStr , params formatParams ) ;
String . NewOrSet ! ( memberWatch . mName , formattedName ) ;
var formattedEval = scope String ( ) ;
formattedEval . AppendF ( evalStr , params formatParams ) ;
String . NewOrSet ! ( memberWatch . mEvalStr , formattedEval ) ;
memberItem . Label = memberWatch . mName ;
if ( wasNewExpression )
{
while ( memberCount < listViewItem . GetChildCount ( ) )
{
WatchListViewItem checkMemberItem = ( WatchListViewItem ) listViewItem . GetChildAtIndex ( memberCount ) ;
if ( checkMemberItem . mWatchSeriesInfo = = null )
break ;
listViewItem . RemoveChildItemAt ( memberCount ) ;
}
}
else
{
while ( memberCount < listViewItem . GetChildCount ( ) )
{
WatchListViewItem checkMemberItem = ( WatchListViewItem ) listViewItem . GetChildAtIndex ( memberCount ) ;
if ( checkMemberItem . mWatchSeriesInfo = = null )
break ;
checkMemberItem . mWatchSeriesInfo . ReleaseRef ( ) ;
watchSeriesInfo . AddRef ( ) ;
checkMemberItem . mWatchSeriesInfo = watchSeriesInfo ;
memberCount + + ;
}
}
2019-11-07 06:53:32 -08:00
// We update here to avoid doing a Draw with old series information (such as addresses)
memberItem . mMustUpdateBeforeEvaluate = true ;
2019-08-23 11:56:54 -07:00
}
else if ( memberVals0 = = ":addrs" )
{
2022-06-27 15:21:30 -07:00
if ( memberCount > 0 )
{
WatchListViewItem memberItem = ( WatchListViewItem ) listViewItem . GetChildAtIndex ( memberCount - 1 ) ;
String . NewOrSet ! ( memberItem . mWatchSeriesInfo . mAddrs , memberVals [ 1 ] ) ;
memberItem . mWatchSeriesInfo . mAddrsEntrySize = 1 ;
}
2019-08-23 11:56:54 -07:00
}
else if ( memberVals0 = = ":addrsEntrySize" )
{
2022-06-27 15:21:30 -07:00
if ( memberCount > 0 )
{
int32 addrsEntrySize = int32 . Parse ( scope String ( memberVals [ 1 ] ) ) ;
WatchListViewItem memberItem = ( WatchListViewItem ) listViewItem . GetChildAtIndex ( memberCount - 1 ) ;
memberItem . mWatchSeriesInfo . mAddrsEntrySize = addrsEntrySize ;
}
2019-08-23 11:56:54 -07:00
}
else if ( memberVals0 = = ":continuation" )
{
2022-06-27 15:21:30 -07:00
if ( memberCount > 0 )
{
WatchListViewItem memberItem = ( WatchListViewItem ) listViewItem . GetChildAtIndex ( memberCount - 1 ) ;
String . NewOrSet ! ( memberItem . mWatchSeriesInfo . mContinuationData , memberVals [ 1 ] ) ;
}
2019-08-23 11:56:54 -07:00
}
else if ( memberVals0 = = ":action" )
{
watch . mAction = new String ( memberVals [ 1 ] ) ;
listViewItem . AddActionButton ( ) ;
}
else if ( memberVals0 = = ":language" )
{
int32 language ;
if ( int32 . Parse ( memberVals [ 1 ] ) case . Ok ( out language ) )
{
watch . mLanguage = ( . ) language ;
}
}
else if ( memberVals0 = = ":warn" )
{
if ( wasNewExpression )
{
gApp . ShowOutput ( ) ;
gApp . OutputLineSmart ( "WARNING: {0}" , memberVals [ 1 ] ) ;
}
}
2022-05-18 13:23:10 -07:00
else if ( memberVals0 = = ":stringView" )
{
watch . mResultType | = . Text ;
if ( memberVals . Count > 1 )
watch . mStringView = memberVals [ 1 ] . Unescape ( . . new . ( ) ) ;
}
2022-05-21 11:58:01 -07:00
else if ( memberVals0 = = ":usedLock" )
{
watch . mUsedLock = true ;
}
else if ( memberVals0 = = ":stackIdx" )
{
if ( int32 stackIdx = int32 . Parse ( memberVals [ 1 ] ) )
watch . mCurStackIdx = stackIdx ;
}
2022-05-23 08:48:55 -07:00
else if ( memberVals0 = = ":addrValueExpr" )
{
watch . mAddrValueExpr = new . ( memberVals [ 1 ] ) ;
}
else if ( memberVals0 = = ":pointeeExpr" )
{
watch . mPointeeExpr = new . ( memberVals [ 1 ] ) ;
}
2019-08-23 11:56:54 -07:00
else
watch . ParseCmd ( memberVals ) ;
continue ;
}
if ( memberVals . Count > = 2 )
2019-09-28 12:15:36 -07:00
{
2019-08-23 11:56:54 -07:00
WatchListViewItem memberItem ;
if ( memberCount > = listViewItem . GetChildCount ( ) )
{
memberItem = ( WatchListViewItem ) AddWatch ( "" , "" , listViewItem ) ;
}
else
memberItem = ( WatchListViewItem ) listViewItem . GetChildAtIndex ( memberCount ) ;
var memberWatch = ( ( WatchListViewItem ) memberItem ) . mWatchEntry ;
memberWatch . mLanguage = watch . mLanguage ;
memberItem . mBottomPadding = 0 ;
if ( memberItem . mWatchSeriesInfo ! = null )
{
//if (memberItem.mSeriesMemberIdx == 0)
//delete memberItem.mWatchSeriesInfo;
//memberItem.mOwnsWatchSeriesInfo = false;
memberItem . mWatchSeriesInfo . ReleaseRef ( ) ;
memberItem . mWatchSeriesInfo = null ;
memberItem . mSeriesMemberIdx = 0 ;
}
String . NewOrSet ! ( memberWatch . mName , memberVals0 ) ;
String evalStr = scope String ( ) ;
if ( evalStr . AppendF ( scope String ( memberVals [ 1 ] ) , watch . mEvalStr ) case . Err )
{
evalStr . Clear ( ) ;
evalStr . Append ( "Format Error: {0}" , scope String ( memberVals [ 1 ] ) ) ;
}
String . NewOrSet ! ( memberWatch . mEvalStr , evalStr ) ;
memberItem . Label = memberWatch . mName ;
memberCount + + ;
}
}
2022-05-21 11:58:01 -07:00
if ( watch . mWantsStackFrameId )
{
watch . mWantsStackFrameId = false ;
watch . mStackFrameId = gApp . mDebugger . GetStackFrameId ( ( watch . mCurStackIdx ! = - 1 ) ? watch . mCurStackIdx : gApp . mDebugger . mActiveCallStackIdx , . . new . ( ) ) ;
2022-05-23 08:48:55 -07:00
if ( ( gApp . mDebugger . mActiveCallStackIdx ! = watch . mCurStackIdx ) & & ( watch . mCurStackIdx ! = - 1 ) )
2022-05-21 11:58:01 -07:00
watch . mUsedLock = true ;
}
2019-08-23 11:56:54 -07:00
if ( ( watch . mReferenceId = = null ) & & ( watch . mEvalStr . Length > 0 ) & & ( ! valueSubItem . mFailed ) )
{
// Allocate a referenceId if we didn't get one (was a temporary expression)
// Make it start with a zero so it parses but is easy to identify as not-an-identifier
watch . mReferenceId = new String ( ) ;
watch . mReferenceId . AppendF ( "0{0}" , + + WatchListView . sCurDynReferenceId ) ;
}
while ( listViewItem . GetChildCount ( ) > memberCount )
listViewItem . RemoveChildItem ( listViewItem . GetChildAtIndex ( memberCount ) ) ;
if ( ( listViewItem . GetChildCount ( ) = = 0 ) & & ( listViewItem . mOpenButton ! = null ) )
{
Widget . RemoveAndDelete ( listViewItem . mOpenButton ) ;
listViewItem . mOpenButton = null ;
DeleteAndNullify ! ( listViewItem . mChildItems ) ;
}
if ( watch . mEvalStr . Length = = 0 )
watch . mResultType = WatchResultType . None ;
2022-05-18 13:23:10 -07:00
var dataItem = listViewItem . GetSubItem ( 1 ) as WatchListViewItem ;
var typeItem = listViewItem . GetSubItem ( 2 ) as WatchListViewItem ;
if ( watch . mStringView ! = null )
{
dataItem . Label = "" ;
if ( var watchStringEdit = dataItem . mCustomContentWidget as WatchStringEdit )
{
watchStringEdit . UpdateString ( watch . mStringView ) ;
}
else if ( dataItem . mCustomContentWidget = = null )
{
dataItem . mCustomContentWidget = new WatchStringEdit ( watch . mStringView , watch . mEvalStr , true ) ;
dataItem . AddWidget ( dataItem . mCustomContentWidget ) ;
listViewItem . mSelfHeight = GS ! ( 80 ) ;
mListView . mListSizeDirty = true ;
typeItem . mCustomContentWidget = new ResizeHandleWidget ( ) ;
typeItem . mCustomContentWidget . Resize ( 0 , 0 , GS ! ( 20 ) , GS ! ( 20 ) ) ;
typeItem . AddWidget ( typeItem . mCustomContentWidget ) ;
}
}
else
{
2022-06-01 12:28:04 -07:00
RemoveCustomContent ( listViewItem ) ;
2022-05-18 13:23:10 -07:00
}
2019-08-23 11:56:54 -07:00
watch . mHasValue = true ;
watch . mHadValue = true ;
}
public override void AddedToParent ( )
{
base . AddedToParent ( ) ;
if ( mDisabled )
mDisabledTicks = 9999 ;
}
public void CheckClearDirtyWatches ( )
{
var debugger = IDEApp . sApp . mDebugger ;
if ( ( mWatchesDirty ) & & ( debugger . mIsRunning ) & & ( debugger . IsPaused ( ) ) )
{
MarkDirty ( ) ;
ClearWatchValues ( mListView . GetRoot ( ) ) ;
mWatchesDirty = false ;
mHadStep = false ;
mClearHadStep = false ;
if ( mIsAuto )
{
var parentItem = mListView . GetRoot ( ) ;
var app = IDEApp . sApp ;
String autosStr = scope String ( ) ;
app . mDebugger . GetAutoLocals ( app . IsInDisassemblyMode ( ) , autosStr ) ;
var autos = scope List < StringView > ( autosStr . Split ( '\n' ) ) ;
int32 curIdx ;
for ( curIdx = 0 ; curIdx < autos . Count ; curIdx + + )
{
String auto = scope String ( autos [ curIdx ] ) ;
if ( auto . IsEmpty )
continue ;
bool found = false ;
while ( curIdx < parentItem . GetChildCount ( ) )
{
var listViewItem = parentItem . GetChildAtIndex ( curIdx ) ;
if ( listViewItem . mLabel = = auto )
{
found = true ;
break ;
}
parentItem . RemoveChildItemAt ( curIdx ) ;
}
if ( ! found )
{
var listViewItem = AddWatch ( auto ) ;
var itemAtIdx = parentItem . GetChildAtIndex ( curIdx ) ;
if ( itemAtIdx ! = listViewItem )
{
// Wrong order
parentItem . RemoveChildItem ( listViewItem ) ;
parentItem . InsertChild ( listViewItem , itemAtIdx ) ;
}
}
}
while ( curIdx < mListView . GetRoot ( ) . GetChildCount ( ) )
parentItem . RemoveChildItemAt ( curIdx ) ;
}
}
}
public override void Update ( )
{
base . Update ( ) ;
if ( mDisabled )
mDisabledTicks + + ;
int childCount = mListView . GetRoot ( ) . GetChildCount ( ) ;
if ( ( ! mIsAuto ) & & ( ( childCount = = 0 ) | | ( mListView . GetRoot ( ) . GetChildAtIndex ( childCount - 1 ) . mLabel . Length > 0 ) ) )
AddWatch ( "" ) ;
CheckClearDirtyWatches ( ) ;
2024-03-26 07:30:54 -04:00
2024-04-27 07:24:36 -04:00
if ( ( mDeselectOnFocusLost ) & & ( ! HasFocus ) & & ( mListView . mFindWidget = = null ) & & ( ! gApp . MenuHasFocus ) )
2024-03-26 07:30:54 -04:00
mListView . GetRoot ( ) . SelectItemExclusively ( null ) ;
//mListView.m
2019-08-23 11:56:54 -07:00
}
public static void AddSelectableMenuItem ( Menu menu , String label , bool selected , Action action )
{
Debug . AssertNotStack ( action ) ;
Menu menuItem = menu . AddItem ( label ) ;
if ( selected )
menuItem . mIconImage = DarkTheme . sDarkTheme . GetImage ( . Check ) ;
menuItem . mOnMenuItemSelected . Add ( new ( imenu ) = > action ( ) ~ { delete action ; } ) ;
}
2022-05-18 13:23:10 -07:00
public static void SetDisplayType ( String referenceId , String formatStr , DebugManager . IntDisplayType intDisplayType , DebugManager . MmDisplayType mmDisplayType , DebugManager . FloatDisplayType floatDisplayType )
2019-08-23 11:56:54 -07:00
{
2022-05-18 13:23:10 -07:00
gApp . mDebugger . SetDisplayTypes ( referenceId , ( formatStr = = null ) ? null : formatStr , intDisplayType , mmDisplayType , floatDisplayType ) ;
2020-06-19 06:42:52 -07:00
gApp . RefreshWatches ( ) ;
2019-08-23 11:56:54 -07:00
}
2022-06-01 12:28:04 -07:00
public static bool AddDisplayTypeMenu ( String label , WatchListView listView , Menu menu , WatchResultType watchResultType , String referenceId , bool includeDefault )
2019-08-23 11:56:54 -07:00
{
2022-05-18 13:23:10 -07:00
bool hasInt = watchResultType . HasFlag ( . Int ) ;
bool hasFloat = watchResultType . HasFlag ( . Float ) ;
bool hasMM128 = watchResultType . HasFlag ( . MM128 ) ;
bool hasText = watchResultType . HasFlag ( . Text ) & & ( referenceId ! = null ) & & ( ! referenceId . EndsWith ( ".[]" ) ) ;
bool canSetFormat = hasInt | | hasFloat | | hasMM128 | | hasText ;
2019-08-23 11:56:54 -07:00
var debugger = IDEApp . sApp . mDebugger ;
2022-05-18 13:23:10 -07:00
String formatStr = scope . ( ) ;
bool foundSpecific = debugger . GetDisplayTypes ( referenceId , formatStr , var intDisplayType , var mmDisplayType , var floatDisplayType ) ;
2019-08-23 11:56:54 -07:00
if ( ( referenceId ! = null ) & & ( ! foundSpecific ) )
{
2020-06-19 06:42:52 -07:00
intDisplayType = . Default ;
mmDisplayType = . Default ;
floatDisplayType = . Default ;
2019-08-23 11:56:54 -07:00
}
if ( ! canSetFormat )
return false ;
2022-05-18 13:23:10 -07:00
var referenceId ;
if ( referenceId ! = null )
{
referenceId = new String ( referenceId ) ;
menu . mOnMenuClosed . Add ( new ( menu , itemSelected ) = >
{
gApp . DeferDelete ( referenceId ) ;
} ) ;
}
Menu parentItem = menu . AddItem ( label ) ;
if ( hasText )
{
AddSelectableMenuItem ( parentItem , "Default" , formatStr . IsEmpty ,
2022-06-01 12:28:04 -07:00
new ( ) = >
{
listView . GetRoot ( ) . WithSelectedItems ( scope ( item ) = >
{
var watchListViewItem = item as WatchListViewItem ;
RemoveCustomContent ( watchListViewItem ) ;
} ) ;
SetDisplayType ( referenceId , "" , intDisplayType , mmDisplayType , floatDisplayType ) ;
} ) ;
2022-05-18 13:23:10 -07:00
AddSelectableMenuItem ( parentItem , "String" , formatStr = = "str" ,
new ( ) = > SetDisplayType ( referenceId , "str" , intDisplayType , mmDisplayType , floatDisplayType ) ) ;
}
2019-12-24 13:13:04 -08:00
if ( hasInt )
2019-08-23 11:56:54 -07:00
{
for ( DebugManager . IntDisplayType i = default ; i < DebugManager . IntDisplayType . COUNT ; i + + )
{
if ( ( i = = 0 ) & & ( ! includeDefault ) )
{
if ( intDisplayType = = 0 )
intDisplayType = DebugManager . IntDisplayType . Decimal ;
continue ;
}
var toType = i ;
AddSelectableMenuItem ( parentItem , ToStackString ! ( i ) , intDisplayType = = i ,
2022-05-18 13:23:10 -07:00
new ( ) = > SetDisplayType ( referenceId , null , toType , mmDisplayType , floatDisplayType ) ) ;
2019-08-23 11:56:54 -07:00
}
}
2019-12-24 13:13:04 -08:00
2020-06-19 06:42:52 -07:00
if ( hasFloat )
{
for ( DebugManager . FloatDisplayType i = default ; i < DebugManager . FloatDisplayType . COUNT ; i + + )
{
if ( ( i = = 0 ) & & ( ! includeDefault ) )
{
if ( floatDisplayType = = 0 )
floatDisplayType = DebugManager . FloatDisplayType . Minimal ;
continue ;
}
var toType = i ;
AddSelectableMenuItem ( parentItem , ToStackString ! ( i ) , floatDisplayType = = i ,
2022-05-18 13:23:10 -07:00
new ( ) = > SetDisplayType ( referenceId , null , intDisplayType , mmDisplayType , toType ) ) ;
2020-06-19 06:42:52 -07:00
}
}
2019-12-24 13:13:04 -08:00
if ( hasMM128 )
{
2019-08-23 11:56:54 -07:00
for ( DebugManager . MmDisplayType i = default ; i < DebugManager . MmDisplayType . COUNT ; i + + )
{
var toType = i ;
AddSelectableMenuItem ( parentItem , ToStackString ! ( i ) , mmDisplayType = = i ,
2022-05-18 13:23:10 -07:00
new ( ) = > SetDisplayType ( referenceId , null , intDisplayType , toType , floatDisplayType ) ) ;
2019-08-23 11:56:54 -07:00
}
}
return true ;
}
2022-05-23 08:48:55 -07:00
protected static void WithSelectedWatchEntries ( WatchListView listView , delegate void ( WatchEntry watchEntry ) dlg )
2022-05-21 11:58:01 -07:00
{
listView . GetRoot ( ) . WithSelectedItems ( scope ( item ) = >
{
var watchListViewItem = item as WatchListViewItem ;
if ( watchListViewItem . mWatchEntry ! = null )
dlg ( watchListViewItem . mWatchEntry ) ;
} ) ;
}
2019-08-23 11:56:54 -07:00
public static void ShowRightClickMenu ( WatchPanel watchPanel , WatchListView listView , WatchListViewItem listViewItem , float x , float y )
{
if ( watchPanel ! = null )
{
watchPanel . mDeselectOnFocusLost = false ;
defer : : { watchPanel . mDeselectOnFocusLost = true ; }
}
Menu menu = new Menu ( ) ;
Menu anItem ;
if ( listViewItem ! = null )
{
2019-09-27 13:03:47 -07:00
var clickedHoverItem = listViewItem . GetSubItem ( 0 ) as HoverWatch . HoverListViewItem ;
2019-08-23 11:56:54 -07:00
var watchEntry = listViewItem . mWatchEntry ;
2022-05-23 08:48:55 -07:00
2022-06-01 12:28:04 -07:00
AddDisplayTypeMenu ( "Default Display" , listView , menu , listViewItem . mWatchEntry . mResultType , null , false ) ;
2019-08-23 11:56:54 -07:00
//Debug.WriteLine(String.Format("RefType: {0}", watchEntry.mReferenceId));
if ( menu . mItems . Count > 0 )
anItem = menu . AddItem ( ) ;
if ( watchEntry . mReferenceId ! = null )
2022-05-18 13:23:10 -07:00
{
2022-06-01 12:28:04 -07:00
AddDisplayTypeMenu ( "Watch Display" , listView , menu , listViewItem . mWatchEntry . mResultType , watchEntry . mReferenceId , true ) ;
2019-08-23 11:56:54 -07:00
2022-05-18 13:23:10 -07:00
int arrayPos = watchEntry . mReferenceId . IndexOf ( ".[]$" ) ;
if ( arrayPos ! = - 1 )
{
var refId = scope String ( watchEntry . mReferenceId , 0 , arrayPos + 3 ) ;
2022-06-01 12:28:04 -07:00
AddDisplayTypeMenu ( "Series Watch Display" , listView , menu , listViewItem . mWatchEntry . mResultType , refId , true ) ;
2022-05-18 13:23:10 -07:00
}
}
2022-05-21 11:58:01 -07:00
var lockMenu = menu . AddItem ( "Lock" ) ;
var lockUnlockedItem = lockMenu . AddItem ( "Unlocked" ) ;
lockUnlockedItem . mOnMenuItemSelected . Add ( new ( menu ) = >
{
WithSelectedWatchEntries ( listView , scope ( selectedWatchEntry ) = >
{
DeleteAndNullify ! ( selectedWatchEntry . mStackFrameId ) ;
} ) ;
gApp . RefreshWatches ( ) ;
} ) ;
var lockNewItem = lockMenu . AddItem ( "Current Stack Frame" ) ;
lockNewItem . mOnMenuItemSelected . Add ( new ( menu ) = >
{
WithSelectedWatchEntries ( listView , scope ( selectedWatchEntry ) = >
{
int32 callStackIdx = gApp . mDebugger . mActiveCallStackIdx ;
if ( selectedWatchEntry . mCurStackIdx ! = - 1 )
callStackIdx = selectedWatchEntry . mCurStackIdx ;
DeleteAndNullify ! ( selectedWatchEntry . mStackFrameId ) ;
selectedWatchEntry . mWantsStackFrameId = true ;
} ) ;
gApp . RefreshWatches ( ) ;
} ) ;
if ( watchEntry . mStackFrameId ! = null )
{
var lockCurItem = lockMenu . AddItem ( watchEntry . mStackFrameId ) ;
lockCurItem . mIconImage = DarkTheme . sDarkTheme . GetImage ( . Check ) ;
int lastColon = watchEntry . mStackFrameId . LastIndexOf ( ':' ) ;
if ( ( lastColon > - 1 ) & & ( var addr = int64 . Parse ( watchEntry . mStackFrameId . Substring ( lastColon + 1 ) , . HexNumber ) ) )
{
lockCurItem . mTooltip = gApp . mDebugger . GetAddressSymbolName ( addr , true , . . new . ( ) ) ;
if ( lockCurItem . mTooltip . IsEmpty )
DeleteAndNullify ! ( lockCurItem . mTooltip ) ;
}
String stackFrameId = new String ( watchEntry . mStackFrameId ) ;
lockCurItem . mOnMenuItemSelected . Add ( new ( menu ) = >
{
WithSelectedWatchEntries ( listView , scope ( selectedWatchEntry ) = >
{
DeleteAndNullify ! ( selectedWatchEntry . mStackFrameId ) ;
selectedWatchEntry . mStackFrameId = new . ( stackFrameId ) ;
} ) ;
gApp . RefreshWatches ( ) ;
}
~ delete stackFrameId ) ;
}
else
{
lockUnlockedItem . mIconImage = DarkTheme . sDarkTheme . GetImage ( . Check ) ;
}
2022-05-18 13:23:10 -07:00
2022-01-07 10:36:21 -05:00
anItem = menu . AddItem ( "Add Watch" ) ;
2022-05-23 08:48:55 -07:00
var addWatchNew = anItem . AddItem ( "Duplicate" ) ;
addWatchNew . mOnMenuItemSelected . Add ( new ( menu ) = >
2022-01-07 10:36:21 -05:00
{
2022-05-23 08:48:55 -07:00
List < String > pendingEvalStrs = scope . ( ) ;
listView . GetRoot ( ) . WithSelectedItems ( scope ( item ) = >
{
var watchListViewItem = item as WatchListViewItem ;
if ( watchListViewItem . mWatchEntry ! = null )
{
if ( watchListViewItem . mParentItem ! = listView . GetRoot ( ) )
{
String compactEvalStr = new String ( ) ;
CompactChildExpression ( watchListViewItem , compactEvalStr ) ;
pendingEvalStrs . Add ( compactEvalStr ) ;
}
else
{
pendingEvalStrs . Add ( new . ( watchEntry . mEvalStr ) ) ;
}
}
} ) ;
for ( var str in pendingEvalStrs )
{
gApp . AddWatch ( str ) ;
delete str ;
}
2022-01-07 10:36:21 -05:00
} ) ;
2022-05-23 08:48:55 -07:00
String pointeeExpr = null ;
String addrValueExpr = null ;
WithSelectedWatchEntries ( listView , scope [ & ] ( selectedWatchEntry ) = >
{
if ( selectedWatchEntry . mPointeeExpr ! = null )
{
if ( pointeeExpr ! = null )
pointeeExpr = "" ;
else
pointeeExpr = selectedWatchEntry . mPointeeExpr ;
}
if ( selectedWatchEntry . mAddrValueExpr ! = null )
{
if ( addrValueExpr ! = null )
addrValueExpr = "" ;
else
addrValueExpr = selectedWatchEntry . mAddrValueExpr ;
}
} ) ;
if ( pointeeExpr ! = null )
{
var addWatchPointee = anItem . AddItem ( scope $"Pointee Address {pointeeExpr}" ) ;
addWatchPointee . mOnMenuItemSelected . Add ( new ( menu ) = >
{
WithSelectedWatchEntries ( listView , scope ( selectedWatchEntry ) = >
{
if ( selectedWatchEntry . mPointeeExpr ! = null )
gApp . AddWatch ( selectedWatchEntry . mPointeeExpr ) ;
} ) ;
} ) ;
if ( addrValueExpr ! = null )
{
var addWatchPointer = anItem . AddItem ( scope $"Pointer Address {addrValueExpr}" ) ;
addWatchPointer . mOnMenuItemSelected . Add ( new ( menu ) = >
{
WithSelectedWatchEntries ( listView , scope ( selectedWatchEntry ) = >
{
if ( selectedWatchEntry . mAddrValueExpr ! = null )
gApp . AddWatch ( selectedWatchEntry . mAddrValueExpr ) ;
} ) ;
} ) ;
}
}
else if ( addrValueExpr ! = null )
{
var addValuePointer = anItem . AddItem ( scope $"Value Address {addrValueExpr}" ) ;
addValuePointer . mOnMenuItemSelected . Add ( new ( menu ) = >
{
WithSelectedWatchEntries ( listView , scope ( selectedWatchEntry ) = >
{
if ( selectedWatchEntry . mAddrValueExpr ! = null )
gApp . AddWatch ( selectedWatchEntry . mAddrValueExpr ) ;
} ) ;
} ) ;
}
2019-12-24 13:13:04 -08:00
if ( ! watchEntry . IsConstant )
2019-08-23 11:56:54 -07:00
{
2019-12-24 13:13:04 -08:00
anItem = menu . AddItem ( "Break When Value Changes" ) ;
if ( watchEntry . mMemoryBreakpointAddr = = 0 )
{
anItem . mOnMenuItemSelected . Add ( new ( evt ) = >
{
String evalStr = scope String ( ) ;
CompactChildExpression ( listViewItem , evalStr ) ;
2022-05-23 08:48:55 -07:00
int valStart = 0 ;
2024-03-22 15:11:40 -04:00
if ( ( evalStr . StartsWith ( "@Beef:" ) ) | | ( evalStr . StartsWith ( "@C:" ) ) )
valStart = evalStr . IndexOf ( ':' ) + 1 ;
2022-05-23 08:48:55 -07:00
if ( evalStr . StartsWith ( '{' ) )
{
int endPos = evalStr . IndexOf ( '}' ) ;
valStart = endPos + 1 ;
while ( ( valStart < evalStr . Length ) & & ( evalStr [ valStart ] . IsWhiteSpace ) )
valStart + + ;
}
if ( ( valStart < evalStr . Length ) & & ( evalStr [ valStart ] = = '*' ) )
evalStr . Remove ( valStart , 1 ) ;
2021-12-21 08:58:37 -05:00
else
2022-05-23 08:48:55 -07:00
evalStr . Insert ( valStart , "&" ) ;
2024-03-22 15:11:40 -04:00
2019-12-24 13:13:04 -08:00
gApp . mBreakpointPanel . CreateMemoryBreakpoint ( evalStr ) ;
gApp . MarkDirty ( ) ;
} ) ;
}
else
{
anItem . mIconImage = DarkTheme . sDarkTheme . GetImage ( . Check ) ;
anItem . mOnMenuItemSelected . Add ( new ( evt ) = >
2019-08-23 11:56:54 -07:00
{
2019-12-24 13:13:04 -08:00
for ( int breakIdx < gApp . mDebugger . mBreakpointList . Count )
2019-08-23 11:56:54 -07:00
{
2019-12-24 13:13:04 -08:00
let breakpoint = gApp . mDebugger . mBreakpointList [ breakIdx ] ;
if ( breakpoint . mMemoryAddress = = watchEntry . mMemoryBreakpointAddr )
{
gApp . mDebugger . DeleteBreakpoint ( breakpoint ) ;
gApp . RefreshWatches ( ) ;
breakIdx - - ;
}
2019-08-23 11:56:54 -07:00
}
2019-12-24 13:13:04 -08:00
} ) ;
2019-12-05 06:49:23 -08:00
2019-12-24 13:13:04 -08:00
let configItem = menu . AddItem ( "Configure Breakpoint" ) ;
configItem . mOnMenuItemSelected . Add ( new ( evt ) = >
2019-12-05 06:49:23 -08:00
{
2019-12-24 13:13:04 -08:00
for ( int breakIdx < gApp . mDebugger . mBreakpointList . Count )
2019-12-05 06:49:23 -08:00
{
2019-12-24 13:13:04 -08:00
let breakpoint = gApp . mDebugger . mBreakpointList [ breakIdx ] ;
if ( breakpoint . mMemoryAddress = = watchEntry . mMemoryBreakpointAddr )
{
ConditionDialog dialog = new ConditionDialog ( ) ;
dialog . Init ( breakpoint ) ;
dialog . PopupWindow ( listView . mWidgetWindow ) ;
}
2019-12-05 06:49:23 -08:00
}
2019-12-24 13:13:04 -08:00
} ) ;
}
2019-08-23 11:56:54 -07:00
}
2020-01-18 14:43:05 -08:00
if ( watchEntry . mResultType . HasFlag ( . Pointer ) )
2019-08-23 11:56:54 -07:00
{
2024-11-20 11:32:56 -05:00
if ( int . Parse ( watchEntry . mPointer ? ? watchEntry . mEditInitialize , . AllowHexSpecifier ) case . Ok ( let addr ) )
2019-08-23 11:56:54 -07:00
{
int threadId ;
gApp . mDebugger . GetStackAllocInfo ( addr , out threadId , null ) ;
if ( threadId ! = 0 )
{
anItem = menu . AddItem ( "Find on Stack" ) ;
anItem . mOnMenuItemSelected . Add ( new ( evt ) = >
{
int stackIdx = - 1 ;
gApp . mDebugger . GetStackAllocInfo ( addr , let threadId , & stackIdx ) ;
if ( stackIdx ! = - 1 )
{
gApp . ShowCallstack ( ) ;
gApp . mCallStackPanel . SelectCallStackIdx ( stackIdx ) ;
}
else if ( threadId ! = 0 )
{
gApp . ShowThreads ( ) ;
gApp . mThreadPanel . SelectThreadId ( threadId ) ;
}
} ) ;
}
}
}
2020-05-08 07:10:35 -07:00
void WithSelected ( delegate void ( ListViewItem ) func )
2019-09-27 13:03:47 -07:00
{
var root = listView . GetRoot ( ) ;
2019-09-28 12:15:36 -07:00
root . WithSelectedItems ( func , false , true ) ;
2019-09-27 13:03:47 -07:00
if ( clickedHoverItem ! = null )
func ( clickedHoverItem ) ;
}
2019-08-23 11:56:54 -07:00
anItem = menu . AddItem ( "Copy Value" ) ;
anItem . mOnMenuItemSelected . Add ( new ( evt ) = >
{
String selectedText = scope String ( ) ;
2019-09-27 13:03:47 -07:00
WithSelected ( scope ( listViewItem ) = >
2019-08-23 11:56:54 -07:00
{
if ( ! selectedText . IsEmpty )
{
selectedText . Append ( "\n" ) ;
}
var subItem = listViewItem . GetSubItem ( 1 ) ;
selectedText . Append ( subItem . Label ) ;
} ) ;
gApp . SetClipboardText ( selectedText ) ;
} ) ;
anItem = menu . AddItem ( "Copy Expression" ) ;
anItem . mOnMenuItemSelected . Add ( new ( evt ) = >
{
String selectedText = scope String ( ) ;
2019-09-27 13:03:47 -07:00
WithSelected ( scope ( listViewItem ) = >
2019-08-23 11:56:54 -07:00
{
String evalStr = scope String ( ) ;
CompactChildExpression ( ( WatchListViewItem ) listViewItem , evalStr ) ;
if ( ! selectedText . IsEmpty )
{
selectedText . Append ( "\n" ) ;
}
selectedText . Append ( evalStr ) ;
} ) ;
gApp . SetClipboardText ( selectedText ) ;
} ) ;
if ( watchPanel ! = null )
{
anItem = menu . AddItem ( "Delete Watch" ) ;
anItem . mOnMenuItemSelected . Add ( new ( evt ) = >
{
watchPanel . DeleteSelectedItems ( ) ;
} ) ;
}
}
if ( menu . mItems . IsEmpty )
{
delete menu ;
return ;
}
MenuWidget menuWidget = ThemeFactory . mDefault . CreateMenuWidget ( menu ) ;
menuWidget . Init ( listView . GetRoot ( ) , x , y ) ;
}
protected override void ShowRightClickMenu ( Widget relWidget , float x , float y )
{
var focusedItem = ( WatchListViewItem ) mListView . GetRoot ( ) . FindFocusedItem ( ) ;
ShowRightClickMenu ( this , mListView , focusedItem , x , y ) ;
}
void ListViewClicked ( MouseEvent theEvent )
{
if ( ( theEvent . mBtn = = 1 ) & & ( ! mDisabled ) )
{
float aX , aY ;
aX = theEvent . mX + mListView . GetRoot ( ) . mX ;
aY = theEvent . mY + mListView . GetRoot ( ) . mY ;
ShowRightClickMenu ( mListView , aX , aY ) ;
}
}
void ListViewMouseDown ( MouseEvent theEvent )
{
mListView . GetRoot ( ) . SelectItemExclusively ( null ) ;
}
public override void KeyChar ( char32 theChar )
{
base . KeyChar ( theChar ) ;
if ( ( mDisabled ) | | ( theChar < ( char8 ) 32 ) )
return ;
var selectedItem = ( WatchListViewItem ) mListView . GetRoot ( ) . FindFirstSelectedItem ( ) ;
if ( selectedItem ! = null )
{
ListViewItemMouseDown ( selectedItem , 2 ) ;
if ( mEditWidget ! = null )
mEditWidget . KeyChar ( theChar ) ;
}
}
void DeleteSelectedItems ( )
{
var root = mListView . GetRoot ( ) ;
List < ListViewItem > selectedItems = scope List < ListViewItem > ( ) ;
root . WithSelectedItems ( scope ( listViewItem ) = >
{
selectedItems . Add ( listViewItem ) ;
} ) ;
// Go through in reverse, to process children before their parents
for ( int itemIdx = selectedItems . Count - 1 ; itemIdx > = 0 ; itemIdx - - )
{
var selectedItem = selectedItems [ itemIdx ] ;
if ( ( selectedItem ! = null ) & & ( selectedItem . mLabel . Length > 0 ) & & ( selectedItem . mParentItem = = root ) )
{
2019-12-21 05:48:44 -08:00
int idx = root . mChildItems . IndexOf ( selectedItem ) ;
2019-08-23 11:56:54 -07:00
root . RemoveChildItem ( selectedItem ) ;
if ( idx < root . mChildItems . Count )
root . SelectItemExclusively ( root . mChildItems [ idx ] ) ;
}
}
}
public void TryRenameItem ( )
{
if ( mEditWidget ! = null )
{
if ( mEditingItem . mColumnIdx = = 0 )
{
let valueItem = ( WatchListViewItem ) mEditingItem . GetSubItem ( 1 ) ;
EditEvent evt = scope . ( ) ;
evt . mSender = mEditWidget ;
HandleRenameCancel ( evt ) ;
EditListViewItem ( valueItem ) ;
}
return ;
}
var focusedItem = mListView . GetRoot ( ) . FindFocusedItem ( ) ;
if ( focusedItem ! = null )
{
EditListViewItem ( ( WatchListViewItem ) focusedItem ) ;
if ( mEditWidget = = null )
{
EditListViewItem ( ( WatchListViewItem ) focusedItem . GetSubItem ( 1 ) ) ;
}
}
}
public override void KeyDown ( KeyCode keyCode , bool isRepeat )
{
if ( keyCode = = . Apps )
{
ShowRightClickMenu ( mListView ) ;
return ;
}
base . KeyDown ( keyCode , isRepeat ) ;
mListView . KeyDown ( keyCode , isRepeat ) ;
if ( ! mIsAuto )
{
if ( keyCode = = KeyCode . F2 )
{
TryRenameItem ( ) ;
}
if ( keyCode = = KeyCode . Delete )
{
DeleteSelectedItems ( ) ;
}
}
}
}
}