[Vm-dev] VM Maker: VMMakerUI-eem.1.mcz

commits at source.squeak.org commits at source.squeak.org
Sun Dec 22 18:21:36 UTC 2019


Eliot Miranda uploaded a new version of VMMakerUI to project VM Maker:
http://source.squeak.org/VMMaker/VMMakerUI-eem.1.mcz

==================== Summary ====================

Name: VMMakerUI-eem.1
Author: eem
Time: 22 December 2019, 10:21:35.048794 am
UUID: dbfca451-fef5-4248-8f2e-49793e2910f6
Ancestors: 

Move the Morphic GUI methods to VMMakerUI.
Add Marcel's gorgeous CogProcessorAlienInspector.

==================== Snapshot ====================

SystemOrganization addCategory: #'VMMakerUI-SqueakInspectors'!
SystemOrganization addCategory: #'VMMakerUI-InterpreterSimulation-Morphic'!

Model subclass: #CogProcessorAlienInspector
	instanceVariableNames: 'cogit coInterpreter objectMemory processor registerSelectors windowTitle registerCache'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'VMMakerUI-SqueakInspectors'!

!CogProcessorAlienInspector commentStamp: 'eem 12/22/2019 08:27' prior: 0!
A CogProcessorAlienInspector is an inspector for a CogProcessorAlien processor simulator that displays the processor simulator's register state.

Instance Variables
	processor:			<CogProcessorAlien>
	registerCache:		<Array of Integer>
	registerSelectors:	<Array of Symbol>
	windowTitle:		<String>!

