diff --git a/DesktopApp/XojoInstruments.xojo_project b/DesktopApp/XojoInstruments.xojo_project index b46184a..9975417 100644 --- a/DesktopApp/XojoInstruments.xojo_project +++ b/DesktopApp/XojoInstruments.xojo_project @@ -21,6 +21,9 @@ Class=XIArray;../XojoInstruments/XojoInstruments/Framework/XIArray.xojo_code;&h0 Class=XIIterator;../XojoInstruments/XojoInstruments/Framework/XIIterator.xojo_code;&h000000004AFAE7FF;&h0000000025A657FF;false Class=SnapshotDelta;../XojoInstruments/XojoInstruments/SnapshotDelta.xojo_code;&h000000007FC35FFF;&h000000005D00D7FF;false Class=XINamedTemporaryFile;../XojoInstruments/XojoInstruments/Framework/XINamedTemporaryFile.xojo_code;&h00000000793B87FF;&h0000000025A657FF;false +Class=InstrumentsLocalSession;../XojoInstruments/XojoInstruments/InstrumentsLocalSession.xojo_code;&h000000006382E7FF;&h000000005D00D7FF;false +Class=InstrumentsSession;../XojoInstruments/XojoInstruments/InstrumentsSession.xojo_code;&h000000004917A7FF;&h000000005D00D7FF;false +Class=XIDate;../XojoInstruments/XojoInstruments/Framework/XIDate.xojo_code;&h000000004A93E7FF;&h0000000025A657FF;false MajorVersion=#XojoInstruments.MajorVersion MinorVersion=#XojoInstruments.MinorVersion SubVersion=#XojoInstruments.BugVersion diff --git a/XojoInstruments/XojoInstruments.xojo_code b/XojoInstruments/XojoInstruments.xojo_code index a0712db..c5f95b7 100644 --- a/XojoInstruments/XojoInstruments.xojo_code +++ b/XojoInstruments/XojoInstruments.xojo_code @@ -2,24 +2,37 @@ Protected Module XojoInstruments #tag Method, Flags = &h1 Protected Sub Start() + StartGUI() + End Sub + #tag EndMethod + + #tag Method, Flags = &h1 + Protected Sub StartGUI() #if TargetDesktop Static desktopGUI As XojoInstrumentsDesktopGUI If desktopGUI = Nil Then - // Take a snapshot to register Introspection-related things to system object list. - Dim snap As New Snapshot(True) - #Pragma Unused snap + If mLocalSession = Nil Then + mLocalSession = New InstrumentsLocalSession() + End If // Create a window. - desktopGUI = New XojoInstrumentsDesktopGUI() + desktopGUI = New XojoInstrumentsDesktopGUI(mLocalSession) End If desktopGUI.Show() + #else + // Local mode is only supported for Desktop apps. + Raise New PlatformNotSupportedException() #endif End Sub #tag EndMethod + #tag Property, Flags = &h21 + Private mLocalSession As InstrumentsLocalSession + #tag EndProperty + #tag ComputedProperty, Flags = &h1 #tag Getter Get diff --git a/XojoInstruments/XojoInstruments/Framework/XIDate.xojo_code b/XojoInstruments/XojoInstruments/Framework/XIDate.xojo_code new file mode 100644 index 0000000..484991f --- /dev/null +++ b/XojoInstruments/XojoInstruments/Framework/XIDate.xojo_code @@ -0,0 +1,6 @@ +#tag Class +Protected Class XIDate +Inherits Date +Implements XojoInstruments.Framework.XIObject +End Class +#tag EndClass diff --git a/XojoInstruments/XojoInstruments/InstrumentsLocalSession.xojo_code b/XojoInstruments/XojoInstruments/InstrumentsLocalSession.xojo_code new file mode 100644 index 0000000..09c7ae0 --- /dev/null +++ b/XojoInstruments/XojoInstruments/InstrumentsLocalSession.xojo_code @@ -0,0 +1,469 @@ +#tag Class +Protected Class InstrumentsLocalSession +Inherits InstrumentsSession +Implements XojoInstruments.Framework.XIObject + #tag Method, Flags = &h0 + Function Capture(createGraph As Boolean) As Snapshot + #pragma BackgroundTasks False + + mLastSnapshotID = mLastSnapshotID + 1 + Dim snap As New Snapshot(mLastSnapshotID) + Dim snapTimestamp As New XIDate() + + Dim objectRefIDs As XIArrayInteger = snap.ObjectRefIDs + Dim objectRefGraph As XIDictionary = If(createGraph, New XIDictionary(), Nil) + + // Collect all objects. + // The loop block only exists to limit the scope of the iterator. + Do + Dim iter As Runtime.ObjectIterator = Runtime.IterateObjects() + While iter.MoveNext() + Dim obj As Object = iter.Current + If (obj IsA XIObject) Or (obj Is iter) Then Continue + + Dim oref As ObjectRef = Me.ObjectRefFor(obj) + If mSystemObjectRefIDs.HasKey(oref.ID) Then Continue + + objectRefIDs.Append(oref.ID) + If createGraph Then + objectRefGraph.Value(oref.ID) = GetReferringObjectRefs(oref) + End If + Wend + Loop Until True + objectRefIDs.Sort() + + // Collect all system objects created during the iteration + // (e.g., introspection cache in Xojo framework); they should be + // ignored when taking a next snapshot. + While True + Dim iter2 As Runtime.ObjectIterator = Runtime.IterateObjects() + Dim secondPass As New XIArrayInteger() + While iter2.MoveNext() + Dim obj As Object = iter2.Current + If (obj IsA XIObject) Or (obj Is iter2) Then Continue + + Dim oref As ObjectRef = Me.ObjectRefFor(obj) + If mSystemObjectRefIDs.HasKey(oref.ID) Then Continue + + secondPass.Append(oref.ID) + Wend + secondPass.Sort() + + // Compute delta + Dim addedObjectRefIDs As XIArrayInteger = Snapshot.ComputeDelta(objectRefIDs, secondPass).Added + For Each id As Integer In addedObjectRefIDs + mSystemObjectRefIDs.Value(id) = True + Next + If addedObjectRefIDs.Ubound() = -1 Then Exit + Wend + + // Remove WeakRefs no longer in use. + Me.GarbageCollect() + + // Set Snapshot + snap.ID = mSnapshots.Count + snap.Timestamp = snapTimestamp + snap.ObjectRefIDs = objectRefIDs + snap.ObjectRefGraph = objectRefGraph + mSnapshots.Value(snap.ID) = snap + + Return snap + End Function + #tag EndMethod + + #tag Method, Flags = &h0 + Sub Constructor() + Super.Constructor() + + mSnapshots = New XIDictionary() + mObjectRefMap = New XIDictionary() + mSystemObjectRefIDs = New XIDictionary() + + // Take an initial snapshot. + Call Me.Capture(False) + End Sub + #tag EndMethod + + #tag Method, Flags = &h0 + Sub GarbageCollect() + #pragma BackgroundTasks False + + For Each classAndDict As Xojo.Core.DictionaryEntry In Me.mObjectRefMap + Dim idToOref As XIDictionary = classAndDict.Value + For Each idAndOref As Xojo.Core.DictionaryEntry In idToOref + // Getting the value removes dead weakrefs. + Call ObjectRef(idAndOref.Value).Value() + Next + Next + End Sub + #tag EndMethod + + #tag Method, Flags = &h21 + Private Shared Function GenerateHint(obj As Object) As String + // Generate hint string for the object. + + // Note: as hints will not be updated, we should avoid using mutable values + // as much as possible. + + #if TargetDesktop + Select Case obj + Case IsA Control + Dim ctrl As Control = Control(obj) + Return ctrl.Name + _ + If(ctrl.Window <> Nil, " [" + Xojo.Introspection.GetType(ctrl.Window).Name + "]", " (no window)") + + Case IsA MenuItem + Return MenuItem(obj).Name + + End Select + #endif + + Select Case obj + Case IsA Picture + Return Str(Picture(obj).Width) + " x " + Str(Picture(obj).Height) + + Case IsA Graphics + Return Str(Graphics(obj).Width) + " x " + Str(Graphics(obj).Height) + + Case IsA Pair + Dim p As Pair = Pair(obj) + Dim leftType, rightType As Xojo.Introspection.TypeInfo + + leftType = Xojo.Introspection.GetType(p.Left) + rightType = Xojo.Introspection.GetType(p.Right) + + Return If(leftType = Nil, "Nil", leftType.FullName) + " : " + If(rightType = Nil, "Nil", rightType.FullName) + + Case IsA WeakRef + Dim target As Object = WeakRef(obj).Value + Return If(target <> Nil, Xojo.Introspection.GetType(target).FullName, "(unknown)") + + Case IsA Thread + Return Thread(obj).DebugIdentifier // mutable value + + // TODO support more classes + End Select + + Return "" + End Function + #tag EndMethod + + #tag Method, Flags = &h21 + Private Function GetReferringObjectRefs(oref As ObjectRef) As XojoInstruments.Framework.XIDictionary + // Finds all objects directly referenced by the specified oref, as possible as we can. + + #pragma BackgroundTasks False + + Using Xojo.Introspection + + Dim refs As New XIDictionary() + Dim obj As Variant = oref.Value() + + If obj = Nil Then Return refs + + If obj.IsArray() Then + Select Case obj.ArrayElementType + Case Variant.TypeDate, Variant.TypeObject + // Currently only 1-D array is supported. + Dim arr() As Variant = obj + For i As Integer = arr.Ubound() DownTo 0 + GetReferringObjectRefsRegister(arr(i), "[" + Str(i) + "]", refs) + Next + + Case Else + // Array of Array is not allowed in Xojo. + 'Case Variant.TypeArray + + // Not interested in value types. + 'Case Variant.TypeBoolean + 'Case Variant.TypeCFStringRef + 'Case Variant.TypeColor + 'Case Variant.TypeCString + 'Case Variant.TypeCurrency + 'Case Variant.TypeDouble + 'Case Variant.TypeInt32 + 'Case Variant.TypeInt64 + 'Case Variant.TypeNil + 'Case Variant.TypeOSType + 'Case Variant.TypePString + 'Case Variant.TypeSingle + 'Case Variant.TypeString + 'Case Variant.TypeStructure + 'Case Variant.TypeText + 'Case Variant.TypeWindowPtr + 'Case Variant.TypeWString + + End Select + + Else + Dim ti As TypeInfo = GetType(obj) + + // Collect properties. This includes shared properties, but + // excludes computed properties. + For Each prop As PropertyInfo In ti.Properties() + If Not prop.IsComputed() Then + Dim name As String = If(prop.IsShared(), "(shared) ", "") + prop.Name + GetReferringObjectRefsRegister(prop.Value(obj), name, refs) + End If + Next + + // Handle special classes. + + #if TargetDesktop + Select Case obj + Case IsA Window + Dim win As Window = obj + // Note: non-control window items cannot be reached. + For i As Integer = win.ControlCount - 1 DownTo 0 + Dim ctrl As Control = win.Control(i) + GetReferringObjectRefsRegister(ctrl, ctrl.Name, refs) + Next + + Case IsA MenuItem + Dim m As MenuItem = obj + For i As Integer = m.Count() - 1 DownTo 0 + Dim child As MenuItem = m.Item(i) + GetReferringObjectRefsRegister(child, "[" + Str(i) + "]", refs) + Next + + Case IsA SegmentedControl + Dim sc As SegmentedControl = obj + For i As Integer = sc.Items.UBound() DownTo 0 + GetReferringObjectRefsRegister(sc.Items(i), "Item[" + Str(i) + "]", refs) + Next + + End Select + #endif + + Select Case obj + Case IsA Dictionary + Dim dict As Dictionary = Dictionary(obj) + For i As Integer = dict.Count() - 1 DownTo 0 + Dim key As Variant = dict.Key(i) + GetReferringObjectRefsRegister(key, "Key[" + Str(i) + "]", refs) + GetReferringObjectRefsRegister(dict.Value(key), "Value[" + Str(i) + "]", refs) + Next + + Case IsA Xojo.Core.Dictionary + Dim dict As Xojo.Core.Dictionary = Xojo.Core.Dictionary(obj) + Dim i As Integer = 0 + For Each ent As Xojo.Core.DictionaryEntry In dict + GetReferringObjectRefsRegister(ent.Key, "Key[" + Str(i) + "]", refs) + GetReferringObjectRefsRegister(ent.Value, "Value[" + Str(i) + "]", refs) + i = i + 1 + Next + + End Select + End If + + // TODO support more classes like Collection + + Return refs + End Function + #tag EndMethod + + #tag Method, Flags = &h21 + Private Sub GetReferringObjectRefsRegister(v As Variant, key As String, dict As XIDictionary) + If v = Nil or v IsA XIObject Then Return + + Dim ti As Xojo.Introspection.TypeInfo = Xojo.Introspection.GetType(v) + + // `ti` will become Nil if the variant is an instance of + // the Xojo framework private class, e.g., `_Profile.Profile`. + If ti = Nil Or ti.IsValueType Then Return + + // Translate Array into Object. + If ti.IsArray() Then + v = v.ObjectValue + End If + + // Register. + dict.Value(key) = Me.ObjectRefFor(v).ID + End Sub + #tag EndMethod + + #tag Method, Flags = &h0 + Function InspectObject(id As Integer) As Boolean + // Returns True when successfully inspected (i.e., object is still alive). + // Returns False if the object has already been garbage collected. + // Raises UnsupportedOperationException when not in Debug Run. + + #if Not DebugBuild + Raise New UnsupportedOperationException() + #endif + + Dim oref As ObjectRef = ObjectRefByID(ID) + If oref = Nil Then + // No such ObjectRef. This should not happen. + Break + Return False + End If + + Dim obj As Object = oref.Value + If obj = Nil Then Return False // Object has been garbage collected. + + If Xojo.Introspection.GetType(obj).FullName = "Delegate" Then + Inspect_Delegate_in_IDE(ID, obj) + Else + Inspect_Object_in_IDE(ID, obj) + End If + + Return True + End Function + #tag EndMethod + + #tag Method, Flags = &h21 + Private Shared Sub Inspect_Delegate_in_IDE(ID As Integer, obj As Object) + // ************************************************************************** + // + // `obj` in Variables is the Delegate(s) you have selected. + // + // Click [ ▶︎ Resume ] to continue... + // + // ************************************************************************** + + #Pragma Unused ID + #Pragma Unused obj + Break + End Sub + #tag EndMethod + + #tag Method, Flags = &h21 + Private Shared Sub Inspect_Object_in_IDE(ID As Integer, obj As Auto) + // ************************************************************************** + // + // `obj` in Variables is the object(s) you have selected. + // + // Click [ ▶︎ Resume ] to continue... + // + // ************************************************************************** + + #Pragma Unused ID + #Pragma Unused obj + Break + End Sub + #tag EndMethod + + #tag Method, Flags = &h0 + Function ObjectRefByID(id As Integer) As ObjectRef + // Get ObjectRef of the given ID. + // Returns Nil when not found. + + #pragma BackgroundTasks False + + For Each classAndDict As Xojo.Core.DictionaryEntry In Me.mObjectRefMap + Dim idToOref As XIDictionary = classAndDict.Value + If idToOref.HasKey(id) Then + Return idToOref.Value(id) + End If + Next + + Return Nil + End Function + #tag EndMethod + + #tag Method, Flags = &h0 + Function ObjectRefFor(obj As Object) As ObjectRef + // Get ObjectRef for the given object. + // Assign a new one when the corresponding ObjectRef has never been created yet. + + #pragma BackgroundTasks False + + Dim className As String = Xojo.Introspection.GetType(obj).FullName + Dim idToOref As XIDictionary = Me.mObjectRefMap.Lookup(className, Nil) + If idToOref = Nil Then + idToOref = New XIDictionary() + Me.mObjectRefMap.Value(className) = idToOref + Else + // If the object already has a reference, return it. + For Each idAndOref As Xojo.Core.DictionaryEntry In idToOref + Dim oref As ObjectRef = idAndOref.Value + If oref.Value Is obj Then Return oref + Next + End If + + // Create a new object reference. + mLastObjectRefID = mLastObjectRefID + 1 + Dim oref As New ObjectRef(mLastObjectRefID, New XIWeakRef(obj), className, GenerateHint(obj)) + + // Register the object reference to the list. + idToOref.Value(oref.ID) = oref + + Return oref + End Function + #tag EndMethod + + #tag Method, Flags = &h0 + Sub RegisterSystemObject(obj As Object) + mSystemObjectRefIDs.Value(Me.ObjectRefFor(obj).ID) = True + End Sub + #tag EndMethod + + + #tag Property, Flags = &h21 + Private mLastObjectRefID As Integer = -1 + #tag EndProperty + + #tag Property, Flags = &h21 + Private mLastSnapshotID As Integer = -1 + #tag EndProperty + + #tag Property, Flags = &h21 + #tag Note + This map holds the mapping of a fully-qualified class name and a dictionary, which holds a mapping of an ID to the actual ObjectRef. + #tag EndNote + Private mObjectRefMap As XIDictionary + #tag EndProperty + + #tag Property, Flags = &h21 + #tag Note + This map holds the list of IDs of ObjectRefs that should be excluded from the snapshot. + #tag EndNote + Private mSystemObjectRefIDs As XIDictionary + #tag EndProperty + + + #tag ViewBehavior + #tag ViewProperty + Name="Name" + Visible=true + Group="ID" + InitialValue="" + Type="String" + EditorType="" + #tag EndViewProperty + #tag ViewProperty + Name="Index" + Visible=true + Group="ID" + InitialValue="-2147483648" + Type="Integer" + EditorType="" + #tag EndViewProperty + #tag ViewProperty + Name="Super" + Visible=true + Group="ID" + InitialValue="" + Type="String" + EditorType="" + #tag EndViewProperty + #tag ViewProperty + Name="Left" + Visible=true + Group="Position" + InitialValue="0" + Type="Integer" + EditorType="" + #tag EndViewProperty + #tag ViewProperty + Name="Top" + Visible=true + Group="Position" + InitialValue="0" + Type="Integer" + EditorType="" + #tag EndViewProperty + #tag EndViewBehavior +End Class +#tag EndClass diff --git a/XojoInstruments/XojoInstruments/InstrumentsSession.xojo_code b/XojoInstruments/XojoInstruments/InstrumentsSession.xojo_code new file mode 100644 index 0000000..194df51 --- /dev/null +++ b/XojoInstruments/XojoInstruments/InstrumentsSession.xojo_code @@ -0,0 +1,89 @@ +#tag Class +Protected Class InstrumentsSession +Implements XojoInstruments.Framework.XIObject + #tag Method, Flags = &h0 + Function Capture(createGraph As Boolean) As Snapshot + Raise New RuntimeException() // subclass must override + End Function + #tag EndMethod + + #tag Method, Flags = &h1 + Protected Sub Constructor() + + End Sub + #tag EndMethod + + #tag Method, Flags = &h0 + Function InspectObject(id As Integer) As Boolean + Raise New RuntimeException() // subclass must override + End Function + #tag EndMethod + + #tag Method, Flags = &h0 + Function ObjectRefByID(id As Integer) As ObjectRef + Raise New RuntimeException() // subclass must override + End Function + #tag EndMethod + + #tag Method, Flags = &h0 + Function ObjectRefFor(obj As Object) As ObjectRef + Raise New RuntimeException() // subclass must override + End Function + #tag EndMethod + + #tag Method, Flags = &h0 + Sub RegisterSystemObject(obj As Object) + Raise New RuntimeException() // subclass must override + End Sub + #tag EndMethod + + + #tag Property, Flags = &h1 + Protected mSnapshots As XIDictionary + #tag EndProperty + + + #tag ViewBehavior + #tag ViewProperty + Name="Name" + Visible=true + Group="ID" + InitialValue="" + Type="String" + EditorType="" + #tag EndViewProperty + #tag ViewProperty + Name="Index" + Visible=true + Group="ID" + InitialValue="-2147483648" + Type="Integer" + EditorType="" + #tag EndViewProperty + #tag ViewProperty + Name="Super" + Visible=true + Group="ID" + InitialValue="" + Type="String" + EditorType="" + #tag EndViewProperty + #tag ViewProperty + Name="Left" + Visible=true + Group="Position" + InitialValue="0" + Type="Integer" + EditorType="" + #tag EndViewProperty + #tag ViewProperty + Name="Top" + Visible=true + Group="Position" + InitialValue="0" + Type="Integer" + EditorType="" + #tag EndViewProperty + #tag EndViewBehavior +End Class +#tag EndClass diff --git a/XojoInstruments/XojoInstruments/ObjectRef.xojo_code b/XojoInstruments/XojoInstruments/ObjectRef.xojo_code index 3162d00..bea429f 100644 --- a/XojoInstruments/XojoInstruments/ObjectRef.xojo_code +++ b/XojoInstruments/XojoInstruments/ObjectRef.xojo_code @@ -1,275 +1,49 @@ #tag Class Protected Class ObjectRef Implements XojoInstruments.Framework.XIObject - #tag Method, Flags = &h21 - Private Sub Constructor() - Static LastID As Integer = -1 - LastID = LastID + 1 - mID = LastID - End Sub - #tag EndMethod - - #tag Method, Flags = &h0 - Shared Sub GarbageCollect() - // Remove dead WeakRefs. - - #pragma BackgroundTasks False - - If ObjectRefMap = Nil Then Return - - For Each classAndDict As Xojo.Core.DictionaryEntry In ObjectRefMap - Dim idToOref As XIDictionary = classAndDict.Value - For Each idAndOref As Xojo.Core.DictionaryEntry In idToOref - Dim oref As ObjectRef = idAndOref.Value - If oref.mReference <> Nil And oref.mReference.Value() = Nil Then - oref.mReference = Nil - End If - Next - Next - End Sub - #tag EndMethod - - #tag Method, Flags = &h21 - Private Shared Function GenerateHint(obj As Object) As String - // Generate hint string for the object. - - // Note: as hints will not be updated, we should avoid using mutable values - // as much as possible. - - #if TargetDesktop - Select Case obj - Case IsA Control - Dim ctrl As Control = Control(obj) - Return ctrl.Name + _ - If(ctrl.Window <> Nil, " [" + Xojo.Introspection.GetType(ctrl.Window).Name + "]", " (no window)") - - Case IsA MenuItem - Return MenuItem(obj).Name - - End Select - #endif - - Select Case obj - Case IsA Picture - Return Str(Picture(obj).Width) + " x " + Str(Picture(obj).Height) - - Case IsA Graphics - Return Str(Graphics(obj).Width) + " x " + Str(Graphics(obj).Height) - - Case IsA Pair - Dim p As Pair = Pair(obj) - Dim leftType, rightType As Xojo.Introspection.TypeInfo - - leftType = Xojo.Introspection.GetType(p.Left) - rightType = Xojo.Introspection.GetType(p.Right) - - Return If(leftType = Nil, "Nil", leftType.FullName) + " : " + If(rightType = Nil, "Nil", rightType.FullName) - - Case IsA WeakRef - Dim target As Object = WeakRef(obj).Value - Return If(target <> Nil, Xojo.Introspection.GetType(target).FullName, "(unknown)") - - Case IsA Thread - Return Thread(obj).DebugIdentifier // mutable value - - // TODO support more classes - End Select - - Return "" - End Function - #tag EndMethod - #tag Method, Flags = &h0 - Shared Sub InspectInIDE(ID As Integer, obj As Object) - If Not DebugBuild Or obj = Nil Then Return - - If Xojo.Introspection.GetType(obj).FullName = "Delegate" Then - Inspect_Delegate_in_IDE(ID, obj) - Else - Inspect_Object_in_IDE(ID, obj) - End If - End Sub - #tag EndMethod - - #tag Method, Flags = &h21 - Private Shared Sub Inspect_Delegate_in_IDE(ID As Integer, obj As Object) - // ************************************************************************** - // - // `obj` in Variables is the Delegate(s) you have selected. - // - // Click [ ▶︎ Resume ] to continue... - // - // ************************************************************************** - - #Pragma Unused ID - #Pragma Unused obj - Break - End Sub - #tag EndMethod - - #tag Method, Flags = &h21 - Private Shared Sub Inspect_Object_in_IDE(ID As Integer, obj As Auto) - // ************************************************************************** - // - // `obj` in Variables is the object(s) you have selected. - // - // Click [ ▶︎ Resume ] to continue... - // - // ************************************************************************** - - #Pragma Unused ID - #Pragma Unused obj - Break + Sub Constructor(id As Integer, wref As XIWeakRef, className As String, hint As String) + Me.ID = id + Me.Reference = wref + Me.ClassName = className + Me.Hint = hint End Sub #tag EndMethod #tag Method, Flags = &h0 - Shared Function ReferenceByID(id As Integer) As ObjectRef - // Get ObjectRef of the given ID. - - #pragma BackgroundTasks False - - If ObjectRefMap = Nil Then Return Nil - - For Each classAndDict As Xojo.Core.DictionaryEntry In ObjectRefMap - Dim idToOref As XIDictionary = classAndDict.Value - If idToOref.HasKey(id) Then - Return idToOref.Value(id) - End If - Next - - Return Nil - End Function - #tag EndMethod - - #tag Method, Flags = &h0 - Shared Function ReferenceFor(obj As Object) As ObjectRef - // Get ObjectRef for the given object. - - #pragma BackgroundTasks False + Function Value() As Object + // Note: this getter has a side-effect for performance boost. - If ObjectRefMap = Nil Then - ObjectRefMap = New XIDictionary() - End If + Dim v As Object = Nil - Dim className As String = Xojo.Introspection.GetType(obj).FullName - Dim idToOref As XIDictionary = ObjectRefMap.Lookup(className, Nil) - If idToOref = Nil Then - idToOref = New XIDictionary() - ObjectRefMap.Value(className) = idToOref - Else - // If the object already has a reference, return it. - For Each idAndOref As Xojo.Core.DictionaryEntry In idToOref - Dim oref As ObjectRef = idAndOref.Value - If oref.mReference <> Nil And oref.mReference.Value() Is obj Then Return oref - Next + If Me.Reference <> Nil Then + v = Me.Reference.Value() + If v = Nil Then Me.Reference = Nil End If - // Create a new object reference. - Dim oref As New ObjectRef() - oref.mReference = New XIWeakRef(obj) - oref.mClassName = className - oref.mHint = GenerateHint(obj) - - // Register the object reference to the list. - idToOref.Value(oref.mID) = oref - - Return oref + Return v End Function #tag EndMethod - #tag ComputedProperty, Flags = &h0 - #tag Getter - Get - return mClassName - End Get - #tag EndGetter + #tag Property, Flags = &h0 ClassName As String - #tag EndComputedProperty - - #tag ComputedProperty, Flags = &h0 - #tag Getter - Get - return mHint - End Get - #tag EndGetter - Hint As String - #tag EndComputedProperty - - #tag ComputedProperty, Flags = &h0 - #tag Getter - Get - return mID - End Get - #tag EndGetter - ID As Integer - #tag EndComputedProperty - - #tag Property, Flags = &h21 - Private mClassName As String - #tag EndProperty - - #tag Property, Flags = &h21 - Private mHint As String #tag EndProperty - #tag Property, Flags = &h21 - Private mID As Integer + #tag Property, Flags = &h0 + Hint As String #tag EndProperty - #tag Property, Flags = &h21 - Private mReference As XIWeakRef + #tag Property, Flags = &h0 + ID As Integer = -1 #tag EndProperty - #tag Property, Flags = &h21 - Private Shared ObjectRefMap As XIDictionary + #tag Property, Flags = &h0 + Reference As XIWeakRef #tag EndProperty - #tag ComputedProperty, Flags = &h0 - #tag Getter - Get - Return If(mReference <> Nil, mReference.Value(), Nil) - End Get - #tag EndGetter - Value As Object - #tag EndComputedProperty - - #tag ComputedProperty, Flags = &h0 - #tag Getter - Get - Return Value - End Get - #tag EndGetter - ValueAsAuto As Auto - #tag EndComputedProperty - #tag ViewBehavior - #tag ViewProperty - Name="ClassName" - Visible=false - Group="Behavior" - InitialValue="" - Type="String" - EditorType="MultiLineEditor" - #tag EndViewProperty - #tag ViewProperty - Name="Hint" - Visible=false - Group="Behavior" - InitialValue="" - Type="String" - EditorType="MultiLineEditor" - #tag EndViewProperty - #tag ViewProperty - Name="ID" - Visible=false - Group="Behavior" - InitialValue="" - Type="Integer" - EditorType="" - #tag EndViewProperty #tag ViewProperty Name="Index" Visible=true @@ -310,6 +84,30 @@ Implements XojoInstruments.Framework.XIObject Type="Integer" EditorType="" #tag EndViewProperty + #tag ViewProperty + Name="ClassName" + Visible=false + Group="Behavior" + InitialValue="" + Type="String" + EditorType="MultiLineEditor" + #tag EndViewProperty + #tag ViewProperty + Name="Hint" + Visible=false + Group="Behavior" + InitialValue="" + Type="String" + EditorType="MultiLineEditor" + #tag EndViewProperty + #tag ViewProperty + Name="ID" + Visible=false + Group="Behavior" + InitialValue="-1" + Type="Integer" + EditorType="" + #tag EndViewProperty #tag EndViewBehavior End Class #tag EndClass diff --git a/XojoInstruments/XojoInstruments/Snapshot.xojo_code b/XojoInstruments/XojoInstruments/Snapshot.xojo_code index ae18026..5b19fd1 100644 --- a/XojoInstruments/XojoInstruments/Snapshot.xojo_code +++ b/XojoInstruments/XojoInstruments/Snapshot.xojo_code @@ -1,8 +1,8 @@ #tag Class Protected Class Snapshot Implements XojoInstruments.Framework.XIObject - #tag Method, Flags = &h21 - Private Shared Function ComputeDelta(lhs As XIArrayInteger, rhs As XIArrayInteger) As SnapshotDelta + #tag Method, Flags = &h0 + Shared Function ComputeDelta(lhs As XIArrayInteger, rhs As XIArrayInteger) As SnapshotDelta // Compare two ObjectRefIDs arrays. // Two arrays must be sorted. @@ -47,283 +47,51 @@ Implements XojoInstruments.Framework.XIObject #tag EndMethod #tag Method, Flags = &h0 - Sub Constructor(createGraph As Boolean) - #pragma BackgroundTasks False - - If SystemObjectsRefIDs = Nil Then - SystemObjectsRefIDs = New XIDictionary() - End If - - LastID = LastID + 1 - mID = LastID - - mObjectRefIDs = New XIArrayInteger() - If createGraph Then - mObjectRefGraph = New XIDictionary() - End If - - // Collect all non-managd objects. - // The loop block only exists to limit the scope of the iterator. - Do - Dim iter As Runtime.ObjectIterator = Runtime.IterateObjects() - While iter.MoveNext() - Dim obj As Object = iter.Current - If (obj IsA XIObject) Or (obj Is iter) Then Continue - - Dim oref As ObjectRef = ObjectRef.ReferenceFor(obj) - If SystemObjectsRefIDs.HasKey(oref.ID) Then Continue - - mObjectRefIDs.Append(oref.ID) - If createGraph Then - mObjectRefGraph.Value(oref.ID) = GetReferringObjectRefs(oref) - End If - Wend - Loop Until True - mObjectRefIDs.Sort() - - // Collect all system objects created during the iteration - // (e.g., introspection cache in Xojo framework); they should be - // ignored when taking a next snapshot. - While True - Dim iter2 As Runtime.ObjectIterator = Runtime.IterateObjects() - Dim secondPass As New XIArrayInteger() - While iter2.MoveNext() - Dim obj As Object = iter2.Current - If (obj IsA XIObject) Or (obj Is iter2) Then Continue - - Dim oref As ObjectRef = ObjectRef.ReferenceFor(obj) - If SystemObjectsRefIDs.HasKey(oref.ID) Then Continue - - secondPass.Append(oref.ID) - Wend - secondPass.Sort() - - // Compute delta - Dim addedObjectRefIDs As XIArrayInteger = ComputeDelta(mObjectRefIDs, secondPass).Added - For Each id As Integer In addedObjectRefIDs - SystemObjectsRefIDs.Value(id) = True - Next - If addedObjectRefIDs.Ubound() = -1 Then Exit - Wend - - // Remove WeakRefs no longer in use. - ObjectRef.GarbageCollect() + Sub Constructor(id As Integer) + Me.ID = id + Me.ObjectRefIDs = New XIArrayInteger() End Sub #tag EndMethod - #tag Method, Flags = &h0 - Function Count() As Integer - Return mObjectRefIDs.Count() - End Function - #tag EndMethod - #tag Method, Flags = &h0 Function DifferenceFrom(other As Snapshot) As SnapshotDelta - Return ComputeDelta(other.mObjectRefIDs, Me.mObjectRefIDs) - End Function - #tag EndMethod - - #tag Method, Flags = &h21 - Private Shared Function GetReferringObjectRefs(oref As ObjectRef) As XojoInstruments.Framework.XIDictionary - // Finds all objects directly referenced by the specified oref, as possible as we can. - - #pragma BackgroundTasks False - - Using Xojo.Introspection - - Dim refs As New XIDictionary() - Dim obj As Variant = oref.Value() - - If obj = Nil Then Return refs - - If obj.IsArray() Then - Select Case obj.ArrayElementType - Case Variant.TypeDate, Variant.TypeObject - // Currently only 1-D array is supported. - Dim arr() As Variant = obj - For i As Integer = arr.Ubound() DownTo 0 - GetReferringObjectRefsRegister(arr(i), "[" + Str(i) + "]", refs) - Next - - Case Else - // Array of Array is not allowed in Xojo. - 'Case Variant.TypeArray - - // Not interested in value types. - 'Case Variant.TypeBoolean - 'Case Variant.TypeCFStringRef - 'Case Variant.TypeColor - 'Case Variant.TypeCString - 'Case Variant.TypeCurrency - 'Case Variant.TypeDouble - 'Case Variant.TypeInt32 - 'Case Variant.TypeInt64 - 'Case Variant.TypeNil - 'Case Variant.TypeOSType - 'Case Variant.TypePString - 'Case Variant.TypeSingle - 'Case Variant.TypeString - 'Case Variant.TypeStructure - 'Case Variant.TypeText - 'Case Variant.TypeWindowPtr - 'Case Variant.TypeWString - - End Select - - Else - Dim ti As TypeInfo = GetType(obj) - - // Collect properties. This includes shared properties, but - // excludes computed properties. - For Each prop As PropertyInfo In ti.Properties() - If Not prop.IsComputed() Then - Dim name As String = If(prop.IsShared(), "(shared) ", "") + prop.Name - GetReferringObjectRefsRegister(prop.Value(obj), name, refs) - End If - Next - - // Handle special classes. - - #if TargetDesktop - Select Case obj - Case IsA Window - Dim win As Window = obj - // Note: non-control window items cannot be reached. - For i As Integer = win.ControlCount - 1 DownTo 0 - Dim ctrl As Control = win.Control(i) - GetReferringObjectRefsRegister(ctrl, ctrl.Name, refs) - Next - - Case IsA MenuItem - Dim m As MenuItem = obj - For i As Integer = m.Count() - 1 DownTo 0 - Dim child As MenuItem = m.Item(i) - GetReferringObjectRefsRegister(child, "[" + Str(i) + "]", refs) - Next - - Case IsA SegmentedControl - Dim sc As SegmentedControl = obj - For i As Integer = sc.Items.UBound() DownTo 0 - GetReferringObjectRefsRegister(sc.Items(i), "Item[" + Str(i) + "]", refs) - Next - - End Select - #endif - - Select Case obj - Case IsA Dictionary - Dim dict As Dictionary = Dictionary(obj) - For i As Integer = dict.Count() - 1 DownTo 0 - Dim key As Variant = dict.Key(i) - GetReferringObjectRefsRegister(key, "Key[" + Str(i) + "]", refs) - GetReferringObjectRefsRegister(dict.Value(key), "Value[" + Str(i) + "]", refs) - Next - - Case IsA Xojo.Core.Dictionary - Dim dict As Xojo.Core.Dictionary = Xojo.Core.Dictionary(obj) - Dim i As Integer = 0 - For Each ent As Xojo.Core.DictionaryEntry In dict - GetReferringObjectRefsRegister(ent.Key, "Key[" + Str(i) + "]", refs) - GetReferringObjectRefsRegister(ent.Value, "Value[" + Str(i) + "]", refs) - i = i + 1 - Next - - End Select - End If - - // TODO support more classes like Collection - - Return refs + Return ComputeDelta(other.ObjectRefIDs, Me.ObjectRefIDs) End Function #tag EndMethod - #tag Method, Flags = &h21 - Private Shared Sub GetReferringObjectRefsRegister(v As Variant, key As String, dict As XIDictionary) - If v = Nil Or v IsA XIObject Then Return - - Dim ti As Xojo.Introspection.TypeInfo = Xojo.Introspection.GetType(v) - - // `ti` will become Nil if the variant is an instance of - // the Xojo framework private class, e.g., `_Profile.Profile`. - If ti = Nil Or ti.IsValueType Then Return - - // Translate Array into Object. - If ti.IsArray() Then - v = v.ObjectValue - End If - - // Register. - dict.Value(key) = ObjectRef.ReferenceFor(v).ID - End Sub - #tag EndMethod - - #tag Method, Flags = &h0 - Shared Sub RegisterSystemObject(obj As Object) - SystemObjectsRefIDs.Value(ObjectRef.ReferenceFor(obj).ID) = True - End Sub - #tag EndMethod - - #tag ComputedProperty, Flags = &h0 - #tag Getter - Get - return mID - End Get - #tag EndGetter - ID As Integer - #tag EndComputedProperty - - #tag Property, Flags = &h21 - Private Shared LastID As Integer = -1 - #tag EndProperty - - #tag Property, Flags = &h21 - Private mID As Integer + #tag Property, Flags = &h0 + ID As Integer = -1 #tag EndProperty - #tag Property, Flags = &h21 - Private mObjectRefGraph As XIDictionary - #tag EndProperty - - #tag Property, Flags = &h21 - Private mObjectRefIDs As XIArrayInteger - #tag EndProperty - - #tag ComputedProperty, Flags = &h0 - #tag Getter - Get - return mObjectRefGraph - End Get - #tag EndGetter + #tag Property, Flags = &h0 + #tag Note + A map of an ID of the ObjectRef and a dictionary, which holds a list of referring objects (objects referred from the object) + as a mapping of a key string (the relationship from the object) and an ID of its ObjectRef. + #tag EndNote ObjectRefGraph As XIDictionary - #tag EndComputedProperty + #tag EndProperty - #tag ComputedProperty, Flags = &h0 - #tag Getter - Get - return mObjectRefIDs - End Get - #tag EndGetter + #tag Property, Flags = &h0 + #tag Note + A list of IDs of ObjectRefs. + #tag EndNote ObjectRefIDs As XIArrayInteger - #tag EndComputedProperty + #tag EndProperty - #tag Property, Flags = &h21 - Private Shared SystemObjectsRefIDs As XIDictionary + #tag Property, Flags = &h0 + Timestamp As XIDate #tag EndProperty #tag ViewBehavior - #tag ViewProperty - Name="ID" - Group="Behavior" - Type="Integer" - #tag EndViewProperty #tag ViewProperty Name="Index" Visible=true Group="ID" InitialValue="-2147483648" Type="Integer" + EditorType="" #tag EndViewProperty #tag ViewProperty Name="Left" @@ -331,18 +99,23 @@ Implements XojoInstruments.Framework.XIObject Group="Position" InitialValue="0" Type="Integer" + EditorType="" #tag EndViewProperty #tag ViewProperty Name="Name" Visible=true Group="ID" + InitialValue="" Type="String" + EditorType="" #tag EndViewProperty #tag ViewProperty Name="Super" Visible=true Group="ID" + InitialValue="" Type="String" + EditorType="" #tag EndViewProperty #tag ViewProperty Name="Top" @@ -350,6 +123,15 @@ Implements XojoInstruments.Framework.XIObject Group="Position" InitialValue="0" Type="Integer" + EditorType="" + #tag EndViewProperty + #tag ViewProperty + Name="ID" + Visible=false + Group="Behavior" + InitialValue="-1" + Type="Integer" + EditorType="" #tag EndViewProperty #tag EndViewBehavior End Class diff --git a/XojoInstruments/XojoInstruments/SnapshotDelta.xojo_code b/XojoInstruments/XojoInstruments/SnapshotDelta.xojo_code index c4b9da2..9a24903 100644 --- a/XojoInstruments/XojoInstruments/SnapshotDelta.xojo_code +++ b/XojoInstruments/XojoInstruments/SnapshotDelta.xojo_code @@ -3,51 +3,24 @@ Protected Class SnapshotDelta Implements XojoInstruments.Framework.XIObject #tag Method, Flags = &h0 Sub Constructor(added As XIArrayInteger, removed As XIArrayInteger, unchanged As XIArrayInteger) - mAdded = added - mRemoved = removed - mUnchanged = unchanged + Me.Added = added + Me.Removed = removed + Me.Unchanged = unchanged End Sub #tag EndMethod - #tag ComputedProperty, Flags = &h0 - #tag Getter - Get - return mAdded - End Get - #tag EndGetter + #tag Property, Flags = &h0 Added As XIArrayInteger - #tag EndComputedProperty - - #tag Property, Flags = &h21 - Private mAdded As XIArrayInteger - #tag EndProperty - - #tag Property, Flags = &h21 - Private mRemoved As XIArrayInteger #tag EndProperty - #tag Property, Flags = &h21 - Private mUnchanged As XIArrayInteger - #tag EndProperty - - #tag ComputedProperty, Flags = &h0 - #tag Getter - Get - return mRemoved - End Get - #tag EndGetter + #tag Property, Flags = &h0 Removed As XIArrayInteger - #tag EndComputedProperty + #tag EndProperty - #tag ComputedProperty, Flags = &h0 - #tag Getter - Get - return mUnchanged - End Get - #tag EndGetter + #tag Property, Flags = &h0 Unchanged As XIArrayInteger - #tag EndComputedProperty + #tag EndProperty #tag ViewBehavior @@ -57,6 +30,7 @@ Implements XojoInstruments.Framework.XIObject Group="ID" InitialValue="-2147483648" Type="Integer" + EditorType="" #tag EndViewProperty #tag ViewProperty Name="Left" @@ -64,18 +38,23 @@ Implements XojoInstruments.Framework.XIObject Group="Position" InitialValue="0" Type="Integer" + EditorType="" #tag EndViewProperty #tag ViewProperty Name="Name" Visible=true Group="ID" + InitialValue="" Type="String" + EditorType="" #tag EndViewProperty #tag ViewProperty Name="Super" Visible=true Group="ID" + InitialValue="" Type="String" + EditorType="" #tag EndViewProperty #tag ViewProperty Name="Top" @@ -83,6 +62,7 @@ Implements XojoInstruments.Framework.XIObject Group="Position" InitialValue="0" Type="Integer" + EditorType="" #tag EndViewProperty #tag EndViewBehavior End Class diff --git a/XojoInstruments/XojoInstrumentsDesktopGUI.xojo_window b/XojoInstruments/XojoInstrumentsDesktopGUI.xojo_window index a1c4c10..897c2e4 100644 --- a/XojoInstruments/XojoInstrumentsDesktopGUI.xojo_window +++ b/XojoInstruments/XojoInstrumentsDesktopGUI.xojo_window @@ -9,7 +9,7 @@ Begin Window XojoInstrumentsDesktopGUI FullScreenButton= False HasBackColor = False Height = 600 - ImplicitInstance= True + ImplicitInstance= False LiveResize = "True" MacProcID = 0 MaxHeight = 32000 @@ -1071,22 +1071,31 @@ End #tag Event Sub Open() // Hide objects in the window from snapshot. - XojoInstruments.Snapshot.RegisterSystemObject(Me) + mTargetSession.RegisterSystemObject(Me) For i As Integer = Me.ControlCount - 1 DownTo 0 - XojoInstruments.Snapshot.RegisterSystemObject(Me.Control(i)) + mTargetSession.RegisterSystemObject(Me.Control(i)) Next End Sub #tag EndEvent + #tag Method, Flags = &h0 + Sub Constructor(sess As XojoInstruments.InstrumentsSession) + Me.mTargetSession = sess + + // Calling the overridden superclass constructor. + Super.Constructor() + End Sub + #tag EndMethod + #tag Method, Flags = &h21 Private Function DoCapture(createGraph As Boolean) As XojoInstruments.Snapshot - Dim snap As New XojoInstruments.Snapshot(createGraph) + Dim snap As XojoInstruments.Snapshot = mTargetSession.Capture(createGraph) SnapshotList.AddRow( _ Str(snap.ID), _ Xojo.Core.Date.Now().ToText(), _ - Str(snap.Count())) + Str(snap.ObjectRefIDs.Count())) SnapshotList.RowTag(SnapshotList.LastIndex) = snap SnapshotList.ListIndex = SnapshotList.LastIndex @@ -1172,7 +1181,7 @@ End For Each id As Integer In snap.ObjectRefIDs Dim oref As XojoInstruments.ObjectRef = _ - XojoInstruments.ObjectRef.ReferenceByID(id) + mTargetSession.ObjectRefByID(id) If Not excludeNodesWithoutEdge Or seen.HasKey(id) Then If renderHints Then // TODO html escape needed @@ -1277,11 +1286,11 @@ End #tag EndMethod #tag Method, Flags = &h21 - Private Function GroupByClassName(ObjectRefIDs As XojoInstruments.Framework.XIArrayInteger) As XIDictionary + Private Function GroupByClassName(orefIDs As XojoInstruments.Framework.XIArrayInteger) As XIDictionary Dim d As New XIDictionary() - For Each id As Integer In ObjectRefIDs - Dim className As String = XojoInstruments.ObjectRef.ReferenceByID(id).ClassName + For Each id As Integer In orefIDs + Dim className As String = mTargetSession.ObjectRefByID(id).ClassName Dim idListForClass As New XIArrayInteger() If d.HasKey(className) Then idListForClass = d.Value(className) @@ -1308,6 +1317,10 @@ End Private mSnapshotDelta As XojoInstruments.SnapshotDelta #tag EndProperty + #tag Property, Flags = &h21 + Private mTargetSession As XojoInstruments.InstrumentsSession + #tag EndProperty + #tag Property, Flags = &h21 Private mTempGraphHTMLFile As XojoInstruments.Framework.XINamedTemporaryFile #tag EndProperty @@ -1354,7 +1367,7 @@ End Sub ExpandRow(row As Integer) Dim ids As XojoInstruments.Framework.XIArrayInteger = Me.RowTag(row) For Each id As Integer In ids - Dim oref As XojoInstruments.ObjectRef = XojoInstruments.ObjectRef.ReferenceByID(id) + Dim oref As XojoInstruments.ObjectRef = mTargetSession.ObjectRefByID(id) Me.AddRow(Str(id) + If(oref.Hint <> "", " − " + oref.Hint, "")) Me.RowTag(Me.LastIndex) = id Next @@ -1372,19 +1385,19 @@ End unchanged = d.Value(2) For Each id As Integer In added - Dim oref As XojoInstruments.ObjectRef = XojoInstruments.ObjectRef.ReferenceByID(id) + Dim oref As XojoInstruments.ObjectRef = mTargetSession.ObjectRefByID(id) Me.AddRow(Str(id) + If(oref.Hint <> "", " − " + oref.Hint, ""), "", "✓", "") Me.RowTag(Me.LastIndex) = id Next For Each id As Integer In removed - Dim oref As XojoInstruments.ObjectRef = XojoInstruments.ObjectRef.ReferenceByID(id) + Dim oref As XojoInstruments.ObjectRef = mTargetSession.ObjectRefByID(id) Me.AddRow(Str(id) + If(oref.Hint <> "", " − " + oref.Hint, ""), "", "", "✓") Me.RowTag(Me.LastIndex) = id Next For Each id As Integer In unchanged - Dim oref As XojoInstruments.ObjectRef = XojoInstruments.ObjectRef.ReferenceByID(id) + Dim oref As XojoInstruments.ObjectRef = mTargetSession.ObjectRefByID(id) Me.AddRow(Str(id) + If(oref.Hint <> "", " − " + oref.Hint, ""), "", "", "") Me.RowTag(Me.LastIndex) = id Next @@ -1407,37 +1420,42 @@ End Return End If - If ComparisonList.RowIsFolder(ComparisonList.ListIndex) Then - // All objects for the class. - Dim d As XojoInstruments.Framework.XIDictionary = ComparisonList.RowTag(ComparisonList.ListIndex) - Dim added, unchanged As XojoInstruments.Framework.XIArrayInteger - - added = d.Value(0) - unchanged = d.Value(2) - - Dim viewObjects As New XojoInstruments.Framework.XIDictionary() - - For Each id As Integer In added - viewObjects.Value(id) = XojoInstruments.ObjectRef.ReferenceByID(id).Value() - Next - - For Each id As Integer In unchanged - viewObjects.Value(id) = XojoInstruments.ObjectRef.ReferenceByID(id).Value() - Next - - XojoInstruments.ObjectRef.InspectInIDE(-1, viewObjects) - - Else - // Single object. - Dim objId As Integer = ComparisonList.RowTag(ComparisonList.ListIndex) - Dim oref As XojoInstruments.ObjectRef = XojoInstruments.ObjectRef.ReferenceByID(objId) - Dim obj As Object = oref.Value() - If obj <> Nil Then - XojoInstruments.ObjectRef.InspectInIDE(objId, obj) - Else + // TODO: recover bulk inspect feature + 'If ComparisonList.RowIsFolder(ComparisonList.ListIndex) Then + '// All objects for the class. + 'Dim d As XojoInstruments.Framework.XIDictionary = ComparisonList.RowTag(ComparisonList.ListIndex) + 'Dim added, unchanged As XojoInstruments.Framework.XIArrayInteger + ' + 'added = d.Value(0) + 'unchanged = d.Value(2) + ' + 'Dim viewObjects As New XojoInstruments.Framework.XIDictionary() + ' + 'For Each id As Integer In added + 'viewObjects.Value(id) = mTargetSession.ObjectRefByID(id).Value() + 'Next + ' + 'For Each id As Integer In unchanged + 'viewObjects.Value(id) = mTargetSession.ObjectRefByID(id).Value() + 'Next + ' + 'XojoInstruments.ObjectRef.InspectObject(-1, viewObjects) + ' + 'Else + + // Single object. + Dim objId As Integer = ComparisonList.RowTag(ComparisonList.ListIndex) + + Try + If Not mTargetSession.InspectObject(objId) Then MsgBox("The object has already been garbage collected.") End If - End If + Catch e As UnsupportedOperationException + MsgBox("The app is not running in Debug Run mode.") + End Try + + 'End If + #else MsgBox("Sorry, this feature is only available in Debug Run.") #endif @@ -1461,15 +1479,15 @@ End If URL.InStr("xojo-instruments") <> 0 Then Dim s2 As String = URL.Mid(URL.InStr("object=") + 7) - Dim s As Integer = Val(s2) - Dim oref As XojoInstruments.ObjectRef = XojoInstruments.ObjectRef.ReferenceByID(s) - Dim obj As Object = oref.Value() + Dim objId As Integer = Val(s2) - If obj <> Nil Then - XojoInstruments.ObjectRef.InspectInIDE(s, obj) - Else - MsgBox("The object has already been garbage collected.") - End If + Try + If Not mTargetSession.InspectObject(objId) Then + MsgBox("The object has already been garbage collected.") + End If + Catch e As UnsupportedOperationException + MsgBox("The app is not running in Debug Run mode.") + End Try Return True End If @@ -1529,28 +1547,32 @@ End Return End If - If SnapshotObjectList.RowIsFolder(SnapshotObjectList.ListIndex) Then - // All objects for the class. - Dim objectIDs As XojoInstruments.Framework.XIArrayInteger = SnapshotObjectList.RowTag(SnapshotObjectList.ListIndex) - Dim viewObjects As New XojoInstruments.Framework.XIDictionary() - - For Each id As Integer In objectIDs - viewObjects.Value(id) = XojoInstruments.ObjectRef.ReferenceByID(id).Value() - Next - - XojoInstruments.ObjectRef.InspectInIDE(-1, viewObjects) - Else - // Single object. - - Dim objId As Integer = SnapshotObjectList.RowTag(SnapshotObjectList.ListIndex) - Dim oref As XojoInstruments.ObjectRef = XojoInstruments.ObjectRef.ReferenceByID(objId) - Dim obj As Object = oref.Value() - If obj <> Nil Then - XojoInstruments.ObjectRef.InspectInIDE(objId, obj) - Else + // TODO + 'If SnapshotObjectList.RowIsFolder(SnapshotObjectList.ListIndex) Then + '// All objects for the class. + 'Dim objectIDs As XojoInstruments.Framework.XIArrayInteger = SnapshotObjectList.RowTag(SnapshotObjectList.ListIndex) + 'Dim viewObjects As New XojoInstruments.Framework.XIDictionary() + ' + 'For Each id As Integer In objectIDs + 'viewObjects.Value(id) = XojoInstruments.ObjectRef.ReferenceByID(id).Value() + 'Next + ' + 'XojoInstruments.ObjectRef.InspectObject(-1, viewObjects) + 'Else + + // Single object. + + Dim objId As Integer = SnapshotObjectList.RowTag(SnapshotObjectList.ListIndex) + Try + If Not mTargetSession.InspectObject(objId) Then MsgBox("The object has already been garbage collected.") End If - End If + Catch e As UnsupportedOperationException + MsgBox("The app is not running in Debug Run mode.") + End Try + + 'End If + #else MsgBox("Sorry, this feature is only available in Debug Run.") #endif @@ -1587,7 +1609,7 @@ End End If Dim objID As Integer = Val(BackrefInput.Text) - Dim objRef As XojoInstruments.ObjectRef = XojoInstruments.ObjectRef.ReferenceByID(objID) + Dim objRef As XojoInstruments.ObjectRef = mTargetSession.ObjectRefByID(objID) If objRef = Nil Then MsgBox("No such object.") @@ -1616,7 +1638,7 @@ End For Each p As Pair In backrefs Dim refID As Integer = p.Left Dim refKey As String = p.Right - Dim oref As XojoInstruments.ObjectRef = XojoInstruments.ObjectRef.ReferenceByID(refID) + Dim oref As XojoInstruments.ObjectRef = mTargetSession.ObjectRefByID(refID) Me.AddFolder( _ Str(refID) + " − " + _