'From Cuis 1.0 of 19 April 2009 [latest update: #187] on 10 May 2009 at 9:50:29 am'!

!MessageTally class methodsFor: 'spying' stamp: 'jmv 5/10/2009 09:39'!
spyAllOn: aBlock
	"Spy on all the processes in the system
	
	[1000 timesRepeat: [3.14159 printString. Processor yield]] fork.
	[1000 timesRepeat: [20 factorial. Processor yield]] fork.
	[1000 timesRepeat: [20 factorial. Processor yield]] fork.
	MessageTally spyAllOn: [ (Delay forMilliseconds: 100) wait]
	
	"
	| node result |
	node _ self new.
	result _ node spyAllEvery: self defaultPollPeriod on: aBlock.
	(StringHolder new contents: (String streamContents: [:s | node report: s; close]))
		openLabel: 'Spy Results' wrap: false.
	^ result! !

!MessageTally class methodsFor: 'spying' stamp: 'jmv 5/10/2009 09:39'!
spyOn: aBlock
	"
	[1000 timesRepeat: [
		100 timesRepeat: [120 factorial].
		(Delay forMilliseconds: 10) wait
		]] forkAt: 45 named: '45'.
	MessageTally spyOn: [10000 timesRepeat: [1.23 printString]]
	"
	| node result |
	node _ self new.
	result _ node spyEvery: self defaultPollPeriod on: aBlock.
	(StringHolder new contents: (String streamContents: [:s | node report: s; close]))
		openLabel: 'Spy Results' wrap: false.
	^ result! !

!MessageTally class methodsFor: 'spying' stamp: 'jmv 5/10/2009 09:39'!
spyOnProcess: aProcess forMilliseconds: msecDuration 
	"
	| p1 p2 |  
	p1 _ [100000 timesRepeat: [3.14159 printString. Processor yield]] fork.  
	p2 _ [100000 timesRepeat: [3.14159 printString. Processor yield]] fork.  
	(Delay forMilliseconds: 100) wait.  
	MessageTally spyOnProcess: p1 forMilliseconds: 1000
	"
	| node |
	node _ self new.
	node
		spyEvery: self defaultPollPeriod
		onProcess: aProcess
		forMilliseconds: msecDuration.
	(StringHolder new
		contents: (String
				streamContents: [:s | node report: s;
						 close]))
		openLabel: 'Spy Results' wrap: false! !

!MessageTally class methodsFor: 'spying' stamp: 'jmv 5/10/2009 09:39'!
tallySendsTo: receiver inBlock: aBlock showTree: treeOption
	"MessageTally tallySends: [3.14159 printString]"
	"This method uses the simulator to count the number of calls on each method
	invoked in evaluating aBlock. If receiver is not nil, then only sends
	to that receiver are tallied.
	Results are presented as leaves, sorted by frequency,
	preceded, optionally, by the whole tree."
	| prev tallies startTime totalTime |
	startTime _ Time millisecondClockValue.
	tallies _ MessageTally new class: aBlock receiver class
							method: aBlock method.
	prev _ aBlock.
	thisContext sender
		runSimulated: aBlock
		contextAtEachStep:
			[:current |
			current == prev ifFalse: 
				["call or return"
				prev sender == nil ifFalse: 
					["call only"
					(receiver == nil or: [current receiver == receiver])
						ifTrue: [tallies tally: current by: 1]].
				prev _ current]].

	totalTime _ Time millisecondClockValue - startTime // 1000.0 roundTo: 0.01.
	(StringHolder new contents:
		(String streamContents:
			[:s |
			s nextPutAll: 'This simulation took ' , totalTime printString
							, ' seconds.'; cr.
			treeOption
				ifTrue: [tallies fullPrintOn: s tallyExact: true orThreshold: 0]
				ifFalse: [tallies leavesPrintOn: s tallyExact: true orThreshold: 0].
			tallies close]))
		openLabel: 'Spy Results' wrap: false! !


!PluggableTextMorph methodsFor: 'accessing' stamp: 'jmv 5/10/2009 09:42'!
wrapFlag: aBoolean
	textMorph wrapFlag: aBoolean! !


!StringHolder methodsFor: 'initialize-release' stamp: 'jmv 5/10/2009 09:32'!
embeddedInMorphicWindowLabeled: labelString

	^self embeddedInMorphicWindowLabeled: labelString wrap: true! !

!StringHolder methodsFor: 'initialize-release' stamp: 'jmv 5/10/2009 09:42'!
embeddedInMorphicWindowLabeled: labelString wrap: aBoolean
	| window |
	window _ (SystemWindow labelled: labelString) model: self.
	window addMorph: ((PluggableTextMorph 
		on: self 
		text: #contents 
		accept: #acceptContents:
		readSelection: nil 
		menu: #codePaneMenu:shifted:)
			wrapFlag: aBoolean)
				frame: (0@0 corner: 1@1).
	^ window! !

!StringHolder methodsFor: 'initialize-release' stamp: 'jmv 5/10/2009 09:21'!
openLabel: aString 
	"Create a standard system view of the model, me, a StringHolder and open it.  If in mvc, terminate the active controller so that the new window will immediately be activated."
	self openAsMorphLabel: aString! !

!StringHolder methodsFor: 'initialize-release' stamp: 'jmv 5/10/2009 09:37'!
openLabel: aString wrap: aBoolean

	"Create a standard system view of the model, me, a StringHolder and open it."
	(self embeddedInMorphicWindowLabeled: aString wrap: aBoolean) openInWorld! !


!Utilities class methodsFor: 'miscellaneous' stamp: 'jmv 5/10/2009 09:22'!
reconstructTextWindowsFromFileNamed: aName
	"Utilities reconstructTextWindowsFromFileNamed: 'TextWindows'"
	| aReferenceStream aDict |
	aReferenceStream _ ReferenceStream fileNamed: aName.
	aDict _ aReferenceStream next.
	aReferenceStream close.
	aDict associationsDo:
		[:assoc |
			(StringHolder new contents: assoc value) openAsMorphLabel: assoc key ]! !

StringHolder removeSelector: #openLabel:andTerminate:!