----- Method: CogProcessorAlienInspector class>>open (in category 'instance creation') -----
open
	^ToolBuilder open:
		(self new
			processor: (Cogit classPool at: #ProcessorClass) new;
			yourself)!

----- Method: CogProcessorAlienInspector class>>openFor: (in category 'instance creation') -----
openFor: aCogit
	^ToolBuilder open: (self new cogit: aCogit; yourself)!

----- Method: CogProcessorAlienInspector>>bitsPerDigit (in category 'defaults') -----
bitsPerDigit
	"How to format the register state?"
	
	^ 4!

----- Method: CogProcessorAlienInspector>>buildWith: (in category 'building') -----
buildWith: builder

	| window registers |
	window := builder pluggableWindowSpec new.
	window
		model: self;
		label: #windowTitle;
		extent: 400 at 200;
		children: OrderedCollection new.
	registers := builder pluggableTextSpec new.
	registers
		model: self;
		font: Preferences standardFixedFont;
		getText: #text;
		frame: (0 at 0 corner: 1 at 1);
		yourself.
	window children add: registers.
	^(builder build: window)
		paneColor: coInterpreter windowColorToUse;
		yourself!

----- Method: CogProcessorAlienInspector>>cogit: (in category 'initialization') -----
cogit: aCogit
	cogit := aCogit.
	coInterpreter := cogit coInterpreter.
	objectMemory := coInterpreter objectMemory.
	processor := cogit processor.
	registerSelectors := OrderedCollection withAll: processor registerStateGetters!

----- Method: CogProcessorAlienInspector>>defaultWindowColor (in category 'accessing - ui') -----
defaultWindowColor

	^ Color fromString: '#6bca61'!

----- Method: CogProcessorAlienInspector>>digitsPerGroup (in category 'defaults') -----
digitsPerGroup
	"How to format the register state?"
	
	^ 2!

----- Method: CogProcessorAlienInspector>>evaluateExpression: (in category 'evaluation') -----
evaluateExpression: exp
	"Callback from text widget after do-it, print-it, inspect-it, etc... The return value will be fed  back."

	| register value |
	register := (exp asString findTokens: '=') first withBlanksTrimmed asLowercase asSymbol.
	value := self registerCache at: register.

	self interpret: register.
	
	^ value!

----- Method: CogProcessorAlienInspector>>initialize (in category 'initialization') -----
initialize

	super initialize.
	
	self registerSelectors: OrderedCollection new.
	
	self registerCache: IdentityDictionary new.!

----- Method: CogProcessorAlienInspector>>inspect: (in category 'initialization') -----
inspect: aRegisterSelector

	self registerSelectors add: aRegisterSelector.
	self changed: #text.!

----- Method: CogProcessorAlienInspector>>inspectAll: (in category 'initialization') -----
inspectAll: someRegisterSelectors

	self registerSelectors addAll: someRegisterSelectors.
	self changed: #text.!

----- Method: CogProcessorAlienInspector>>inspectNone (in category 'initialization') -----
inspectNone

	self registerSelectors removeAll.
	self changed: #text.!

----- Method: CogProcessorAlienInspector>>interpret: (in category 'evaluation') -----
interpret: registerSelector
	"Offer some ways of interpretation."
	
	| value options choice |

	self flag: #updates. "mt: The cache value corresponds maybe to the value at interaction time. In case the register changes quickly and it takes the user some time to make a choice?"
	value := self registerCache at: registerSelector.
	
	options := OrderedDictionary newFrom: {
		'Object' -> #interpret:asObject:.
		'Stack frame' -> #interpret:asStackFrame:.
		'Code address' -> #interpret:asCodeAddress:.
		'Integer' -> #interpret:asInteger:.
		'Character' -> #interpret:asCharacter:.
	}.
	
	choice := Project uiManager
		chooseFrom: options keys
		values: options values
		title: ('{1} {2}' format: {registerSelector asUppercase. coInterpreter whereIs: value}).
		
	choice ifNotNil:
		[:selector | self perform: selector with: registerSelector with: value]!

----- Method: CogProcessorAlienInspector>>interpret:asCharacter: (in category 'evaluation') -----
interpret: registerSelector asCharacter: registerValue
	
	registerValue asCharacter explore.!

----- Method: CogProcessorAlienInspector>>interpret:asCodeAddress: (in category 'evaluation') -----
interpret: registerSelector asCodeAddress: registerValue
	
	cogit disassembleCodeAt: registerValue!

----- Method: CogProcessorAlienInspector>>interpret:asInteger: (in category 'evaluation') -----
interpret: registerSelector asInteger: registerValue
	
	registerValue explore.!

----- Method: CogProcessorAlienInspector>>interpret:asObject: (in category 'evaluation') -----
interpret: registerSelector asObject: registerValue
	
	coInterpreter printOop: registerValue!

----- Method: CogProcessorAlienInspector>>interpret:asStackFrame: (in category 'evaluation') -----
interpret: registerSelector asStackFrame: registerValue
	
	coInterpreter printFrame: registerValue!

----- Method: CogProcessorAlienInspector>>interpret:asWhoKnows: (in category 'evaluation') -----
interpret: registerSelector asWhoKnows: registerValue
	
	UserDialogBoxMorph inform: (coInterpreter whereIs: registerValue) title: registerSelector!

----- Method: CogProcessorAlienInspector>>pcText (in category 'accessing - ui') -----
pcText

	^processor pc hex allButFirst: 3!

----- Method: CogProcessorAlienInspector>>processor (in category 'accessing') -----
processor
	^processor!

----- Method: CogProcessorAlienInspector>>processor: (in category 'accessing') -----
processor: aCogProcessorAlien
	processor := aCogProcessorAlien.
	registerSelectors := processor registerStateGetters.
	windowTitle := nil.
	self changed: #windowTitle.!

----- Method: CogProcessorAlienInspector>>registerAt: (in category 'accessing - ui') -----
registerAt: aRegisterSelector

	^ self alien perform: aRegisterSelector!

----- Method: CogProcessorAlienInspector>>registerCache (in category 'accessing') -----
registerCache

	^ registerCache!

----- Method: CogProcessorAlienInspector>>registerCache: (in category 'accessing') -----
registerCache: anObject

	registerCache := anObject.!

----- Method: CogProcessorAlienInspector>>registerSelectors (in category 'accessing') -----
registerSelectors

	^ registerSelectors!

----- Method: CogProcessorAlienInspector>>registerSelectors: (in category 'accessing') -----
registerSelectors: anObject

	registerSelectors := anObject.
	self changed: #text.!

----- Method: CogProcessorAlienInspector>>registerTextAt: (in category 'accessing - ui') -----
registerTextAt: aRegisterSelector

	| raw current last text |
	current := processor perform: aRegisterSelector.
	last := self registerCache at: aRegisterSelector ifAbsent: [].
	self registerCache at: aRegisterSelector put: current.	

	raw := String streamContents:
				[:s |
				current
					printOn: s
					base: (2 raisedTo: self bitsPerDigit)
					length: processor class wordSize * 8 / self bitsPerDigit
					padded: true].
		
	text := (String streamContents:
				[:s |
				raw groupsOf: self digitsPerGroup atATimeCollect:
					[:group |
					s nextPutAll: group; space]])
						asText.

	last ~= current ifTrue:
		[text addAllAttributes: {TextEmphasis bold. TextColor color: Color salmon}].
	^text!

----- Method: CogProcessorAlienInspector>>stepIn: (in category 'stepping') -----
stepIn: window
	self changed: #text.!

----- Method: CogProcessorAlienInspector>>stepTimeIn: (in category 'stepping') -----
stepTimeIn: window
	"The minimum update time in milliseconds."
	^500!

----- Method: CogProcessorAlienInspector>>text (in category 'accessing - ui') -----
text

	^Text streamContents:
		[:s | | max exclude fpstate |
		max := (self registerSelectors ifEmpty: [1] ifNotEmpty: [:selector | (selector collect: #size) max]).
		s
			nextPutAll: ('PC' padded: #right to: max with: Character space);
			nextPutAll: ' = ';
			nextPutAll: self pcText;
			cr.
		exclude := Set new.
		1 to: (fpstate := processor floatingPointRegisterStateGetters) size by: 4 do:
			[:index|
			((index to: index + 3) allSatisfy: [:fpri| (processor perform: (fpstate at: fpri)) isZero]) ifTrue:
				[exclude addAll: (fpstate copyFrom: index to: index + 3)]].
		self registerSelectors do: [:selector |
			(exclude includes: selector) ifFalse:
				[s
					nextPutAll: ((selector asUppercase padded: #right to: max with: Character space)
						asText addAttribute: (PluggableTextAttribute evalBlock: [self interpret: selector]));
					nextPutAll: ' = ';
					nextPutAll: (self registerTextAt: selector);
					cr]]]!

----- Method: CogProcessorAlienInspector>>wantsStepsIn: (in category 'stepping') -----
wantsStepsIn: window
	^ true!

----- Method: CogProcessorAlienInspector>>windowTitle (in category 'accessing - ui') -----
windowTitle

	^windowTitle ifNil: ['Register State of ', (String streamContents: [:s| processor printNameOn: s])]!

----- Method: CogProcessorAlienInspector>>windowTitle: (in category 'accessing - ui') -----
windowTitle: newTitle

	windowTitle = newTitle ifTrue: [^ self].
	windowTitle := newTitle.
	self changed: #windowTitle.!

Model subclass: #SimulatorMorphicModel
	instanceVariableNames: 'vm title stepping morph'
	classVariableNames: ''
	poolDictionaries: 'EventSensorConstants'
	category: 'VMMakerUI-InterpreterSimulation-Morphic'!

!SimulatorMorphicModel commentStamp: 'eem 7/14/2015 17:07' prior: 0!
A SimulatorMorphicModel handles Morphic callbacks and UI  for (some parts of ) the simulator.

I   handle event forwarding management..

Currently, I am a listener to HandMorphs>>addPrimitiveEventListener. 
I am added as a listener by SimulatorMorph>>displayView (which probably  needs to change. tty)!

----- Method: SimulatorMorphicModel class>>initialize (in category 'class initialization') -----
initialize
	"I want to keep it launchable by script only for now.
	Eliot has a bunch of options that aren't really feasible for a Morphic first approach.
	"
	"self
		registerWindowColor;
		registerInOpenMenu;
		registerInFlaps"!

----- Method: SimulatorMorphicModel class>>on:title:transcript: (in category 'instance creation') -----
on: aStackInterpreterSimulator title: aString transcript: aTranscriptStream
	| simmodel |
	simmodel := self new.
	simmodel 
		vm: aStackInterpreterSimulator;
		title: aString;
		transcript: aTranscriptStream.
	^simmodel.	!

----- Method: SimulatorMorphicModel class>>registerInFlaps (in category 'class initialization') -----
registerInFlaps
"	Flaps 
		registerQuad: 
			{ #StackInterpreterSimulator. 
			#prototypicalToolWindow.
			'StackInterpreter Simulator' translated.
			'A Morphic Wrapper for VM Simulations' translated }
	 	forFlapNamed: 'Tools' translated.
	Flaps replaceToolsFlap"!

----- Method: SimulatorMorphicModel class>>registerInOpenMenu (in category 'class initialization') -----
registerInOpenMenu
	(TheWorldMenu respondsTo: #registerOpenCommand:) ifTrue: [
		TheWorldMenu unregisterOpenCommand: 'StackInterpreter Simulator'.
		TheWorldMenu registerOpenCommand: {'StackInterpreter Simulator'. {self. #open}}].
		!

----- Method: SimulatorMorphicModel class>>unload (in category 'class initialization') -----
unload
	self 
		unregisterFromOpenMenu;
		unregisterFromFlaps.!

----- Method: SimulatorMorphicModel class>>unregisterFromFlaps (in category 'class initialization') -----
unregisterFromFlaps
	"Flaps 
		unregisterQuadsWithReceiver: self;
		replaceToolsFlap"!

----- Method: SimulatorMorphicModel class>>unregisterFromOpenMenu (in category 'class initialization') -----
unregisterFromOpenMenu
	 (TheWorldMenu respondsTo: #registerOpenCommand:)
		ifTrue: [TheWorldMenu unregisterOpenCommand: 'StackInterpreter Simulator'].
!

----- Method: SimulatorMorphicModel>>bounds (in category 'accessing') -----
bounds
	^morph bounds.!

----- Method: SimulatorMorphicModel>>byteCountText (in category 'user interface') -----
byteCountText
	^vm byteCountText!

----- Method: SimulatorMorphicModel>>currentContextStack (in category 'user interface - squeakJS') -----
currentContextStack
	self flag: 'tty'.
	^ 'Current Context Stack' printString asText!

----- Method: SimulatorMorphicModel>>defaultWindowColor (in category 'user interface') -----
defaultWindowColor
	^ (Color r: 0.645 g: 1.0 b: 1.0)!

----- Method: SimulatorMorphicModel>>displayForm (in category 'accessing') -----
displayForm
	^ vm displayForm!

----- Method: SimulatorMorphicModel>>displayView (in category 'accessing') -----
displayView
	^ vm displayView!

----- Method: SimulatorMorphicModel>>displayView: (in category 'accessing') -----
displayView: anImageMorph
	vm displayView: anImageMorph!

----- Method: SimulatorMorphicModel>>forceInterruptCheck (in category 'buttons callbacks') -----
forceInterruptCheck
	vm forceInterruptCheck
"^UserDialogBoxMorph inform: 'Toggle Transcript' title: 'TODO:'"!

----- Method: SimulatorMorphicModel>>fullDisplayUpdate (in category 'buttons callbacks') -----
fullDisplayUpdate
	vm fullDisplayUpdate
"^UserDialogBoxMorph inform: 'Toggle Transcript' title: 'TODO:'"!

----- Method: SimulatorMorphicModel>>hack (in category 'buttons callbacks') -----
hack
	UserDialogBoxMorph inform: (morph bounds printString) title: 'Hack:'!

----- Method: SimulatorMorphicModel>>handleListenEvent: (in category 'event-forwarding') -----
handleListenEvent: aMorphicEvent
"The SimulatorImageMorph  regsitered me (a SimulatorMorphicModel ) with HandMorph>>addEventListener
HandMorph then broadcasts events to all registered listeners at this method. See HandMorph>>sendListenPrimitiveEvent
"
	morph ifNotNil:
		[(SimulatorEventTransformer default degenerateEvent: aMorphicEvent) ifNotNil:
			[:evtBuf|
			 ((evtBuf at: 1) = EventTypeMouse and: [morph bounds containsPoint: aMorphicEvent position]) ifTrue:
				[| xtranslated ytranslated |
				xtranslated :=  (evtBuf at:3) - (morph bounds left) - 2 .  "<--heh"  
				ytranslated :=  (evtBuf at:4) - (morph bounds top). 
				evtBuf at: 3 put: xtranslated.
				evtBuf at: 4 put: ytranslated].
			vm queueForwardedEvent: evtBuf]]!

----- Method: SimulatorMorphicModel>>help (in category 'buttons callbacks') -----
help
	"Open up a workspace with explanatory info in it about the StackInterpreterSimulator"
	Workspace new
		contents: self helpText;
		openLabel: self windowTitle, ' Help'.!

----- Method: SimulatorMorphicModel>>helpText (in category 'buttons callbacks') -----
helpText
	^(String streamContents: [:str |
		str nextPutAll:
'Stack Intepreter Simulator Help Contents Go Here.']) translated!

----- Method: SimulatorMorphicModel>>initialExtent (in category 'user interface') -----
initialExtent
	^ 1286 at 938!

----- Method: SimulatorMorphicModel>>initialize (in category 'initialize-release') -----
initialize
	
	title := 'StackInterpreter Simulator (Beta))'.!

----- Method: SimulatorMorphicModel>>ioExit (in category 'buttons callbacks') -----
ioExit
	vm ioExit
	displayView activeHand removeEventListener: self model.	"This is a bug as the user in vm ioExit may have cancelled the confirm t.m."
"^UserDialogBoxMorph inform: 'Toggle Transcript' title: 'TODO:'"!

----- Method: SimulatorMorphicModel>>loadImage (in category 'buttons callbacks') -----
loadImage
	^UserDialogBoxMorph inform: 'load image' title: 'TODO:'!

----- Method: SimulatorMorphicModel>>morph (in category 'accessing') -----
morph
	"I need the bounds of my morph for filtering mouse events.
       If there is a canned way of doing this besides this tight binding to my SimulatorMorph,
	then please refactor me.

      see my protocol event-forwarding for the gory details"
	self flag:'tty'.
	^morph.!

----- Method: SimulatorMorphicModel>>morph: (in category 'accessing') -----
morph: aMorph
	"I need the bounds of my morph for filtering mouse events.
       If there is a canned way of doing this besides this tight binding to my SimulatorMorph,
	then please refactor me.

      see my protocol event-forwarding for the gory details"
	self flag:'tty'.
	morph := aMorph.!

----- Method: SimulatorMorphicModel>>onItemClicked: (in category 'user interface - squeakJS') -----
onItemClicked: anItem
	"I am an item in the current context display on the SqueakJS tree view".!

----- Method: SimulatorMorphicModel>>options (in category 'buttons callbacks') -----
options
^UserDialogBoxMorph inform: 'Options Popup--need checkboxes?' title: 'TODO:'!

----- Method: SimulatorMorphicModel>>over (in category 'buttons callbacks') -----
over
	stepping:=true.
^UserDialogBoxMorph inform: 'Step Over' title: 'TODO:'!

----- Method: SimulatorMorphicModel>>processesAndContextStack (in category 'user interface - squeakJS') -----
processesAndContextStack
	"just a stub. see top right panel at http://lively-web.org/users/bert/squeak.html  for what I intend to present"
	self flag: 'tty'.
	^ 'Processes and ContextStack' printString asText
!

----- Method: SimulatorMorphicModel>>reset (in category 'buttons callbacks') -----
reset
	^UserDialogBoxMorph inform: 'Reset' title: 'TODO:'!

----- Method: SimulatorMorphicModel>>return (in category 'buttons callbacks') -----
return
^UserDialogBoxMorph inform: 'Return' title: 'TODO:'!

----- Method: SimulatorMorphicModel>>run (in category 'buttons callbacks') -----
run
	stepping:=false.
	vm run
"^UserDialogBoxMorph inform: 'Run' title: 'TODO:'"!

----- Method: SimulatorMorphicModel>>send (in category 'buttons callbacks') -----
send
^UserDialogBoxMorph inform: 'Send' title: 'TODO:'!

----- Method: SimulatorMorphicModel>>specialObjectsAndActiveContext (in category 'user interface - squeakJS') -----
specialObjectsAndActiveContext
	"just a stub. see top left panel at http://lively-web.org/users/bert/squeak.html  for what I intend to present"
	self flag: 'tty'.
	^ 'Special Objects and Active Context' printString asText
!

----- Method: SimulatorMorphicModel>>step (in category 'buttons callbacks') -----
step
	stepping:=true.
^UserDialogBoxMorph inform: 'Step' title: 'TODO:'!

----- Method: SimulatorMorphicModel>>stepping (in category 'accessing') -----
stepping
	^stepping!

----- Method: SimulatorMorphicModel>>stepping: (in category 'accessing') -----
stepping: aBoolean
	stepping := aBoolean!

----- Method: SimulatorMorphicModel>>title: (in category 'accessing') -----
title: aString
	title := aString!

----- Method: SimulatorMorphicModel>>toggleTranscript (in category 'buttons callbacks') -----
toggleTranscript
	vm toggleTranscriptForSimulatorMorph: self transcript.
"^UserDialogBoxMorph inform: 'Toggle Transcript' title: 'TODO:'"!

----- Method: SimulatorMorphicModel>>transcript (in category 'accessing') -----
transcript
	^vm transcript!

----- Method: SimulatorMorphicModel>>transcript: (in category 'accessing') -----
transcript: aTranscriptStream
	vm transcript: aTranscriptStream.!

----- Method: SimulatorMorphicModel>>utilitiesMenu: (in category 'user interface') -----
utilitiesMenu: aMenuMorph 
	^vm utilitiesMenu: aMenuMorph!

----- Method: SimulatorMorphicModel>>vm (in category 'accessing') -----
vm
	^vm!

----- Method: SimulatorMorphicModel>>vm: (in category 'accessing') -----
vm: aVMSimulator
	vm := aVMSimulator!

----- Method: SimulatorMorphicModel>>windowTitle (in category 'user interface') -----
windowTitle
	^ title translated!

ImageMorph subclass: #SimulatorImageMorph
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'VMMakerUI-InterpreterSimulation-Morphic'!

!SimulatorImageMorph commentStamp: 'eem 7/15/2015 09:48' prior: 0!
A SimulatorImageMorph is an ImageMorph that suppresses halos.!

----- Method: SimulatorImageMorph>>extent: (in category 'geometry') -----
extent: aPoint
	"Override to restore the default resizing behaviour."
	^self perform: #extent: withArguments: {aPoint} inSuperclass: ImageMorph superclass!

----- Method: SimulatorImageMorph>>handleMouseDown: (in category 'event handling') -----
handleMouseDown: anEvent
	anEvent wasHandled: true!

----- Method: SimulatorImageMorph>>handleMouseEnter: (in category 'event handling') -----
handleMouseEnter: anEvent
	anEvent wasHandled: true!

----- Method: SimulatorImageMorph>>handleMouseLeave: (in category 'event handling') -----
handleMouseLeave: anEvent
	^super handleMouseLeave: anEvent!

----- Method: SimulatorImageMorph>>handleMouseOver: (in category 'event handling') -----
handleMouseOver: anEvent
	anEvent wasHandled: true!

----- Method: SimulatorImageMorph>>handleMouseUp: (in category 'event handling') -----
handleMouseUp: anEvent
	anEvent wasHandled: true!

----- Method: SimulatorImageMorph>>handlerForMouseDown: (in category 'event handling') -----
handlerForMouseDown: anEvent
	"Override all mouse button shenanigans like halos by handling any and all mouse down events."
	^self!

SystemWindow subclass: #SimulatorMorph
	instanceVariableNames: 'loadButton helpButton resetButton stepButton overButton sendButton returnButton runButton toggleTranscriptButton optionsButton transcriptPanel commandPanel contextPanel stackPanel callStackPanel displayForm displayView eventEncoder ioExitButton fullDisplayUpdateButton forceInterruptCheckButton hackButton'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'VMMakerUI-InterpreterSimulation-Morphic'!

!SimulatorMorph commentStamp: 'eem 7/14/2015 17:06' prior: 0!
A SimulatorMorph is a copy of PreferenceBrowserMorph that has been mangled into something that will support the simulator.  I provide some UI features inspired by Bert Freudenberg's Lively Squeak VM at http://lively-web.org/users/bert/squeak.html.

See class protocol 'documentation' for examples of invoking me.

My model is SimulatorMorphicModel. 
My model has a reference to the Simulator and itermediates all (?) interaction with it.

The simulator renders the simulated World on a SimulatorImageMorph that I contain. 

There is some cruft (tight coupling via direct references along all three layers UI-Model-VM) in me that exists to support Eliot's original Simulator>>openAsMorph functionality and use-case.
Rumors that said cruft is an artifact of tty's rudimentary Morphic skills are entirely credible.

I hold out the barest glimmer of hope that Bert Freudenberg's SqueakJS functionality can be integrated into my functionality as well. 
see http://lively-web.org/users/bert/squeak.html for the inspiration.

I am not amenable to Flaps or the WorldMenu as there is a lot of pre-run configuration that is done to the Simulator prior to its being run.
Managing that ability with a GUI is counter-productive. If said functionality is desired in the future, then inspiration can be gleaned by cut-n-paste from PreferenceBrowser and PreferenceBrowserModel.!

----- Method: SimulatorMorph class>>ttyOne (in category 'documentation') -----
ttyOne
"Script tty uses to run the stackIntepreter using this class"
| vm |
Transcript clear.
vm := StackInterpreterSimulator newWithOptions: #(#STACKVM).
vm openOn: '/home/tty/usr/src/smalltalk/buildCogDevelopmentImageCog.app/Contents/Resources/targets/Squeak4.5.image'.
"vm setBreakSelector: #&."
vm 
	openAsSimulatorMorph "; 
	toggleTranscript;
	halt;
	run"
!

----- Method: SimulatorMorph class>>withVMSimulator:title:transcript: (in category 'instance creation') -----
withVMSimulator: aSimulatorMorphicModel title: aString transcript: aTranscript
	^self new initializeWithVMSimulator: aSimulatorMorphicModel title: aString aTranscript: aTranscript;
		yourself.
		
!

----- Method: SimulatorMorph>>basicButton (in category 'submorphs - buttons') -----
basicButton
	| button |
	button := SimpleButtonMorph new.
	button
		borderWidth: 2;
		borderColor: #raised;
		on: #mouseEnter send: #value to: [button borderColor: self paneColor];
		on: #mouseLeave send: #value to: [button borderColor: #raised];
		vResizing: #spaceFill;
		useRoundedCorners;
		clipSubmorphs: true;
		color: self paneColor muchLighter;
		target: self model.
	^button!

----- Method: SimulatorMorph>>buttonRowLayoutFrame (in category 'submorphs - buttons') -----
buttonRowLayoutFrame 
	^LayoutFrame fractions: (0 at 0 corner: 1 at 0) offsets: (0 at 0 corner: 0@ (TextStyle defaultFont height * 2.5))
!

----- Method: SimulatorMorph>>callStackPanel (in category 'submorphs - squeakJS') -----
callStackPanel
	"If any Morphic gurus exist, please have at it."
	^callStackPanel ifNil: 
		[callStackPanel :=  (PluggableTextMorph
				on: self model
				text: #processesAndContextStack
				accept: nil
				readSelection: nil
				menu: nil) hideScrollBarsIndefinitely.
		callStackPanel		
			color: Color transparent;
			hResizing: #spaceFill;
			vResizing: #spaceFill;
			cellInset: 5;
			yourself].

!

----- Method: SimulatorMorph>>commandPanel (in category 'submorphs - simulator panel') -----
commandPanel
	self flag: 'tty'. "does this hybrid of PreferenceBrowser layout and Simulato openAsMorph stuff make sense?"
	^commandPanel ifNil: 
		[commandPanel :=  (PluggableTextMorph
				on: self model vm
				text: #byteCountText
				accept: nil
				readSelection: nil
				menu: #utilitiesMenu:) hideScrollBarsIndefinitely.
		commandPanel		
			color: Color transparent;
			hResizing: #spaceFill;
			vResizing: #spaceFill;
			cellInset: 5;
			yourself].
!

----- Method: SimulatorMorph>>contextPanel (in category 'submorphs - squeakJS') -----
contextPanel
	"This should show the currentContext and Special Objects array. as seen at SqueakJS
	  Doing that requires real talent. talent tty is lacking at the moment
							on: [ Array with:  (MorphWithSubmorphsWrapper with: self)  ]	
	Array with: (ObjectExplorerWrapper with: rootObject name: 'root' model: self parent: nil)
	"
	^contextPanel ifNil: 
		[contextPanel := (SimpleHierarchicalListMorph
							on: [ Array with: (ObjectExplorerWrapper with: (self model vm) name: 'root' model: (self model vm) parent: nil) ]
							list: #value
							selected: nil
							changeSelected: nil
							menu: nil
							keystroke: nil) showScrollBarsOnlyWhenNeeded: true.
		contextPanel		
			color: Color transparent;
			hResizing: #spaceFill;
			vResizing: #spaceFill;
			cellInset: 5;
			yourself]


!

----- Method: SimulatorMorph>>displayView (in category 'submorphs - simulator display view') -----
displayView
	"The VM SImulator draws directly on an imageMorph named displayView
	  displayView is housed on a Form named displayForm
	   displayForm is initialized in StackInterpreterSimulator >> initialize.
	  see StackInterpreterSimulator >>openAsMorph for original constructs."
	^displayView ifNil: 
		[displayView :=  SimulatorImageMorph new image: model vm displayForm. 
		self model displayView: displayView.					
		self model morph: displayView. "<-- N.B.. morph bounds are used to filter events in the model. tty"
	      displayView activeHand addEventListener: self model.		

 		displayView		
			color: Color transparent;
			hResizing: #spaceFill;
			vResizing: #spaceFill;
			cellInset: 5;
			yourself]!

----- Method: SimulatorMorph>>displayViewLayoutFrame (in category 'submorphs - simulator display view') -----
displayViewLayoutFrame 
	| squeakJSFrame buttonFrame simulatorFrame|
	"if any Morphic guru's understand layouts and offsets, please fix this. tty"
	buttonFrame := self buttonRowLayoutFrame.
	squeakJSFrame := self squeakJSRowLayoutFrame.
	simulatorFrame := self simulatorLayoutFrame.
	^LayoutFrame fractions: (0 at 0 corner: 1 at 1) 
				    offsets: (0@(buttonFrame bottomOffset) corner: simulatorFrame leftOffset at squeakJSFrame topOffset)!

----- Method: SimulatorMorph>>extent: (in category 'geometry') -----
extent: aPoint
	super extent: aPoint.
	self fullBounds.
!

----- Method: SimulatorMorph>>forceInterruptCheckButton (in category 'submorphs - buttons') -----
forceInterruptCheckButton
	self flag: 'tty'.
	^forceInterruptCheckButton ifNil: 
		[forceInterruptCheckButton := self basicButton 
						label: 'vm forceInterruptCheck' translated; 
						actionSelector: #forceInterruptCheck;						
						setBalloonText: 
							'Invoke forceInterruptCheck on Simulator.' translated]!

----- Method: SimulatorMorph>>fullDisplayUpdateButton (in category 'submorphs - buttons') -----
fullDisplayUpdateButton
	self flag: 'tty'.
	^fullDisplayUpdateButton ifNil: 
		[fullDisplayUpdateButton := self basicButton 
						label: 'vm fullDisplayUpdate' translated; 
						actionSelector: #fullDisplayUpdate;						
						setBalloonText: 
							'Invoke fullDisplayUpdate on Simulator.' translated]!

----- Method: SimulatorMorph>>hackButton (in category 'submorphs - buttons') -----
hackButton
	self flag: 'tty'.
	^hackButton ifNil: 
		[hackButton := self basicButton 
						label: 'Display ImageMorph Bounds' translated; 
						actionSelector: #hack;						
						setBalloonText: 
							'tty needs a hack button.' translated]!

----- Method: SimulatorMorph>>helpButton (in category 'submorphs - buttons') -----
helpButton
	^helpButton ifNil: 
		[helpButton := self basicButton 
						label: 'help' translated; 
						setBalloonText: 
							'Click here to get some hints on use of me ',
							'Panel' translated;
						actionSelector: #help]!

----- Method: SimulatorMorph>>initializeWithVMSimulator:title:aTranscript: (in category 'initialization') -----
initializeWithVMSimulator: aStackInterpreterSimulator title: aString aTranscript: aTranscript
	self flag: 'tty'. "need to get the layout right at this point. resizers and scroll bars would be nice. Layout offsets need a gimlet eye as well"
	self 
		model: (SimulatorMorphicModel on: aStackInterpreterSimulator title: aString transcript: aTranscript);
		clipSubmorphs: true;
		setLabel: self model windowTitle;
		name: aString;
		addMorph: self newButtonRow fullFrame: self buttonRowLayoutFrame;
		addMorph: self squeakJSRow fullFrame: self squeakJSRowLayoutFrame;
		addMorph: self simulatorPanel fullFrame: self simulatorLayoutFrame;
		addMorph: self displayView fullFrame: self displayViewLayoutFrame.	
	^self!

----- Method: SimulatorMorph>>ioExitButton (in category 'submorphs - buttons') -----
ioExitButton
	self flag: 'tty'.
	^ioExitButton ifNil: 
		[ioExitButton := self basicButton 
						label: 'vm ioExit' translated; 
						actionSelector: #ioExit;						
						setBalloonText: 
							'Invoke ioExit on Simulator.' translated]!

----- Method: SimulatorMorph>>loadButton (in category 'submorphs - buttons') -----
loadButton
	^loadButton ifNil: 
		[loadButton := self basicButton 
						label: 'Load Image' translated; 
						actionSelector: #loadImage;						
						setBalloonText: 
							'Select an image to load.' translated]!

----- Method: SimulatorMorph>>newButtonRow (in category 'submorphs - buttons') -----
newButtonRow
	^BorderedMorph new
		color: Color transparent;
		cellInset: 2;
		layoutInset: 2;
		layoutPolicy: TableLayout new;
		listDirection: #leftToRight;
		listCentering: #topLeft;
		cellPositioning: #topLeft;
		on: #mouseEnter send: #paneTransition: to: self;
		on: #mouseLeave send: #paneTransition: to: self;
		addMorphBack: self hackButton;
		addMorphBack: self newSeparator;

"		addMorphBack: self resetButton;
		addMorphBack: self newSeparator;
		addMorphBack: self forceInterruptCheckButton;
		addMorphBack: self newSeparator;
		addMorphBack: self fullDisplayUpdateButton;
		addMorphBack: self newSeparator;
		addMorphBack: self toggleTranscriptButton;"  
		addMorphBack: self runButton;				
		addMorphBack: self newSeparator; 
		addMorphBack: self ioExitButton;
		addMorphBack: self newTransparentFiller;		
		addMorphBack: self stepButton;
		addMorphBack: self newSeparator;		
		addMorphBack: self overButton;
		addMorphBack: self newSeparator;
		addMorphBack: self newSeparator;		
		addMorphBack: self sendButton;
		addMorphBack: self newSeparator;		
		addMorphBack: self returnButton;		
		addMorphBack: self newTransparentFiller;
"		addMorphBack: self loadButton;
		addMorphBack: self newSeparator;				
		addMorphBack: self optionsButton;     too complex to implement now. See StackInterpreterSimulator class comment for examples"										
		addMorphBack: self newTransparentFiller;
		addMorphBack: self helpButton;
		yourself.!

----- Method: SimulatorMorph>>newSeparator (in category 'submorphs - buttons') -----
newSeparator
	^BorderedMorph new
		borderWidth: 2;
		borderColor: Color transparent;
		color: self paneColor;
		hResizing: #rigid;
		width: 5;
		vResizing: #spaceFill;
		yourself!

----- Method: SimulatorMorph>>newTransparentFiller (in category 'submorphs - buttons') -----
newTransparentFiller
	^Morph new
		color: Color transparent;
		vResizing: #spaceFill;
		hResizing: #spaceFill;
		yourself.!

----- Method: SimulatorMorph>>optionsButton (in category 'submorphs - buttons') -----
optionsButton
	^optionsButton ifNil: 
		[optionsButton := self basicButton 
						label: 'VM Options' translated; 
						actionSelector: #options;						
						setBalloonText: 
							'VM Options.' translated]!

----- Method: SimulatorMorph>>overButton (in category 'submorphs - buttons') -----
overButton
	^overButton ifNil: 
		[overButton := self basicButton 
						label: 'Over' translated; 
						actionSelector: #over;						
						setBalloonText: 
							'Step Over.' translated]!

----- Method: SimulatorMorph>>resetButton (in category 'submorphs - buttons') -----
resetButton
	^resetButton ifNil: 
		[resetButton := self basicButton 
						label: 'Reset' translated; 
						actionSelector: #reset;						
						setBalloonText: 
							'Reset running simulation.' translated]!

----- Method: SimulatorMorph>>returnButton (in category 'submorphs - buttons') -----
returnButton
	self flag: 'tty'.
	^returnButton ifNil: 
		[returnButton := self basicButton 
						label: 'Return' translated; 
						actionSelector: #return;						
						setBalloonText: 
							'Return from what?.' translated]!

----- Method: SimulatorMorph>>runButton (in category 'submorphs - buttons') -----
runButton
	self flag: 'tty'.
	^runButton ifNil: 
		[runButton := self basicButton 
						label: 'vm run' translated; 
						actionSelector: #run;						
						setBalloonText: 
							'Run Simulation.' translated]!

----- Method: SimulatorMorph>>sendButton (in category 'submorphs - buttons') -----
sendButton
	self flag: 'tty'.
	^sendButton ifNil: 
		[sendButton := self basicButton 
						label: 'Send' translated; 
						actionSelector: #send;						
						setBalloonText: 
							'Send what exactly?.' translated]!

----- Method: SimulatorMorph>>simulatorLayoutFrame (in category 'submorphs - simulator panel') -----
simulatorLayoutFrame 
	| squeakJSFrame buttonFrame |
	"I don't understand offsets in the LayoutFrame. I just fiddled until it looked ok. If anybody knows what they are doing, please refactor."
	self flag: 'tty'.
	buttonFrame := self buttonRowLayoutFrame.
	squeakJSFrame := self squeakJSRowLayoutFrame.
	^LayoutFrame fractions: (0.7 at 0 corner: 1 at squeakJSFrame topOffset) 
				    offsets: (0@(buttonFrame bottomOffset) corner: 0.70 at squeakJSFrame topOffset)
!

----- Method: SimulatorMorph>>simulatorPanel (in category 'submorphs - simulator panel') -----
simulatorPanel
	"standard controls from StackInterpreterSimulator >> openAsMorph"
	^BorderedMorph new
		color: Color transparent;
		layoutInset: 10;
		cellInset: 10;
		layoutPolicy: TableLayout new;
		listDirection: #topToBottom;
		listCentering: #topLeft;
		cellPositioning: #topLeft;
		on: #mouseEnter send: #paneTransition: to: self;
		on: #mouseLeave send: #paneTransition: to: self;		
		addMorphBack: self transcriptPanel;
		addMorphBack: self commandPanel;
		yourself.!

----- Method: SimulatorMorph>>squeakJSRow (in category 'submorphs - squeakJS') -----
squeakJSRow
	"row fo SqueakJS context, stack and call-stack panels"
	^BorderedMorph new
		color: Color blue;
		cellInset: 2;
		layoutInset: 2;
		layoutPolicy: TableLayout new;
		listDirection: #leftToRight;
		listCentering: #topLeft;
		cellPositioning: #topLeft;
		on: #mouseEnter send: #paneTransition: to: self;
		on: #mouseLeave send: #paneTransition: to: self;
		addMorphBack: self callStackPanel;
		addMorphBack: self contextPanel;
		addMorphBack: self stackPanel;		
		yourself.!

----- Method: SimulatorMorph>>squeakJSRowLayoutFrame (in category 'submorphs - squeakJS') -----
squeakJSRowLayoutFrame 
	^LayoutFrame fractions: (0 at 0.8 corner: 1 at 1) offsets: (0 at 0.8 corner: 1@ (TextStyle defaultFont height * 2.5))
!

----- Method: SimulatorMorph>>stackPanel (in category 'submorphs - squeakJS') -----
stackPanel
	"If any Morphic gurus exist, please have at it."
	^stackPanel ifNil: 
		[stackPanel :=  (PluggableTextMorph
				on: self model
				text: #currentContextStack
				accept: nil
				readSelection: nil
				menu: nil) hideScrollBarsIndefinitely.
		stackPanel		
			color: Color transparent;
			hResizing: #spaceFill;
			vResizing: #spaceFill;
			cellInset: 5;
			yourself].

!

----- Method: SimulatorMorph>>stepButton (in category 'submorphs - buttons') -----
stepButton
	self flag: 'tty'.
	^stepButton ifNil: 
		[stepButton := self basicButton 
						label: 'Step' translated; 
						actionSelector: #step;						
						setBalloonText: 
							'Step Into.' translated]!

----- Method: SimulatorMorph>>toggleTranscriptButton (in category 'submorphs - buttons') -----
toggleTranscriptButton
	"tty I dont like this. I have diabled the button"
	self flag: 'tty'.
	^toggleTranscriptButton ifNil: 
		[toggleTranscriptButton := self basicButton 
						label: 'Toggle Transcript' translated; 
						actionSelector: #toggleTranscript;						
						setBalloonText: 
							'Use External Transcript Instead of Internal.' translated]!

----- Method: SimulatorMorph>>transcriptPanel (in category 'submorphs - simulator panel') -----
transcriptPanel
	self flag: 'tty'. "does this hybrid of PreferenceBrowser layout and Simulato openAsMorph stuff make sense?"
	^transcriptPanel ifNil: 
		[transcriptPanel := (PluggableTextMorph
				on:  self model vm transcript
				text: nil
				accept: nil
				readSelection: nil
				menu: #codePaneMenu:shifted:).
		transcriptPanel	
			name: 'transcriptPanel';	
			color: Color transparent;
			hResizing: #spaceFill;
			vResizing: #spaceFill;
			cellInset: 5;
			yourself].
!

TestCase subclass: #SimulatorMorphicEventTests
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: 'EventSensorConstants'
	category: 'VMMakerUI-InterpreterSimulation-Morphic'!

----- Method: SimulatorMorphicEventTests>>testKeyEventDegeneration (in category 'test event') -----
testKeyEventDegeneration
	|aMorphicEvent evtBuf type|
	aMorphicEvent := HandMorph new generateKeyboardEvent: {2 . 0. 0. 0. 0. 0. 0. 0}.
	evtBuf := SimulatorEventTransformer default degenerateEvent: aMorphicEvent. 
	type := evtBuf at:1.
	self assert:(type = EventTypeKeyboard).
!

----- Method: SimulatorMorphicEventTests>>testMouseEventDegeneration (in category 'test event') -----
testMouseEventDegeneration
	|aMorphicEvent evtBuf type|
	"see class comment in EventSensor browse"
	aMorphicEvent := HandMorph new generateMouseEvent: {1 . 0. 0. 0. 0. 0. 0. 0}.
	evtBuf := SimulatorEventTransformer default degenerateEvent: aMorphicEvent. 
	type := evtBuf at:1.
	self assert:(type = EventTypeMouse).
!

----- Method: SimulatorMorphicEventTests>>testNullEventDegeneration (in category 'test event') -----
testNullEventDegeneration
	|aMorphicEvent evtBuf type|
	"Test a bad morphic event returns a null event"	"see class comment in EventSensor browse"
	aMorphicEvent := UserInputEvent new.
	evtBuf := SimulatorEventTransformer default degenerateEvent: aMorphicEvent. 
	type := evtBuf at:1.
	self assert:(type = EventTypeNone).

!

----- Method: SimulatorMorphicEventTests>>testSimulatorDisplayViewAccess (in category 'test tight coupling') -----
testSimulatorDisplayViewAccess
	"There is tight coupling between the morph,model and vm simulator on the simulators displayView variable
	 this test makes sure it is accesible and is an ImageMorph."
	
self assert: ((SystemNavigation allImplementorsOf: #displayView localTo: StackInterpreterSimulator) size = 1).
self assert: ((SystemNavigation allImplementorsOf: #displayView: localTo: StackInterpreterSimulator)size = 1).

!

----- Method: SimulatorMorphicEventTests>>testStackInterpreterSimulatorDisplayViewAccess (in category 'test tight coupling') -----
testStackInterpreterSimulatorDisplayViewAccess
	"There is tight coupling between the morph,model and vm simulator on the simulators displayView variable
	 this test makes sure it is accesible and is an ImageMorph."
	
self assert: ((SystemNavigation allImplementorsOf: #displayView localTo: StackInterpreterSimulator) size = 1).
self assert: ((SystemNavigation allImplementorsOf: #displayView: localTo: StackInterpreterSimulator)size = 1).

!

----- Method: CogVMSimulator>>openAsMorph (in category '*VMMakerUI-InterpreterSimulation-Morphic') -----
openAsMorph
	"Open a morphic view on this simulation."
	| localImageName borderWidth window |
	localImageName := imageName
							ifNotNil: [self localNameFor: imageName]
							ifNil: [' synthetic image'].
	window := (SystemWindow labelled: 'Simulation of ', localImageName) model: self.
	window paneColor: self windowColorToUse.

	window addMorph: (displayView := SimulatorImageMorph new image: displayForm)
			frame: (0 at 0 corner: 1 at 0.8).
	displayView activeHand addEventListener: self.
	eventTransformer := SimulatorEventTransformer new.

	transcript := TranscriptStream on: (String new: 10000).
	window addMorph: (PluggableTextMorph
							on: transcript text: nil accept: nil
							readSelection: nil menu: #codePaneMenu:shifted:)
			frame: (0 at 0.8 corner: 0.7 at 1).
	window addMorph: (PluggableTextMorph on: self
						text: #byteCountText accept: nil
						readSelection: nil menu: #utilitiesMenu:) hideScrollBarsIndefinitely
			frame: (0.7 at 0.8 corner: 1 at 1).

	borderWidth := [SystemWindow borderWidth] "Squeak 4.1"
						on: MessageNotUnderstood
						do: [:ex| 0]. "3.8"
	borderWidth := borderWidth + window borderWidth.
	window openInWorldExtent: (self desiredDisplayExtent
								+ (2 * borderWidth @ borderWidth)
								+ (0 at window labelHeight)
								* (1@(1/0.8))) rounded.
	^window!

----- Method: CogVMSimulator>>openAsMorphNoTranscript (in category '*VMMakerUI-InterpreterSimulation-Morphic') -----
openAsMorphNoTranscript
	"Open a morphic view on this simulation."
	| localImageName borderWidth window |
	localImageName := imageName
							ifNotNil: [self localNameFor: imageName]
							ifNil: [' synthetic image'].
	window := (SystemWindow labelled: 'Simulation of ', localImageName) model: self.
	window paneColor: self windowColorToUse.

	window addMorph: (displayView := SimulatorImageMorph new image: displayForm)
			frame: (0 at 0 corner: 1 at 0.95).
	displayView activeHand addEventListener: self.
	eventTransformer := SimulatorEventTransformer new.

	window addMorph: (PluggableTextMorph on: self
						text: #byteCountText accept: nil
						readSelection: nil menu: #utilitiesMenu:) hideScrollBarsIndefinitely
		frame: (0 at 0.95 corner: 1 at 1).

	borderWidth := [SystemWindow borderWidth] "Squeak 4.1"
						on: MessageNotUnderstood
						do: [:ex| 0]. "3.8"
	borderWidth := borderWidth + window borderWidth.
	window openInWorldExtent: (self desiredDisplayExtent
								+ (2 * borderWidth at borderWidth)
								+ (0 at window labelHeight)
								* (1@(1/0.95))) rounded!

Object subclass: #SimulatorEventTransformer
	instanceVariableNames: 'buttons modifiers'
	classVariableNames: 'Default'
	poolDictionaries: 'EventSensorConstants'
	category: 'VMMakerUI-InterpreterSimulation-Morphic'!

!SimulatorEventTransformer commentStamp: 'eem 7/14/2015 17:05' prior: 0!
A SimulatorEventTransformer takes events as wrapped by HandMorph and converts them to a form a StackInterpreterSimulator can deal with.

See HandMorph >> handleEvent to see what the wrapping entails.
See HandMorph >> ProcessEvents  or EventSensor >> fetchMoreEvents for examples of what an unwrapped event looks like when given to the system for pre-wrapping.

Instance Variables
!

----- Method: SimulatorEventTransformer class>>default (in category 'initialize-release') -----
default
	^Default ifNil:[Default := self new]!

----- Method: SimulatorEventTransformer class>>eventTypeMouse (in category 'accessing') -----
eventTypeMouse
	^EventTypeMouse!

----- Method: SimulatorEventTransformer>>degenerateEvent: (in category 'event transformation') -----
degenerateEvent: aMorphicEvent
	"tty. Bert had mentioned a distinction between events and polling events and that Morphic could handle both.
	I don't know what he is talking about."
	aMorphicEvent isMouse ifTrue:
		[^self degenerateMouseEvent: aMorphicEvent].
	aMorphicEvent isKeyboard ifTrue:
		[^self degenerateKeyboardEvent: aMorphicEvent].
"	type = EventTypeDragDropFiles ifTrue: [evt := self generateDropFilesEvent: evtBuf].
	type = EventTypeWindow	ifTrue:[evt := self generateWindowEvent: evtBuf]."

	^nil!

----- Method: SimulatorEventTransformer>>degenerateEvent:for: (in category 'event transformation') -----
degenerateEvent: aMorphicEvent for: client
	"Handle ''degenerating'' events for aClient.  This interface gets the client
	 to queue the event via queueForwardedEvent:, and may generate more
	 than one event for the input event (i.e. a fake mouse move before a
	 button down), in addition to filtering-out excessive mouse moves."
	aMorphicEvent isMouse ifTrue:
		[^self degenerateMouseEvent: aMorphicEvent for: client].
	aMorphicEvent isKeyboard ifTrue:
		[^self degenerateKeyboardEvent: aMorphicEvent for: client].
	^self degenerateUnknownEvent: aMorphicEvent for: client!

----- Method: SimulatorEventTransformer>>degenerateKeyboardEvent: (in category 'event transformation') -----
degenerateKeyboardEvent: aMorphicEvent
	"see HandMorph>>generateKeyboardEvent and EventSensor class comment"
	^{	2.
		aMorphicEvent timeStamp.
		aMorphicEvent keyValue.		"<--this is wrong. See Sensor FirstEvt: for what needs to happen. hooo boy"
		aMorphicEvent type caseOf: {
					[#keyDown]	->	[EventKeyDown].
					[#keyUp]		->	[EventKeyUp].
					[#keystroke]	->	[EventKeyChar] }.
		modifiers.
		aMorphicEvent keyValue.
		0.
		0 }!

----- Method: SimulatorEventTransformer>>degenerateKeyboardEvent:for: (in category 'event transformation') -----
degenerateKeyboardEvent: aMorphicEvent for: aClient
	"Convert the keyboard event into a low-level event for the VM simulator (aClient).
	 See HandMorph>>generateKeyboardEvent and EventSensor class comment"
	aClient queueForwardedEvent:
		{	2.
			aMorphicEvent timeStamp.
			aMorphicEvent keyValue.		"<--this is wrong. See Sensor FirstEvt: for what needs to happen. hooo boy"
			aMorphicEvent type caseOf: {
						[#keyDown]	->	[EventKeyDown].
						[#keyUp]		->	[EventKeyUp].
						[#keystroke]	->	[EventKeyChar] }.
			modifiers.
			aMorphicEvent keyValue.
			0.
			self windowIndex }!

----- Method: SimulatorEventTransformer>>degenerateMouseEvent: (in category 'event transformation') -----
degenerateMouseEvent: aMorphicEvent
	"see HandMorph>>generateMouseEvent"

	modifiers := aMorphicEvent buttons >> 3. "Sad, but modifiers come in on mouse move events..."
	aMorphicEvent type == #mouseMove
		ifTrue: [buttons = 0 ifTrue: [^nil]] "filter-out mouse moves unless buttons are pressed, so simulation doersn't get window leave events when we leave its window"
		ifFalse: [buttons := aMorphicEvent buttons].
	^{	1.
		aMorphicEvent timeStamp.
		aMorphicEvent position x.
		aMorphicEvent position y.
		buttons bitAnd: 7.  "thanks Ron T."
		buttons >> 3.     "Thanks dtl"
		0.
		0 }!

----- Method: SimulatorEventTransformer>>degenerateMouseEvent:for: (in category 'event transformation') -----
degenerateMouseEvent: aMorphicEvent for: aClient
	"Convert the mouse event into low-level events for the VM simulator (aClient).  Filter-out mouse moves,
	 and generate a fake mouse move before each button press.
	 See HandMorph>>generateMouseEvent"
	| translated |
	translated := aMorphicEvent position - aClient displayView bounds origin.
	modifiers := aMorphicEvent buttons >> 3. "Sad, but modifiers come in on mouse move events..."

	aMorphicEvent type == #mouseMove
		ifTrue: "filter-out mouse moves unless buttons are pressed, so simulation doesn't get window leave events when we leave its window"
			[buttons = 0 ifTrue: [^nil]]
		ifFalse:"If the buttons are going down, make sure to add a mouse move event to the current position before the buttons are pressed."
			[((buttons bitAnd: 7) = 0 and: [(aMorphicEvent buttons bitAnd: 7) ~= 0]) ifTrue:
				[aClient queueForwardedEvent:
							{	1.
								aMorphicEvent timeStamp.
								translated x.
								translated y.
								0.
								buttons >> 3.     "Thanks dtl"
								0.
								self windowIndex }].
				 buttons := aMorphicEvent buttons].
	aClient queueForwardedEvent:
			{	1.
				aMorphicEvent timeStamp.
				translated x.
				translated y.
				buttons bitAnd: 7.  "thanks Ron T."
				buttons >> 3.     "Thanks dtl"
				0.
				self windowIndex }!

----- Method: SimulatorEventTransformer>>initialize (in category 'initialize-release') -----
initialize
	buttons := modifiers := 0!

----- Method: SimulatorEventTransformer>>windowIndex (in category 'event transformation') -----
windowIndex
	^1!

Inspector subclass: #VMObjectInspector
	instanceVariableNames: 'memory coInterpreter objectMemory cogit'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'VMMakerUI-SqueakInspectors'!

----- Method: VMObjectInspector class>>memory:coInterpreter:objectMemory: (in category 'instance creation') -----
memory: aByteArray coInterpreter: aStackInterpreter objectMemory: anObjectMemory
	^self new memory: aByteArray coInterpreter: aStackInterpreter objectMemory: anObjectMemory cogit: nil!

----- Method: VMObjectInspector class>>memory:coInterpreter:objectMemory:cogit: (in category 'instance creation') -----
memory: aByteArray coInterpreter: aStackInterpreter objectMemory: anObjectMemory cogit: aCogit
	^self new memory: aByteArray coInterpreter: aStackInterpreter objectMemory: anObjectMemory  cogit: aCogit!

----- Method: VMObjectInspector>>memory:coInterpreter:objectMemory:cogit: (in category 'initialization') -----
memory: aByteArray coInterpreter: aStackInterpreter objectMemory: anObjectMemory cogit: aCogit
	memory := aByteArray.
	coInterpreter := aStackInterpreter.
	objectMemory := anObjectMemory.
	cogit := aCogit!

----- Method: StackInterpreterSimulator>>openAsMorph (in category '*VMMakerUI-InterpreterSimulation-Morphic') -----
openAsMorph
	"Open a morphic view on this simulation."
	| localImageName borderWidth window |
	localImageName := imageName
							ifNotNil: [self localNameFor: imageName]
							ifNil: [' synthetic image'].
	window := (SystemWindow labelled: 'Simulation of ', localImageName) model: self.
	window paneColor: self windowColorToUse.

	window addMorph: (displayView := SimulatorImageMorph new image: displayForm)
			frame: (0 at 0 corner: 1 at 0.8).
	displayView activeHand addEventListener: self.
	eventTransformer := SimulatorEventTransformer new.

	transcript := TranscriptStream on: (String new: 10000).
	window addMorph: (PluggableTextMorph
							on: transcript text: nil accept: nil
							readSelection: nil menu: #codePaneMenu:shifted:)
			frame: (0 at 0.8 corner: 0.7 at 1).
	window addMorph: (PluggableTextMorph on: self
						text: #byteCountText accept: nil
						readSelection: nil menu: #utilitiesMenu:) hideScrollBarsIndefinitely
			frame: (0.7 at 0.8 corner: 1 at 1).

	borderWidth := [SystemWindow borderWidth] "Squeak 4.1"
						on: MessageNotUnderstood
						do: [:ex| 0]. "3.8"
	borderWidth := borderWidth + window borderWidth.
	window openInWorldExtent: (self desiredDisplayExtent
								+ (2 * borderWidth at borderWidth)
								+ (0 at window labelHeight)
								* (1@(1/0.8))) rounded.
	^window!

----- Method: StackInterpreterSimulator>>openAsMorphNoTranscript (in category '*VMMakerUI-InterpreterSimulation-Morphic') -----
openAsMorphNoTranscript
	"Open a morphic view on this simulation."
	| localImageName borderWidth window |
	localImageName := imageName
							ifNotNil: [self localNameFor: imageName]
							ifNil: [' synthetic image'].
	window := (SystemWindow labelled: 'Simulation of ', localImageName) model: self.
	window paneColor: self windowColorToUse.

	window addMorph: (displayView := SimulatorImageMorph new image: displayForm)
			frame: (0 at 0 corner: 1 at 0.95).
	displayView activeHand addEventListener: self.
	eventTransformer := SimulatorEventTransformer new.

	window addMorph: (PluggableTextMorph on: self
						text: #byteCountText accept: nil
						readSelection: nil menu: #utilitiesMenu:) hideScrollBarsIndefinitely
		frame: (0 at 0.95 corner: 1 at 1).

	borderWidth := [SystemWindow borderWidth] "Squeak 4.1"
						on: MessageNotUnderstood
						do: [:ex| 0]. "3.8"
	borderWidth := borderWidth + window borderWidth.
	window openInWorldExtent: (self desiredDisplayExtent
								+ (2 * borderWidth at borderWidth)
								+ (0 at window labelHeight)
								* (1@(1/0.95))) rounded!

----- Method: StackInterpreterSimulator>>openAsSimulatorMorph (in category '*VMMakerUI-InterpreterSimulation-Morphic') -----
openAsSimulatorMorph
	"Open a morphic view on this simulation. ala Bert Freudenberg's
	SqueakJS http://lively-web.org/users/bert/squeak.html	"
	| localImageName borderWidth window |
	localImageName := imageName
							ifNil: [' synthetic image']
							ifNotNil: [self localNameFor: imageName].

	transcript := TranscriptStream on: (String new: 10000).

	window := SimulatorMorph	
					withVMSimulator: self 
					title: 'Simulation of ' , localImageName, ' (beta)'
					transcript: transcript.				

	borderWidth := [SimulatorMorph borderWidth] "Squeak 4.1"
						on: MessageNotUnderstood
						do: [:ex | 0].
	"3.8"
	borderWidth := borderWidth + window borderWidth.
	window openInWorldExtent: (self desiredDisplayExtent + (2 * borderWidth) + (0 @ window labelHeight) * (1 @ (1 / 0.8))) rounded.
	^window!



More information about the Vm-dev mailing list