From 324f0d320f6509ff169bbb7b0f7addebc3b089a6 Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Wed, 15 Apr 2026 11:25:03 +0200 Subject: [PATCH 01/22] feat: darker color on selected row in table --- .../DSRecordBrowserPresenter.class.st | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st index ac5a71a..ad95971 100644 --- a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st +++ b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st @@ -229,6 +229,15 @@ DSRecordBrowserPresenter >> getRecordColorAssociationsFrom: aWindowRecordCollect ^ recordColorsAssociations sorted: [ :recordA :recordB | recordA key dateTime < recordB key dateTime ] ] +{ #category : 'helpers' } +DSRecordBrowserPresenter >> getTableRowColorFor: anAssociation [ + "Returns the row's corresponding color depending of the table selected row." + + anAssociation = recordsTablePresenter selectedItem + ifTrue: [ ^ anAssociation value darker ] + ifFalse: [ ^ anAssociation value ] +] + { #category : 'helpers' } DSRecordBrowserPresenter >> getTimelinePointsFrom: aHistory [ "Returns a list of plots for the timeline chart." @@ -322,19 +331,19 @@ DSRecordBrowserPresenter >> recordsTable [ ^ self newTreeTable addColumn: (SpStringTableColumn new title: 'Event'; - displayBackgroundColor: [ :association | association value ]; + displayBackgroundColor: [ :association | self getTableRowColorFor: association ]; evaluated: [ :association | association key eventName asString ]; displayColor: [ :aRecord | Color white ]; yourself); addColumn: (SpStringTableColumn new title: 'Event type'; - displayBackgroundColor: [ :association | association value ]; + displayBackgroundColor: [ :association | self getTableRowColorFor: association ]; evaluated: [ :association | association key class asString ]; displayColor: [ :aRecord | Color white ]; yourself); addColumn: (SpStringTableColumn new title: 'Time'; - displayBackgroundColor: [ :association | association value ]; + displayBackgroundColor: [ :association | self getTableRowColorFor: association ]; evaluated: [ :association | association key dateTime asTime print24 ]; displayColor: [ :aRecord | Color white ]; yourself); From ec1322175f318285b2704a5cc97a98b5d0dcd13c Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Wed, 15 Apr 2026 15:29:16 +0200 Subject: [PATCH 02/22] feat: windows presenter --- .../DSRecordBrowserPresenterTest.class.st | 35 ++++++++++-- .../DSRecordBrowserPresenter.class.st | 54 +++++++++++++++++-- 2 files changed, 79 insertions(+), 10 deletions(-) diff --git a/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st b/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st index 7e65221..17f96a5 100644 --- a/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st +++ b/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st @@ -16,10 +16,15 @@ DSRecordBrowserPresenterTest >> filesPresenter [ { #category : 'helpers' } DSRecordBrowserPresenterTest >> generateRecordsFile [ - "Generates a file of records and returns its file reference." - | records recordFileRef writeStream | - records := self getRecordExamples. + ^ self generateRecordsFileFor: self getRecordExamples +] + +{ #category : 'helpers' } +DSRecordBrowserPresenterTest >> generateRecordsFileFor: someRecords [ + "Generates a file of random records and returns its file reference." + + | recordFileRef writeStream | recordFileRef := self temporaryDirectory / ('ds-spy-test-' , UUID new asString). recordFileRef ensureCreateFile. @@ -27,10 +32,10 @@ DSRecordBrowserPresenterTest >> generateRecordsFile [ writeStream nextPut: $[. - records doWithIndex: [ :record :index | + someRecords doWithIndex: [ :record :index | writeStream nextPutAll: (STON toString: record). - index = records size ifFalse: [ + index = someRecords size ifFalse: [ writeStream nextPut: $,. writeStream crlf ] ]. @@ -354,6 +359,20 @@ DSRecordBrowserPresenterTest >> testUpdateRecordsTableWhenAddingFile [ self assert: self recordsTablePresenter roots last key class equals: DSInspectItRecord ] +{ #category : 'tests' } +DSRecordBrowserPresenterTest >> testUpdateWindowsPresenter [ + + | records fileRef presenterMock windows | + records := self getRecordExamples. + fileRef := self generateRecordsFileFor: records. + presenterMock := MockObject new on: #selectedItem respond: fileRef. + browser updateWindowsPresenter: presenterMock. + + windows := self windowsPresenter roots. + self assert: windows size equals: 4. + self assert: (windows allSatisfy: [ :window | window class = DSWindowRecord ]) +] + { #category : 'tests' } DSRecordBrowserPresenterTest >> testWindowColorFrom [ @@ -368,3 +387,9 @@ DSRecordBrowserPresenterTest >> timelinePresenter [ ^ browser presenterAt: #graphicTimeline ] + +{ #category : 'helpers' } +DSRecordBrowserPresenterTest >> windowsPresenter [ + + ^ browser presenterAt: #windowsPresenter +] diff --git a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st index ad95971..fd7643a 100644 --- a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st +++ b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st @@ -16,7 +16,8 @@ Class { 'toolbarPresenter', 'fileListPresenter', 'startRecordButtonPresenter', - 'stopRecordButtonPresenter' + 'stopRecordButtonPresenter', + 'windowsPresenter' ], #classInstVars : [ 'uniqueInstance' @@ -145,7 +146,8 @@ DSRecordBrowserPresenter >> connectPresenters [ fileListPresenter whenSelectionChangedDo: [ :presenter | self updateRecordsTable: presenter. - self updateTimelineChart ]. + self updateTimelineChart. + self updateWindowsPresenter: presenter ]. recordsFilter whenChangedDo: [ fileListPresenter selectedItem ifNotNil: [ self updateRecordsTable: fileListPresenter ] ] ] @@ -166,6 +168,7 @@ DSRecordBrowserPresenter >> defaultLayout [ add: (SpTabLayout new add: recordsTablePresenter label: 'Records'; add: graphicTimeline label: 'Timeline'; + add: windowsPresenter label: 'Windows'; yourself); yourself); yourself) @@ -269,7 +272,8 @@ DSRecordBrowserPresenter >> initializePresenters [ fileListPresenter := self fileList. recordsTablePresenter := self recordsTable. graphicTimeline := self newRoassal. - recordsFilter := self recordsFilter + recordsFilter := self recordsFilter. + windowsPresenter := self windowsPresenter ] { #category : 'operations' } @@ -336,7 +340,7 @@ DSRecordBrowserPresenter >> recordsTable [ displayColor: [ :aRecord | Color white ]; yourself); addColumn: (SpStringTableColumn new - title: 'Event type'; + title: 'Type'; displayBackgroundColor: [ :association | self getTableRowColorFor: association ]; evaluated: [ :association | association key class asString ]; displayColor: [ :aRecord | Color white ]; @@ -348,7 +352,7 @@ DSRecordBrowserPresenter >> recordsTable [ displayColor: [ :aRecord | Color white ]; yourself); beResizable; - actions: self recordsTableActions; + " actions: self recordsTableActions;" yourself ] @@ -532,6 +536,15 @@ DSRecordBrowserPresenter >> updateToolbar [ stopRecordButtonPresenter enabled: DSSpy recordingSession ] +{ #category : 'operations' } +DSRecordBrowserPresenter >> updateWindowsPresenter: aFileListPresenter [ + + | fileRef | + fileRef := aFileListPresenter selectedItem. + + fileRef ifNotNil: [ windowsPresenter roots: (self getHistoryFrom: fileRef) windows ] +] + { #category : 'accessing' } DSRecordBrowserPresenter >> windowIcon [ @@ -543,3 +556,34 @@ DSRecordBrowserPresenter >> windowTitle [ ^ 'Debugging record browser' ] + +{ #category : 'layout' } +DSRecordBrowserPresenter >> windowsPresenter [ + "Instanciates a new records table that displays data based on the selected file's records." + + ^ self newTreeTable + addColumn: (SpStringTableColumn new + title: 'Window / Event'; + evaluated: [ :anItem | anItem asString ]; + yourself); + addColumn: (SpStringTableColumn new + title: 'Type'; + evaluated: [ :anItem | + anItem class = DSWindowRecord + ifTrue: [ anItem windowType ] + ifFalse: [ anItem class name ] ]; + yourself); + addColumn: (SpStringTableColumn new + title: 'Nb of events / Time'; + evaluated: [ :anItem | + anItem class = DSWindowRecord + ifTrue: [ anItem events size asString , ' events' ] + ifFalse: [ anItem dateTime asTime print24 ] ]; + yourself); + beResizable; + "actions: self recordsTableActions;"children: [ :item | + item class = DSWindowRecord + ifTrue: [ item events ] + ifFalse: [ { } ] ]; + yourself +] From 2a8ad7595bab81773fcc214cbcd2014591bde0d1 Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Wed, 15 Apr 2026 16:21:31 +0200 Subject: [PATCH 03/22] fix: changing dsspy shortcut --- DebuggingSpy-Browser/PharoShortcuts.extension.st | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DebuggingSpy-Browser/PharoShortcuts.extension.st b/DebuggingSpy-Browser/PharoShortcuts.extension.st index ac2408d..4eee33c 100644 --- a/DebuggingSpy-Browser/PharoShortcuts.extension.st +++ b/DebuggingSpy-Browser/PharoShortcuts.extension.st @@ -3,5 +3,5 @@ Extension { #name : 'PharoShortcuts' } { #category : '*DebuggingSpy-Browser' } PharoShortcuts >> openDebuggingSpyBrowserShortcut [ - ^ $d meta , $s meta + ^ $o meta , $d meta ] From 53cb1d5818b78646c35d085186542686ce36d164 Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Wed, 15 Apr 2026 11:48:51 +0200 Subject: [PATCH 04/22] test: getTableRowColorFor --- .../DSRecordBrowserPresenterTest.class.st | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st b/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st index 17f96a5..69623fa 100644 --- a/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st +++ b/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st @@ -261,6 +261,21 @@ DSRecordBrowserPresenterTest >> testGetWindowFromRecord [ self assert: window name equals: record windowId ] +{ #category : 'tests' } +DSRecordBrowserPresenterTest >> testGetTableRowColorFor [ + + | association | + self recordsTablePresenter roots: { + (DSAbstractEventRecord new -> Color red). + (DSAbstractEventRecord new -> Color blue). + (DSAbstractEventRecord new -> Color green) }. + association := self recordsTablePresenter roots first. + + self assert: (browser getTableRowColorFor: association) equals: association value. + self recordsTablePresenter selectItem: association. + self assert: (browser getTableRowColorFor: association) equals: association value darker +] + { #category : 'tests' } DSRecordBrowserPresenterTest >> testRemoveFile [ From 0ce60b02f2ae5371dd4c8ca52553b04d5dd08875 Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Wed, 15 Apr 2026 15:29:16 +0200 Subject: [PATCH 05/22] feat: windows presenter --- .../DSRecordBrowserPresenterTest.class.st | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st b/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st index 69623fa..ad30fa5 100644 --- a/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st +++ b/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st @@ -22,8 +22,9 @@ DSRecordBrowserPresenterTest >> generateRecordsFile [ { #category : 'helpers' } DSRecordBrowserPresenterTest >> generateRecordsFileFor: someRecords [ - "Generates a file of random records and returns its file reference." + "Generates a file of records and returns its file reference." + | recordFileRef writeStream | | recordFileRef writeStream | recordFileRef := self temporaryDirectory / ('ds-spy-test-' , UUID new asString). @@ -32,9 +33,11 @@ DSRecordBrowserPresenterTest >> generateRecordsFileFor: someRecords [ writeStream nextPut: $[. + someRecords doWithIndex: [ :record :index | someRecords doWithIndex: [ :record :index | writeStream nextPutAll: (STON toString: record). + index = someRecords size ifFalse: [ index = someRecords size ifFalse: [ writeStream nextPut: $,. writeStream crlf ] ]. @@ -388,6 +391,20 @@ DSRecordBrowserPresenterTest >> testUpdateWindowsPresenter [ self assert: (windows allSatisfy: [ :window | window class = DSWindowRecord ]) ] +{ #category : 'tests' } +DSRecordBrowserPresenterTest >> testUpdateWindowsPresenter [ + + | records fileRef presenterMock windows | + records := self getRecordExamples. + fileRef := self generateRecordsFileFor: records. + presenterMock := MockObject new on: #selectedItem respond: fileRef. + browser updateWindowsPresenter: presenterMock. + + windows := self windowsPresenter roots. + self assert: windows size equals: 4. + self assert: (windows allSatisfy: [ :window | window class = DSWindowRecord ]) +] + { #category : 'tests' } DSRecordBrowserPresenterTest >> testWindowColorFrom [ @@ -408,3 +425,9 @@ DSRecordBrowserPresenterTest >> windowsPresenter [ ^ browser presenterAt: #windowsPresenter ] + +{ #category : 'helpers' } +DSRecordBrowserPresenterTest >> windowsPresenter [ + + ^ browser presenterAt: #windowsPresenter +] From 116a82a5d414ad31fabafb874cf6cce60207c445 Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Wed, 15 Apr 2026 17:22:49 +0200 Subject: [PATCH 06/22] refactor: removing timeline from browser --- .../DSRecordBrowserPresenter.class.st | 59 +------------------ 1 file changed, 1 insertion(+), 58 deletions(-) diff --git a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st index fd7643a..d310635 100644 --- a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st +++ b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st @@ -11,7 +11,6 @@ Class { 'files', 'recordsTablePresenter', 'timerWindow', - 'graphicTimeline', 'recordsFilter', 'toolbarPresenter', 'fileListPresenter', @@ -146,7 +145,6 @@ DSRecordBrowserPresenter >> connectPresenters [ fileListPresenter whenSelectionChangedDo: [ :presenter | self updateRecordsTable: presenter. - self updateTimelineChart. self updateWindowsPresenter: presenter ]. recordsFilter whenChangedDo: [ fileListPresenter selectedItem ifNotNil: [ self updateRecordsTable: fileListPresenter ] ] @@ -167,7 +165,6 @@ DSRecordBrowserPresenter >> defaultLayout [ add: (SpBoxLayout newTopToBottom add: (SpTabLayout new add: recordsTablePresenter label: 'Records'; - add: graphicTimeline label: 'Timeline'; add: windowsPresenter label: 'Windows'; yourself); yourself); @@ -241,19 +238,6 @@ DSRecordBrowserPresenter >> getTableRowColorFor: anAssociation [ ifFalse: [ ^ anAssociation value ] ] -{ #category : 'helpers' } -DSRecordBrowserPresenter >> getTimelinePointsFrom: aHistory [ - "Returns a list of plots for the timeline chart." - - ^ aHistory windows collectWithIndex: [ :windowRecord :index | - RSTimeLinePlot new - entries: { - windowRecord events first dateTime asNanoSeconds. - windowRecord events last dateTime asNanoSeconds } - at: index; - color: windowRecord windowColor ] -] - { #category : 'helpers' } DSRecordBrowserPresenter >> getWindowFromRecord: aRecord [ "Returns the record's corresponding window record in the history." @@ -271,7 +255,6 @@ DSRecordBrowserPresenter >> initializePresenters [ toolbarPresenter := self toolbar. fileListPresenter := self fileList. recordsTablePresenter := self recordsTable. - graphicTimeline := self newRoassal. recordsFilter := self recordsFilter. windowsPresenter := self windowsPresenter ] @@ -352,7 +335,7 @@ DSRecordBrowserPresenter >> recordsTable [ displayColor: [ :aRecord | Color white ]; yourself); beResizable; - " actions: self recordsTableActions;" + actions: self recordsTableActions; yourself ] @@ -442,34 +425,6 @@ DSRecordBrowserPresenter >> stopRecording [ timerWindow := nil ] -{ #category : 'layout' } -DSRecordBrowserPresenter >> timelineChart [ - "Returns a chart that represents a timeline using the file list presenter's data for its plots." - - | history names chart data | - fileListPresenter selectedItem ifNil: [ ^ nil ]. - - history := self getHistoryFrom: fileListPresenter selectedItem. - names := history windows collect: [ :i | i windowType ]. - - data := self getTimelinePointsFrom: history. - data size < 2 ifTrue: [ ^ nil ]. - - chart := RSCompositeChart new. - chart addAll: data. - - chart verticalTick fromNames: names. - - chart horizontalTick - useNiceLabel; - numberOfTicks: history windows size // 2; - useDiagonalLabel; - labelConversion: [ :v | (DateAndTime fromSeconds: v // 1000000000) asTime ]. "Plots are instancied using their dateTime as nano seconds to prevent events which last less than a second to be hided, so we convert them into seconds to get the label." - - chart build. - ^ chart -] - { #category : 'accessing' } DSRecordBrowserPresenter >> timerWindow [ @@ -517,18 +472,6 @@ DSRecordBrowserPresenter >> updateRecordsTable: filesPresenter [ recordsTablePresenter roots: recordColorAssociations ] -{ #category : 'operations' } -DSRecordBrowserPresenter >> updateTimelineChart [ - "Regenerates the timeline chart using the selected record's data" - - | chart | - chart := self timelineChart. - chart - ifNil: [ graphicTimeline script: [ :canvas | ] ] - ifNotNil: [ graphicTimeline script: [ :canvas | chart renderIn: canvas ] ]. - graphicTimeline refresh -] - { #category : 'layout' } DSRecordBrowserPresenter >> updateToolbar [ From 4b9edd8a1003201dae63f780506264720f03b5e2 Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Thu, 16 Apr 2026 10:23:55 +0200 Subject: [PATCH 07/22] feat: showing nanoseconds for records dateTime feat: adding actions for windows presenter --- .../DSRecordBrowserPresenterTest.class.st | 18 ++++------ .../DSRecordBrowserPresenter.class.st | 36 +++++++++++++++---- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st b/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st index ad30fa5..48e1c07 100644 --- a/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st +++ b/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st @@ -265,18 +265,12 @@ DSRecordBrowserPresenterTest >> testGetWindowFromRecord [ ] { #category : 'tests' } -DSRecordBrowserPresenterTest >> testGetTableRowColorFor [ - - | association | - self recordsTablePresenter roots: { - (DSAbstractEventRecord new -> Color red). - (DSAbstractEventRecord new -> Color blue). - (DSAbstractEventRecord new -> Color green) }. - association := self recordsTablePresenter roots first. - - self assert: (browser getTableRowColorFor: association) equals: association value. - self recordsTablePresenter selectItem: association. - self assert: (browser getTableRowColorFor: association) equals: association value darker +DSRecordBrowserPresenterTest >> testPrintAsFormattedTime [ + self assert: (browser printAsFormattedTime: (Time + hour: 1 + minute: 2 + second: 3 + nanoSecond: 123456789) asDateAndTime) equals: '01:02:03.123456789' ] { #category : 'tests' } diff --git a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st index d310635..46f62a8 100644 --- a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st +++ b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st @@ -304,6 +304,13 @@ DSRecordBrowserPresenter >> openAddFileDialog [ newFiles ifNotNil: [ newFiles do: [ :file | self addFile: file asFileReference ] ] ] +{ #category : 'printing' } +DSRecordBrowserPresenter >> printAsFormattedTime: aDateAndTime [ + "Returns the specified date and time as a string of format hh:mm:ss.nnnnnnnnn" + + ^ String new: 18 streamContents: [ :aStream | aDateAndTime asTime print24: true showSeconds: true on: aStream ] +] + { #category : 'layout' } DSRecordBrowserPresenter >> recordsFilter [ "Instanciates a new chooser that displays every record classes that could be used to filter records in table." @@ -331,7 +338,7 @@ DSRecordBrowserPresenter >> recordsTable [ addColumn: (SpStringTableColumn new title: 'Time'; displayBackgroundColor: [ :association | self getTableRowColorFor: association ]; - evaluated: [ :association | association key dateTime asTime print24 ]; + evaluated: [ :association | self printAsFormattedTime: association key dateTime ]; displayColor: [ :aRecord | Color white ]; yourself); beResizable; @@ -481,6 +488,7 @@ DSRecordBrowserPresenter >> updateToolbar [ { #category : 'operations' } DSRecordBrowserPresenter >> updateWindowsPresenter: aFileListPresenter [ + "Updates the windows presenter by setting its roots by using the files presenter selected item." | fileRef | fileRef := aFileListPresenter selectedItem. @@ -521,12 +529,28 @@ DSRecordBrowserPresenter >> windowsPresenter [ evaluated: [ :anItem | anItem class = DSWindowRecord ifTrue: [ anItem events size asString , ' events' ] - ifFalse: [ anItem dateTime asTime print24 ] ]; + ifFalse: [ self printAsFormattedTime: anItem dateTime ] ]; yourself); beResizable; - "actions: self recordsTableActions;"children: [ :item | - item class = DSWindowRecord - ifTrue: [ item events ] - ifFalse: [ { } ] ]; + actions: self windowsPresenterActions; + children: [ :item | + item class = DSWindowRecord + ifTrue: [ item events ] + ifFalse: [ { } ] ]; + yourself +] + +{ #category : 'layout' } +DSRecordBrowserPresenter >> windowsPresenterActions [ + "Return a list of actions which can be done on a record from the table. For example, inspect the selected record." + + ^ SpActionGroup new + addActionWith: [ :anItem | + anItem + name: 'Inspect'; + iconName: #inspect; + description: 'Inspect the selected element.'; + shortcutKey: $i meta; + action: [ windowsPresenter selectedItem key inspect ] ]; yourself ] From e28a139f8e12c7ce3760d479b8a078be7a6cf757 Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Thu, 16 Apr 2026 11:05:58 +0200 Subject: [PATCH 08/22] introducing statistics presenter --- .../DSRecordBrowserPresenter.class.st | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st index 46f62a8..6d36da2 100644 --- a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st +++ b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st @@ -16,7 +16,8 @@ Class { 'fileListPresenter', 'startRecordButtonPresenter', 'stopRecordButtonPresenter', - 'windowsPresenter' + 'windowsPresenter', + 'statisticsPresenter' ], #classInstVars : [ 'uniqueInstance' @@ -166,6 +167,7 @@ DSRecordBrowserPresenter >> defaultLayout [ add: (SpTabLayout new add: recordsTablePresenter label: 'Records'; add: windowsPresenter label: 'Windows'; + add: statisticsPresenter label: 'Statistics'; yourself); yourself); yourself) @@ -256,7 +258,8 @@ DSRecordBrowserPresenter >> initializePresenters [ fileListPresenter := self fileList. recordsTablePresenter := self recordsTable. recordsFilter := self recordsFilter. - windowsPresenter := self windowsPresenter + windowsPresenter := self windowsPresenter. + statisticsPresenter := self statisticsPresenter ] { #category : 'operations' } @@ -409,6 +412,21 @@ DSRecordBrowserPresenter >> startRecording [ self updateToolbar ] +{ #category : 'layout' } +DSRecordBrowserPresenter >> statisticsPresenter [ + "Instanciates a new records table that displays data based on the selected file's records." + + ^ SpGridLayout new + add: 'Amount of events:' atPoint: 1 @ 1; + add: (self newText appendText: 'test') atPoint: 2 @ 1; + add: 'Amount of windows:' atPoint: 1 @ 2; + add: (self newText appendText: 'test') atPoint: 2 @ 2; + add: 'Record duration:' atPoint: 1 @ 3; + add: (self newText appendText: 'test') atPoint: 2 @ 3; + beColumnNotHomogeneous; + yourself +] + { #category : 'layout' } DSRecordBrowserPresenter >> stopRecordButton [ "Instanciates a button that stops the DSSpy recording session on click." From 2f65bd871c93e79e3cbc3141fc0eca53cbd2dcf1 Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Thu, 16 Apr 2026 11:16:05 +0200 Subject: [PATCH 09/22] refactoring: introducing selectedHistory slot --- .../DSRecordBrowserPresenterTest.class.st | 15 +++---- .../DSRecordBrowserPresenter.class.st | 41 ++++++++++++------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st b/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st index 48e1c07..10804b9 100644 --- a/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st +++ b/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st @@ -223,7 +223,8 @@ DSRecordBrowserPresenterTest >> testGetHistoryFrom [ | fileRef | fileRef := self generateRecordsFile. - self assert: (browser getHistoryFrom: fileRef) class equals: DSRecordHistory + self assert: (browser getHistoryFrom: fileRef) class equals: DSRecordHistory. + self assert: (browser getHistoryFrom: nil) isNil ] { #category : 'tests' } @@ -349,10 +350,10 @@ DSRecordBrowserPresenterTest >> testUpdateLastRecord [ { #category : 'tests' } DSRecordBrowserPresenterTest >> testUpdateRecordsTable [ - | fileRef presenterMock | + | fileRef | fileRef := self generateRecordsFile. - presenterMock := MockObject new on: #selectedItem respond: fileRef. - browser updateRecordsTable: presenterMock. + browser selectedHistory: (browser getHistoryFrom: fileRef). + browser updateRecordsTable. self assert: self recordsTablePresenter roots first key class equals: DSBrowseRecord. self assert: (self recordsTablePresenter roots at: 2) key class equals: DSMouseEnterWindowRecord. @@ -374,11 +375,11 @@ DSRecordBrowserPresenterTest >> testUpdateRecordsTableWhenAddingFile [ { #category : 'tests' } DSRecordBrowserPresenterTest >> testUpdateWindowsPresenter [ - | records fileRef presenterMock windows | + | records fileRef windows | records := self getRecordExamples. fileRef := self generateRecordsFileFor: records. - presenterMock := MockObject new on: #selectedItem respond: fileRef. - browser updateWindowsPresenter: presenterMock. + browser selectedHistory: (browser getHistoryFrom: fileRef). + browser updateWindowsPresenter. windows := self windowsPresenter roots. self assert: windows size equals: 4. diff --git a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st index 6d36da2..f0d9d45 100644 --- a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st +++ b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st @@ -17,7 +17,8 @@ Class { 'startRecordButtonPresenter', 'stopRecordButtonPresenter', 'windowsPresenter', - 'statisticsPresenter' + 'statisticsPresenter', + 'selectedHistory' ], #classInstVars : [ 'uniqueInstance' @@ -145,10 +146,11 @@ DSRecordBrowserPresenter >> connectPresenters [ "Updates the records and the timeline whenever the selected file is changed." fileListPresenter whenSelectionChangedDo: [ :presenter | - self updateRecordsTable: presenter. - self updateWindowsPresenter: presenter ]. + selectedHistory := self getHistoryFrom: presenter selectedItem. + self updateRecordsTable. + self updateWindowsPresenter ]. - recordsFilter whenChangedDo: [ fileListPresenter selectedItem ifNotNil: [ self updateRecordsTable: fileListPresenter ] ] + recordsFilter whenChangedDo: [ self updateRecordsTable ] ] { #category : 'layout' } @@ -214,6 +216,7 @@ DSRecordBrowserPresenter >> filterRecordsButton [ DSRecordBrowserPresenter >> getHistoryFrom: aFileReference [ "Returns the generated history using the specified file reference which should countains DSSpy records." + aFileReference ifNil: [ ^ nil ]. ^ DSRecordHistory on: (DSSpy materialize: aFileReference) ] @@ -387,6 +390,18 @@ DSRecordBrowserPresenter >> removeFile: aFileReference [ fileListPresenter selectItem: (files ifNotEmpty: [ files last ]) ] +{ #category : 'accessing' } +DSRecordBrowserPresenter >> selectedHistory [ + + ^ selectedHistory +] + +{ #category : 'accessing' } +DSRecordBrowserPresenter >> selectedHistory: anHistory [ + + selectedHistory := anHistory +] + { #category : 'layout' } DSRecordBrowserPresenter >> startRecordButton [ "Instanciates a button that starts the DSSpy recording session on click." @@ -482,19 +497,18 @@ DSRecordBrowserPresenter >> updateLastRecord: aRecord [ ] { #category : 'operations' } -DSRecordBrowserPresenter >> updateRecordsTable: filesPresenter [ +DSRecordBrowserPresenter >> updateRecordsTable [ "Updates the records' table presenter and add to each record its corresponding color." - | fileRef recordColorAssociations | + | recordColorAssociations | recordColorAssociations := Array new. - fileRef := filesPresenter selectedItem. - fileRef ifNotNil: [ - recordColorAssociations := self getRecordColorAssociationsFrom: (self getHistoryFrom: fileRef) windows. + selectedHistory ifNotNil: [ + recordColorAssociations := self getRecordColorAssociationsFrom: selectedHistory windows. recordColorAssociations := recordColorAssociations reject: [ :association | recordsFilter chosenItems includes: association key class ] ]. - recordsTablePresenter roots: recordColorAssociations + recordsTablePresenter roots: recordColorAssociations ] { #category : 'layout' } @@ -505,13 +519,10 @@ DSRecordBrowserPresenter >> updateToolbar [ ] { #category : 'operations' } -DSRecordBrowserPresenter >> updateWindowsPresenter: aFileListPresenter [ +DSRecordBrowserPresenter >> updateWindowsPresenter [ "Updates the windows presenter by setting its roots by using the files presenter selected item." - | fileRef | - fileRef := aFileListPresenter selectedItem. - - fileRef ifNotNil: [ windowsPresenter roots: (self getHistoryFrom: fileRef) windows ] + selectedHistory ifNil: [ windowsPresenter roots: { } ] ifNotNil: [ windowsPresenter roots: selectedHistory windows ] ] { #category : 'accessing' } From 9a10e90eb4177719e0e5ad6b96059b4408300b88 Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Thu, 16 Apr 2026 16:55:04 +0200 Subject: [PATCH 10/22] feat: color indicator in windows tab and some statistics in dedicated tab --- .../DSAbstractEventRecord.extension.st | 7 ++ .../DSRecordBrowserPresenter.class.st | 66 ++++++++++++------- .../DSWindowRecord.extension.st | 7 ++ 3 files changed, 55 insertions(+), 25 deletions(-) diff --git a/DebuggingSpy-Browser/DSAbstractEventRecord.extension.st b/DebuggingSpy-Browser/DSAbstractEventRecord.extension.st index 5696c56..496830f 100644 --- a/DebuggingSpy-Browser/DSAbstractEventRecord.extension.st +++ b/DebuggingSpy-Browser/DSAbstractEventRecord.extension.st @@ -15,3 +15,10 @@ DSAbstractEventRecord class >> getLeafSubClasses [ ^ classes ] + +{ #category : '*DebuggingSpy-Browser' } +DSAbstractEventRecord >> ifWindow: aValue ifRecord: anotherValue [ + "If the object is a DSWindowRecord, returns aValue, and returns the other value otherwise." + + ^ anotherValue +] diff --git a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st index f0d9d45..3e5dc98 100644 --- a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st +++ b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st @@ -148,7 +148,8 @@ DSRecordBrowserPresenter >> connectPresenters [ fileListPresenter whenSelectionChangedDo: [ :presenter | selectedHistory := self getHistoryFrom: presenter selectedItem. self updateRecordsTable. - self updateWindowsPresenter ]. + self updateWindowsPresenter. + self updateStatisticsPresenter ]. recordsFilter whenChangedDo: [ self updateRecordsTable ] ] @@ -239,7 +240,7 @@ DSRecordBrowserPresenter >> getTableRowColorFor: anAssociation [ "Returns the row's corresponding color depending of the table selected row." anAssociation = recordsTablePresenter selectedItem - ifTrue: [ ^ anAssociation value darker ] + ifTrue: [ ^ anAssociation value muchDarker ] ifFalse: [ ^ anAssociation value ] ] @@ -247,9 +248,7 @@ DSRecordBrowserPresenter >> getTableRowColorFor: anAssociation [ DSRecordBrowserPresenter >> getWindowFromRecord: aRecord [ "Returns the record's corresponding window record in the history." - | rawRecords | - rawRecords := DSSpy materialize: fileListPresenter selectedItem. - ^ ((DSRecordHistory on: rawRecords) windows select: [ :window | window windowId = aRecord windowId ]) first + ^ (selectedHistory windows select: [ :window | window windowId = aRecord windowId ]) first ] { #category : 'initialization' } @@ -283,7 +282,7 @@ DSRecordBrowserPresenter >> listAddedFilesActions [ iconName: #history; description: 'Inspect the record history'; shortcutKey: $h meta; - action: [ (self getHistoryFrom: fileListPresenter selectedItem) inspect ] ]; + action: [ selectedHistory inspect ] ]; addActionWith: [ :anItem | anItem name: 'Remove'; @@ -432,12 +431,6 @@ DSRecordBrowserPresenter >> statisticsPresenter [ "Instanciates a new records table that displays data based on the selected file's records." ^ SpGridLayout new - add: 'Amount of events:' atPoint: 1 @ 1; - add: (self newText appendText: 'test') atPoint: 2 @ 1; - add: 'Amount of windows:' atPoint: 1 @ 2; - add: (self newText appendText: 'test') atPoint: 2 @ 2; - add: 'Record duration:' atPoint: 1 @ 3; - add: (self newText appendText: 'test') atPoint: 2 @ 3; beColumnNotHomogeneous; yourself ] @@ -511,6 +504,20 @@ DSRecordBrowserPresenter >> updateRecordsTable [ recordsTablePresenter roots: recordColorAssociations ] +{ #category : 'operations' } +DSRecordBrowserPresenter >> updateStatisticsPresenter [ + "Updates the different fields in the statistics presenter depending on the selected history." + + | stats | + selectedHistory ifNil: [ ^ self ]. + stats := { + ('Amount of events: ' , selectedHistory records size asString). + ('Amount of windows: ' , selectedHistory windows size asString). + ('Time taken: ' , (Time fromSeconds: selectedHistory stopTime asSeconds - selectedHistory startTime asSeconds) print24) }. + + stats doWithIndex: [ :stat :index | statisticsPresenter add: stat asPresenter atPoint: 1 @ index ] +] + { #category : 'layout' } DSRecordBrowserPresenter >> updateToolbar [ @@ -539,33 +546,42 @@ DSRecordBrowserPresenter >> windowTitle [ { #category : 'layout' } DSRecordBrowserPresenter >> windowsPresenter [ - "Instanciates a new records table that displays data based on the selected file's records." + "Instanciates a new table that displays the windows and their events as children. For each column, the manipulated object could be either a DSWindowRecord or a record that inherits from DSAbstractEventRecord." ^ self newTreeTable + addColumn: (SpStringTableColumn new + width: 4; + beNotExpandable; + evaluated: [ nil ]; + yourself); + addColumn: (SpStringTableColumn new + width: 16; + beNotExpandable; + displayBackgroundColor: [ :anItem | + anItem ifWindow: anItem windowColor ifRecord: (self getWindowFromRecord: anItem) windowColor ]; + evaluated: [ nil ]; + yourself); addColumn: (SpStringTableColumn new title: 'Window / Event'; - evaluated: [ :anItem | anItem asString ]; + evaluated: [ :anItem | + anItem + ifWindow: (anItem asString asText + addAttribute: TextBackgroundColor red; + yourself) + ifRecord: anItem asString ]; yourself); addColumn: (SpStringTableColumn new title: 'Type'; - evaluated: [ :anItem | - anItem class = DSWindowRecord - ifTrue: [ anItem windowType ] - ifFalse: [ anItem class name ] ]; + evaluated: [ :anItem | anItem ifWindow: anItem windowType ifRecord: anItem class name ]; yourself); addColumn: (SpStringTableColumn new title: 'Nb of events / Time'; evaluated: [ :anItem | - anItem class = DSWindowRecord - ifTrue: [ anItem events size asString , ' events' ] - ifFalse: [ self printAsFormattedTime: anItem dateTime ] ]; + anItem ifWindow: anItem events size asString , ' events' ifRecord: (self printAsFormattedTime: anItem dateTime) ]; yourself); beResizable; actions: self windowsPresenterActions; - children: [ :item | - item class = DSWindowRecord - ifTrue: [ item events ] - ifFalse: [ { } ] ]; + children: [ :item | item ifWindow: item events ifRecord: { } ]; yourself ] diff --git a/DebuggingSpy-Browser/DSWindowRecord.extension.st b/DebuggingSpy-Browser/DSWindowRecord.extension.st index 99ca3e7..7d05e0d 100644 --- a/DebuggingSpy-Browser/DSWindowRecord.extension.st +++ b/DebuggingSpy-Browser/DSWindowRecord.extension.st @@ -1,5 +1,12 @@ Extension { #name : 'DSWindowRecord' } +{ #category : '*DebuggingSpy-Browser' } +DSWindowRecord >> ifWindow: aValue ifRecord: anotherValue [ + "If the object is a DSWindowRecord, returns aValue, and returns the other value otherwise." + + ^ aValue +] + { #category : '*DebuggingSpy-Browser' } DSWindowRecord >> windowColor [ "Returns the toolinfo associated window color, and the default color if undefined." From 5e060b5a656ab2af996589b9c9ceeb8fd46cef58 Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Fri, 17 Apr 2026 10:51:26 +0200 Subject: [PATCH 11/22] refactoring(windows-tab): some refactoring in the evaluated methods --- .../DSAbstractEventRecord.extension.st | 27 ++++++++++++++-- .../DSRecordBrowserPresenter.class.st | 31 ++++++------------- .../DSWindowRecord.extension.st | 19 ++++++++++-- 3 files changed, 50 insertions(+), 27 deletions(-) diff --git a/DebuggingSpy-Browser/DSAbstractEventRecord.extension.st b/DebuggingSpy-Browser/DSAbstractEventRecord.extension.st index 496830f..471e082 100644 --- a/DebuggingSpy-Browser/DSAbstractEventRecord.extension.st +++ b/DebuggingSpy-Browser/DSAbstractEventRecord.extension.st @@ -17,8 +17,29 @@ DSAbstractEventRecord class >> getLeafSubClasses [ ] { #category : '*DebuggingSpy-Browser' } -DSAbstractEventRecord >> ifWindow: aValue ifRecord: anotherValue [ - "If the object is a DSWindowRecord, returns aValue, and returns the other value otherwise." +DSAbstractEventRecord >> printAsFormattedTime [ + "Returns the specified date and time as a string of format hh:mm:ss.nnnnnnnnn" - ^ anotherValue + ^ (String new: 18 streamContents: [ :aStream | dateTime asTime print24: true showSeconds: true on: aStream ]) asText allBold +] + +{ #category : '*DebuggingSpy-Browser' } +DSAbstractEventRecord >> type [ + "Returns the record's type to be displayed in the windows presenter." + + ^ self class name +] + +{ #category : '*DebuggingSpy-Browser' } +DSAbstractEventRecord >> window [ + "Returns the record's window from the browser selected history." + + ^ DSRecordBrowserPresenter uniqueInstance getWindowFromRecord: self +] + +{ #category : '*DebuggingSpy-Browser' } +DSAbstractEventRecord >> windowColor [ + "Returns the record's window color." + + ^ self window windowColor ] diff --git a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st index 3e5dc98..09f5af5 100644 --- a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st +++ b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st @@ -309,13 +309,6 @@ DSRecordBrowserPresenter >> openAddFileDialog [ newFiles ifNotNil: [ newFiles do: [ :file | self addFile: file asFileReference ] ] ] -{ #category : 'printing' } -DSRecordBrowserPresenter >> printAsFormattedTime: aDateAndTime [ - "Returns the specified date and time as a string of format hh:mm:ss.nnnnnnnnn" - - ^ String new: 18 streamContents: [ :aStream | aDateAndTime asTime print24: true showSeconds: true on: aStream ] -] - { #category : 'layout' } DSRecordBrowserPresenter >> recordsFilter [ "Instanciates a new chooser that displays every record classes that could be used to filter records in table." @@ -343,7 +336,7 @@ DSRecordBrowserPresenter >> recordsTable [ addColumn: (SpStringTableColumn new title: 'Time'; displayBackgroundColor: [ :association | self getTableRowColorFor: association ]; - evaluated: [ :association | self printAsFormattedTime: association key dateTime ]; + evaluated: [ :association | association key printAsFormattedTime ]; displayColor: [ :aRecord | Color white ]; yourself); beResizable; @@ -557,31 +550,27 @@ DSRecordBrowserPresenter >> windowsPresenter [ addColumn: (SpStringTableColumn new width: 16; beNotExpandable; - displayBackgroundColor: [ :anItem | - anItem ifWindow: anItem windowColor ifRecord: (self getWindowFromRecord: anItem) windowColor ]; + displayBackgroundColor: [ :anItem | anItem windowColor ]; evaluated: [ nil ]; yourself); addColumn: (SpStringTableColumn new title: 'Window / Event'; - evaluated: [ :anItem | - anItem - ifWindow: (anItem asString asText - addAttribute: TextBackgroundColor red; - yourself) - ifRecord: anItem asString ]; + evaluated: [ :anItem | anItem asString ]; yourself); addColumn: (SpStringTableColumn new title: 'Type'; - evaluated: [ :anItem | anItem ifWindow: anItem windowType ifRecord: anItem class name ]; + evaluated: [ :anItem | anItem type ]; yourself); addColumn: (SpStringTableColumn new - title: 'Nb of events / Time'; - evaluated: [ :anItem | - anItem ifWindow: anItem events size asString , ' events' ifRecord: (self printAsFormattedTime: anItem dateTime) ]; + title: 'Time'; + evaluated: [ :anItem | anItem printAsFormattedTime ]; yourself); beResizable; actions: self windowsPresenterActions; - children: [ :item | item ifWindow: item events ifRecord: { } ]; + children: [ :item | + item class = DSWindowRecord + ifTrue: [ item events ] + ifFalse: [ { } ] ]; yourself ] diff --git a/DebuggingSpy-Browser/DSWindowRecord.extension.st b/DebuggingSpy-Browser/DSWindowRecord.extension.st index 7d05e0d..1c7a939 100644 --- a/DebuggingSpy-Browser/DSWindowRecord.extension.st +++ b/DebuggingSpy-Browser/DSWindowRecord.extension.st @@ -1,10 +1,23 @@ Extension { #name : 'DSWindowRecord' } { #category : '*DebuggingSpy-Browser' } -DSWindowRecord >> ifWindow: aValue ifRecord: anotherValue [ - "If the object is a DSWindowRecord, returns aValue, and returns the other value otherwise." +DSWindowRecord >> printAsFormattedTime [ + "Returns the formatted time to be displayed in the windows presenter." - ^ aValue + ^ nil +] + +{ #category : '*DebuggingSpy-Browser' } +DSWindowRecord >> type [ + "Returns the window's type to be displayed in the windows presenter." + + ^ self windowType , ' (' , events size asString , ' events)' +] + +{ #category : '*DebuggingSpy-Browser' } +DSWindowRecord >> window [ + + ^ self ] { #category : '*DebuggingSpy-Browser' } From a933fac78e55fd883b32b7705887c9fcc61d5a74 Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Fri, 17 Apr 2026 10:59:38 +0200 Subject: [PATCH 12/22] feat(colors): color indicator on records table --- .../DSRecordBrowserPresenter.class.st | 12 ++++++------ .../StCritiquePackageSelectorPresenter.extension.st | 2 +- .../StRewriterExpressionFinderPresenter.extension.st | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st index 09f5af5..1139440 100644 --- a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st +++ b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st @@ -321,23 +321,23 @@ DSRecordBrowserPresenter >> recordsTable [ "Instanciates a new records table that displays data based on the selected file's records." ^ self newTreeTable + addColumn: (SpStringTableColumn new + displayBackgroundColor: [ :association | association key windowColor ]; + width: 4; + beNotExpandable; + evaluated: [ nil ]; + yourself); addColumn: (SpStringTableColumn new title: 'Event'; - displayBackgroundColor: [ :association | self getTableRowColorFor: association ]; evaluated: [ :association | association key eventName asString ]; - displayColor: [ :aRecord | Color white ]; yourself); addColumn: (SpStringTableColumn new title: 'Type'; - displayBackgroundColor: [ :association | self getTableRowColorFor: association ]; evaluated: [ :association | association key class asString ]; - displayColor: [ :aRecord | Color white ]; yourself); addColumn: (SpStringTableColumn new title: 'Time'; - displayBackgroundColor: [ :association | self getTableRowColorFor: association ]; evaluated: [ :association | association key printAsFormattedTime ]; - displayColor: [ :aRecord | Color white ]; yourself); beResizable; actions: self recordsTableActions; diff --git a/DebuggingSpy-Browser/StCritiquePackageSelectorPresenter.extension.st b/DebuggingSpy-Browser/StCritiquePackageSelectorPresenter.extension.st index c21d065..976836d 100644 --- a/DebuggingSpy-Browser/StCritiquePackageSelectorPresenter.extension.st +++ b/DebuggingSpy-Browser/StCritiquePackageSelectorPresenter.extension.st @@ -4,7 +4,7 @@ Extension { #name : 'StCritiquePackageSelectorPresenter' } StCritiquePackageSelectorPresenter class >> windowColor [ - ^ Color fromHexString: '#ff8f1f' + ^ Color fromHexString: '#ff9100' ] { #category : '*DebuggingSpy-Browser' } diff --git a/DebuggingSpy-Browser/StRewriterExpressionFinderPresenter.extension.st b/DebuggingSpy-Browser/StRewriterExpressionFinderPresenter.extension.st index 97b859e..d563b91 100644 --- a/DebuggingSpy-Browser/StRewriterExpressionFinderPresenter.extension.st +++ b/DebuggingSpy-Browser/StRewriterExpressionFinderPresenter.extension.st @@ -4,7 +4,7 @@ Extension { #name : 'StRewriterExpressionFinderPresenter' } StRewriterExpressionFinderPresenter class >> windowColor [ - ^ Color fromHexString: '#292929' + ^ Color fromHexString: '#ffffff' ] { #category : '*DebuggingSpy-Browser' } From 681fb2f377a112239a25ca9f7e966df9a25c122d Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Fri, 17 Apr 2026 11:36:34 +0200 Subject: [PATCH 13/22] fix(history): timeTaken and computeIdleTime + fix absoluteTimeTaken --- .../DSRecordHistoryTest.class.st | 40 ++++++++++++++++++- DebuggingSpy/DSRecordHistory.class.st | 16 ++++++-- 2 files changed, 51 insertions(+), 5 deletions(-) diff --git a/DebuggingSpy-Tests/DSRecordHistoryTest.class.st b/DebuggingSpy-Tests/DSRecordHistoryTest.class.st index dac60e6..0fdb164 100644 --- a/DebuggingSpy-Tests/DSRecordHistoryTest.class.st +++ b/DebuggingSpy-Tests/DSRecordHistoryTest.class.st @@ -44,7 +44,7 @@ DSRecordHistoryTest >> setUp [ DSRecordHistoryTest >> testAbsoluteTimeTaken [ history records: self getRecordsExample. - self assert: history absoluteTimeTaken equals: 22 + self assert: history absoluteTimeTaken equals: 22 * 60 ] { #category : 'tests' } @@ -374,6 +374,26 @@ DSRecordHistoryTest >> testCollectTimeDiscrepancies [ self assert: deltaDict third key second class equals: DSClipboardCopyRecord ] +{ #category : 'tests' } +DSRecordHistoryTest >> testComputeIdleTime [ + + | idleTime | + history records: { + (DSMouseEnterWindowRecord new dateTime: '2024-09-23T15:02:44' asDateAndTime). + (DSDoItRecord new dateTime: '2024-09-23T15:02:47' asDateAndTime). + (DSStepIntoRecord new dateTime: '2024-09-23T15:02:54' asDateAndTime). + (DSDebugItRecord new dateTime: '2024-09-23T15:02:56' asDateAndTime). + (DSMouseLeaveWindowRecord new dateTime: '2024-09-23T15:03:00' asDateAndTime). + (DSWindowClosedRecord new dateTime: '2024-09-23T15:03:03' asDateAndTime). + (DSMouseEnterWindowRecord new dateTime: '2024-09-23T15:06:07' asDateAndTime). + (DSPrintItRecord new dateTime: '2024-09-23T15:06:10' asDateAndTime). + (DSClipboardCopyRecord new dateTime: '2024-09-23T15:06:26' asDateAndTime). + (DSMethodRemovedRecord new dateTime: '2024-09-23T15:06:30' asDateAndTime) }. + + idleTime := history computeIdleTime. + self assert: idleTime equals: 7 + 184 + 16 +] + { #category : 'tests' } DSRecordHistoryTest >> testCountDebugActions [ @@ -1126,6 +1146,24 @@ DSRecordHistoryTest >> testStopTime [ self assert: history stopTime equals: '15:24:44' asTime ] +{ #category : 'tests' } +DSRecordHistoryTest >> testTimeTaken [ + + history records: { + (DSMouseEnterWindowRecord new dateTime: '2024-09-23T15:02:44' asDateAndTime). + (DSDoItRecord new dateTime: '2024-09-23T15:02:47' asDateAndTime). + (DSStepIntoRecord new dateTime: '2024-09-23T15:02:54' asDateAndTime). + (DSDebugItRecord new dateTime: '2024-09-23T15:02:56' asDateAndTime). + (DSMouseLeaveWindowRecord new dateTime: '2024-09-23T15:03:00' asDateAndTime). + (DSWindowClosedRecord new dateTime: '2024-09-23T15:03:03' asDateAndTime). + (DSMouseEnterWindowRecord new dateTime: '2024-09-23T15:06:07' asDateAndTime). + (DSPrintItRecord new dateTime: '2024-09-23T15:06:10' asDateAndTime). + (DSClipboardCopyRecord new dateTime: '2024-09-23T15:06:26' asDateAndTime). + (DSMethodRemovedRecord new dateTime: '2024-09-23T15:06:30' asDateAndTime) }. + + self assert: history timeTaken equals: 3 * 60 + 46 - (7 + 184 + 16) +] + { #category : 'tests' } DSRecordHistoryTest >> testToolInfosFor [ diff --git a/DebuggingSpy/DSRecordHistory.class.st b/DebuggingSpy/DSRecordHistory.class.st index 90c86c2..c09df26 100644 --- a/DebuggingSpy/DSRecordHistory.class.st +++ b/DebuggingSpy/DSRecordHistory.class.st @@ -57,8 +57,7 @@ DSRecordHistory class >> windowLeaveEventTypes [ DSRecordHistory >> absoluteTimeTaken [ "The absolute time taken to perform the recording of user events, including unmonitoring activities (interruptions or activities outside the IDE)." - ^ ((records last dateTime asSeconds - records first dateTime asSeconds) - / 60) asFloat + ^ records last dateTime asSeconds - records first dateTime asSeconds ] { #category : 'API-history' } @@ -165,6 +164,15 @@ DSRecordHistory >> collectTimeDiscrepancies [ ^ deltas ] +{ #category : 'API-history' } +DSRecordHistory >> computeIdleTime [ + "Returns the sum of all time discrepancies durations and returns the result as a number of seconds." + + | associations | + associations := self collectTimeDiscrepancies collect: [ :association | association value asSeconds ]. + ^ associations sum +] + { #category : 'API-history' } DSRecordHistory >> countDebugActions [ @@ -609,8 +617,8 @@ DSRecordHistory >> timeTaken [ - last log minus the first log timestamp minus time gaps (or discrepancies) - time gaps are calculated as the sum of time differences between two following events with a time delta > 5 min. We consider that, if the user did not do anything (basically typing or moving the mouse) for more than 5 min, the she was away from the task." - ^ ((records last dateTime asSeconds - records first dateTime asSeconds - - self collectTimeDiscrepancies) / 60) asFloat + + ^ self absoluteTimeTaken - self computeIdleTime ] { #category : 'accessing' } From bb9fae242c98a0ee6bc222b03247ad96c532ce81 Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Fri, 17 Apr 2026 12:05:07 +0200 Subject: [PATCH 14/22] feat(windows-tab): display time taken, idle time and fix when no idle time fix: sort color referential by hue --- .../DSRecordBrowserPresenter.class.st | 21 ++++++++++++++++--- .../DebugPointBrowserPresenter.extension.st | 2 +- .../DSRecordHistoryTest.class.st | 10 ++++++--- DebuggingSpy/DSRecordHistory.class.st | 1 + 4 files changed, 27 insertions(+), 7 deletions(-) diff --git a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st index 1139440..b3271ba 100644 --- a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st +++ b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st @@ -89,6 +89,13 @@ DSRecordBrowserPresenter class >> uniqueInstance [ ^ uniqueInstance ifNil: [ uniqueInstance := self new ] ] +{ #category : 'windows' } +DSRecordBrowserPresenter class >> windowColor [ + + + ^ Color fromHexString: '#ec45ff' +] + { #category : 'accessing' } DSRecordBrowserPresenter class >> windowColorFrom: anObject [ "If the specified object is nil, returns the default windowColor, else return its window color." @@ -97,6 +104,12 @@ DSRecordBrowserPresenter class >> windowColorFrom: anObject [ ^ anObject windowColor ] +{ #category : 'accessing' } +DSRecordBrowserPresenter class >> windowType [ + + ^ 'Debugging Spy browser' +] + { #category : 'files' } DSRecordBrowserPresenter >> addFile: aFileReference [ "Adds a file in the presenter and set is as selected, which updates the records displayed." @@ -136,7 +149,7 @@ DSRecordBrowserPresenter >> colorReferential [ evaluated: [ :association | association value ]; displayColor: [ :aRecord | Color white ]; yourself); - roots: self class colorAssociations; + roots: (self class colorAssociations sort: [ :a :b | a key hue <= b key hue ]); beResizable; yourself ] @@ -506,7 +519,9 @@ DSRecordBrowserPresenter >> updateStatisticsPresenter [ stats := { ('Amount of events: ' , selectedHistory records size asString). ('Amount of windows: ' , selectedHistory windows size asString). - ('Time taken: ' , (Time fromSeconds: selectedHistory stopTime asSeconds - selectedHistory startTime asSeconds) print24) }. + ('Time taken: ' , (Time fromSeconds: selectedHistory timeTaken) print24). + ('Idle time: ' , (Time fromSeconds: selectedHistory computeIdleTime) print24). + ('Absolute time taken: ' , (Time fromSeconds: selectedHistory absoluteTimeTaken) print24) }. stats doWithIndex: [ :stat :index | statisticsPresenter add: stat asPresenter atPoint: 1 @ index ] ] @@ -585,6 +600,6 @@ DSRecordBrowserPresenter >> windowsPresenterActions [ iconName: #inspect; description: 'Inspect the selected element.'; shortcutKey: $i meta; - action: [ windowsPresenter selectedItem key inspect ] ]; + action: [ windowsPresenter selectedItem inspect ] ]; yourself ] diff --git a/DebuggingSpy-Browser/DebugPointBrowserPresenter.extension.st b/DebuggingSpy-Browser/DebugPointBrowserPresenter.extension.st index 122134e..7ccb3a1 100644 --- a/DebuggingSpy-Browser/DebugPointBrowserPresenter.extension.st +++ b/DebuggingSpy-Browser/DebugPointBrowserPresenter.extension.st @@ -4,7 +4,7 @@ Extension { #name : 'DebugPointBrowserPresenter' } DebugPointBrowserPresenter class >> windowColor [ - ^ Color fromHexString: '#ff0fef' + ^ Color fromHexString: '#772980' ] { #category : '*DebuggingSpy-Browser' } diff --git a/DebuggingSpy-Tests/DSRecordHistoryTest.class.st b/DebuggingSpy-Tests/DSRecordHistoryTest.class.st index 0fdb164..1e4bad8 100644 --- a/DebuggingSpy-Tests/DSRecordHistoryTest.class.st +++ b/DebuggingSpy-Tests/DSRecordHistoryTest.class.st @@ -377,7 +377,12 @@ DSRecordHistoryTest >> testCollectTimeDiscrepancies [ { #category : 'tests' } DSRecordHistoryTest >> testComputeIdleTime [ - | idleTime | + history records: { + (DSMouseEnterWindowRecord new dateTime: '2024-09-23T15:02:44' asDateAndTime). + (DSDoItRecord new dateTime: '2024-09-23T15:02:47' asDateAndTime) }. + + self assert: history computeIdleTime equals: 0. + history records: { (DSMouseEnterWindowRecord new dateTime: '2024-09-23T15:02:44' asDateAndTime). (DSDoItRecord new dateTime: '2024-09-23T15:02:47' asDateAndTime). @@ -390,8 +395,7 @@ DSRecordHistoryTest >> testComputeIdleTime [ (DSClipboardCopyRecord new dateTime: '2024-09-23T15:06:26' asDateAndTime). (DSMethodRemovedRecord new dateTime: '2024-09-23T15:06:30' asDateAndTime) }. - idleTime := history computeIdleTime. - self assert: idleTime equals: 7 + 184 + 16 + self assert: history computeIdleTime equals: 7 + 184 + 16 ] { #category : 'tests' } diff --git a/DebuggingSpy/DSRecordHistory.class.st b/DebuggingSpy/DSRecordHistory.class.st index c09df26..749d0e6 100644 --- a/DebuggingSpy/DSRecordHistory.class.st +++ b/DebuggingSpy/DSRecordHistory.class.st @@ -170,6 +170,7 @@ DSRecordHistory >> computeIdleTime [ | associations | associations := self collectTimeDiscrepancies collect: [ :association | association value asSeconds ]. + associations ifEmpty: [ ^ 0 ]. ^ associations sum ] From 5ed9f862e59a665fb587cb0ecbfe6c9248cac72d Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Fri, 17 Apr 2026 14:16:53 +0200 Subject: [PATCH 15/22] fix: debugging spy windowType --- DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st index b3271ba..9c29460 100644 --- a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st +++ b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st @@ -107,7 +107,7 @@ DSRecordBrowserPresenter class >> windowColorFrom: anObject [ { #category : 'accessing' } DSRecordBrowserPresenter class >> windowType [ - ^ 'Debugging Spy browser' + ^ 'Debugging Spy' ] { #category : 'files' } From f9f61b92a464dec125934653c2d59cc8ef27e3d8 Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Fri, 17 Apr 2026 14:57:05 +0200 Subject: [PATCH 16/22] test: updateStatisticsPresenter --- .../DSRecordBrowserPresenterTest.class.st | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st b/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st index 10804b9..70d624c 100644 --- a/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st +++ b/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st @@ -91,6 +91,12 @@ DSRecordBrowserPresenterTest >> setUp [ browser := DSRecordBrowserPresenter new ] +{ #category : 'helpers' } +DSRecordBrowserPresenterTest >> statisticsPresenter [ + + ^ browser presenterAt: #statisticsPresenter +] + { #category : 'running' } DSRecordBrowserPresenterTest >> tearDown [ @@ -372,6 +378,25 @@ DSRecordBrowserPresenterTest >> testUpdateRecordsTableWhenAddingFile [ self assert: self recordsTablePresenter roots last key class equals: DSInspectItRecord ] +{ #category : 'tests' } +DSRecordBrowserPresenterTest >> testUpdateStatisticsPresenter [ + + | children | + self assert: browser updateStatisticsPresenter equals: browser. + + browser selectedHistory: (browser getHistoryFrom: self generateRecordsFile). + browser updateStatisticsPresenter. + + children := self statisticsPresenter children. + self assert: children size equals: 5. + + self assert: children keys first label equals: 'Amount of events: 4'. + self assert: children keys second label equals: 'Amount of windows: 4'. + self assert: children keys third label equals: 'Time taken: 00:00:03'. + self assert: children keys fourth label equals: 'Idle time: 00:00:00'. + self assert: children keys last label equals: 'Absolute time taken: 00:00:03' +] + { #category : 'tests' } DSRecordBrowserPresenterTest >> testUpdateWindowsPresenter [ From a3696f19bb063cd8307dd0dc0464c6c6e9e70927 Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Fri, 17 Apr 2026 15:05:50 +0200 Subject: [PATCH 17/22] test: remove deprecated tests & fix failing tests --- .../DSRecordBrowserPresenterTest.class.st | 18 ++++++------------ .../DSRecordBrowserPresenter.class.st | 9 --------- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st b/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st index 70d624c..c64b071 100644 --- a/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st +++ b/DebuggingSpy-Browser-Tests/DSRecordBrowserPresenterTest.class.st @@ -167,15 +167,18 @@ DSRecordBrowserPresenterTest >> testColorAssociations [ | associations | associations := { ((Color fromHexString: '#1f48ff') -> 'Browser'). - ((Color fromHexString: '#ff0fef') -> 'Debug point browser'). + ((Color fromHexString: '#772980') -> 'Debug point browser'). ((Color fromHexString: '#345e54') -> 'Epicea'). ((Color fromHexString: '#00e5ff') -> 'Iceberg'). - ((Color fromHexString: '#ff8f1f') -> 'Critique browser'). + ((Color fromHexString: '#ff9100') -> 'Critique browser'). ((Color fromHexString: '#ff2200') -> 'Debugger'). ((Color fromHexString: '#fad314') -> 'Inspector'). ((Color fromHexString: '#70B77E') -> 'Playground'). - ((Color fromHexString: '#292929') -> 'Rewriter') }. + ((Color fromHexString: '#ffffff') -> 'Rewriter'). + ((Color fromHexString: '#ec45ff') -> 'Debugging Spy'). + ((Color fromHexString: '#b3b3b3') -> 'Unknown window') }. + self assert: associations size equals: DSRecordBrowserPresenter colorAssociations size. self assert: (associations allSatisfy: [ :asso | DSRecordBrowserPresenter colorAssociations includes: asso ]) ] @@ -271,15 +274,6 @@ DSRecordBrowserPresenterTest >> testGetWindowFromRecord [ self assert: window name equals: record windowId ] -{ #category : 'tests' } -DSRecordBrowserPresenterTest >> testPrintAsFormattedTime [ - self assert: (browser printAsFormattedTime: (Time - hour: 1 - minute: 2 - second: 3 - nanoSecond: 123456789) asDateAndTime) equals: '01:02:03.123456789' -] - { #category : 'tests' } DSRecordBrowserPresenterTest >> testRemoveFile [ diff --git a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st index 9c29460..830b00e 100644 --- a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st +++ b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st @@ -248,15 +248,6 @@ DSRecordBrowserPresenter >> getRecordColorAssociationsFrom: aWindowRecordCollect ^ recordColorsAssociations sorted: [ :recordA :recordB | recordA key dateTime < recordB key dateTime ] ] -{ #category : 'helpers' } -DSRecordBrowserPresenter >> getTableRowColorFor: anAssociation [ - "Returns the row's corresponding color depending of the table selected row." - - anAssociation = recordsTablePresenter selectedItem - ifTrue: [ ^ anAssociation value muchDarker ] - ifFalse: [ ^ anAssociation value ] -] - { #category : 'helpers' } DSRecordBrowserPresenter >> getWindowFromRecord: aRecord [ "Returns the record's corresponding window record in the history." From 681373644f7a50e7df89e22ff58103a385ec94db Mon Sep 17 00:00:00 2001 From: Nicolas Potel Date: Fri, 17 Apr 2026 15:36:58 +0200 Subject: [PATCH 18/22] test: fix failing tests --- .../DSRecordBrowserPresenter.class.st | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st index 830b00e..211d27b 100644 --- a/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st +++ b/DebuggingSpy-Browser/DSRecordBrowserPresenter.class.st @@ -39,7 +39,7 @@ DSRecordBrowserPresenter class >> colorAssociations [ ] { #category : 'accessing' } -DSRecordBrowserPresenter class >> defaultExtent [ +DSRecordBrowserPresenter class >> defaultPreferredExtent [ ^ 1000 @ 600 ] @@ -74,6 +74,7 @@ DSRecordBrowserPresenter class >> resetBrowser [ DSRecordBrowserPresenter class >> toggleBrowser [ "Opens the browser or closes it depending on its state. If it needs to be created, then creates and opens it." +