'From Cuis 1.0 of 28 July 2009 [latest update: #242] on 30 July 2009 at 5:08:31 pm'!
!classDefinition: #PluggableTextMorph category: #'Morphic-Windows'!
ScrollPane subclass: #PluggableTextMorph
	instanceVariableNames: 'textMorph getTextSelector setTextSelector getSelectionSelector hasUnacceptedEdits askBeforeDiscardingEdits selectionInterval hasEditingConflicts editorClass '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Morphic-Windows'!

!FillInTheBlankMorph methodsFor: 'initialization' stamp: 'jmv 7/30/2009 16:48'!
createTextPaneExtent: answerExtent acceptBoolean: acceptBoolean
	"create the textPane"
	| result frame |
	result := PluggableTextMorph
				on: self
				editorClass: TextEditor
				text: #response
				accept: #response:
				readSelection: #selectionInterval
				menu: #paneMenu:shifted:editorClass:.
	result extent: answerExtent.
	result borderWidth: 1.
	result hasUnacceptedEdits: true.
	result acceptOnCR: acceptBoolean.
	frame := LayoutFrame new.
	frame leftFraction: 0.0;
		 rightFraction: 1.0;
		 topFraction: 0.2;
		 bottomFraction: 0.7.
	result layoutFrame: frame.
	self addMorph: result.
	^ result! !

!FillInTheBlankMorph methodsFor: 'menu' stamp: 'jmv 7/30/2009 16:42'!
paneMenu: aMenu shifted: shifted editorClass: anEditorClass

	^ StringHolder new paneMenu: aMenu shifted: shifted editorClass: anEditorClass! !


!ObjectExplorer methodsFor: 'accessing' stamp: 'jmv 7/30/2009 16:48'!
explorerFor: anObject 
	| window listMorph |
	rootObject := anObject.
	window := (SystemWindow labelled: (rootObject printStringLimitedTo: 64)) model: self.
	window addMorph: (listMorph := SimpleHierarchicalListMorph 
						on: self
						list: #getList
						selected: #getCurrentSelection
						changeSelected: #noteNewSelection:
						menu: #genericMenu:
						keystroke: #explorerKey:from:)
		frame: (0 @ 0 corner: 1 @ 0.8).
	window 
		addMorph: ((PluggableTextMorph 
				on: self
				editorClass: self editorClass
				text: #trash
				accept: #trash:
				readSelection: #contentsSelection
				menu: #paneMenu:shifted:editorClass:) askBeforeDiscardingEdits: false)
		frame: (0 @ 0.8 corner: 1 @ 1).
	listMorph autoDeselect: false.
	^window! !

!ObjectExplorer methodsFor: 'menus' stamp: 'jmv 7/30/2009 16:42'!
paneMenu: aMenu shifted: shifted editorClass: anEditorClass
	"Note that unless we override perform:orSendTo:, PluggableTextController will respond to all menu items"
	^ StringHolder basicNew paneMenu: aMenu shifted: shifted editorClass: anEditorClass
! !


!ProcessBrowser methodsFor: 'views' stamp: 'jmv 7/30/2009 10:00'!
asPrototypeInWindow
	"Create a pluggable version of me, answer a window"

	| window aTextMorph |
	window _ SystemWindow new model: self.
	window
		addMorph: ((PluggableListMorph
				on: self
				list: #processNameList
				selected: #processListIndex
				changeSelected: #processListIndex:
				menu: #processListMenu:
				keystroke: #processListKey:from:)
				enableDragNDrop: false)
		frame: (0 @ 0 extent: 0.5 @ 0.5).
	window
		addMorph: ((PluggableListMorph
				on: self
				list: #stackNameList
				selected: #stackListIndex
				changeSelected: #stackListIndex:
				menu: #stackListMenu:
				keystroke: #stackListKey:from:)
				enableDragNDrop: false)
		frame: (0.5 @ 0.0 extent: 0.5 @ 0.5).
	aTextMorph _ PluggableTextMorph
				on: self
				editorClass: TextEditor
				text: #selectedMethod
				accept: nil
				readSelection: nil
				menu: nil.
	window
		addMorph: aTextMorph
		frame: (0 @ 0.5 corner: 1 @ 1).
	window setLabel: 'Process Browser'.
	^ window! !

!ProcessBrowser methodsFor: 'views' stamp: 'jmv 7/30/2009 10:00'!
openAsMorph
	"Create a pluggable version of me, answer a window"
	| window aTextMorph |
	window _ SystemWindow new
				model: self.

	deferredMessageRecipient _ WorldState.
	window
		addMorph: ((PluggableListMorph
				on: self
				list: #processNameList
				selected: #processListIndex
				changeSelected: #processListIndex:
				menu: #processListMenu:
				keystroke: #processListKey:from:)
				enableDragNDrop: false)
		frame: (0 @ 0 extent: 0.5 @ 0.5).
	window
		addMorph: ((PluggableListMorph
				on: self
				list: #stackNameList
				selected: #stackListIndex
				changeSelected: #stackListIndex:
				menu: #stackListMenu:
				keystroke: #stackListKey:from:)
				enableDragNDrop: false)
		frame: (0.5 @ 0.0 extent: 0.5 @ 0.5).
	aTextMorph _ PluggableTextMorph
				on: self
				editorClass: TextEditor
				text: #selectedMethod
				accept: nil
				readSelection: nil
				menu: nil.
	aTextMorph askBeforeDiscardingEdits: false.
	window
		addMorph: aTextMorph
		frame: (0 @ 0.5 corner: 1 @ 1).
	window setUpdatablePanesFrom: #(#processNameList #stackNameList ).
	(window setLabel: 'Process Browser') openInWorld.
	startedCPUWatcher ifTrue: [ self setUpdateCallbackAfter: 7 ].
	^ window! !


!ScrollPane methodsFor: 'menu' stamp: 'jmv 7/30/2009 16:45'!
getMenu: shiftKeyState
	"Answer the menu for this text view, supplying an empty menu to be filled in. If the menu selector takes an extra argument, pass in the current state of the shift key."
	| menu aMenu aTitle |
	getMenuSelector == nil ifTrue: [^ nil].
	menu _ MenuMorph new defaultTarget: model.
	aTitle _ getMenuTitleSelector ifNotNil: [model perform: getMenuTitleSelector].
	getMenuSelector numArgs = 1 ifTrue: [
		aMenu _ model perform: getMenuSelector with: menu.
		aTitle ifNotNil:  [aMenu addTitle: aTitle].
		^ aMenu].
	getMenuSelector numArgs = 2 ifTrue: [
		aMenu _ model perform: getMenuSelector with: menu with: shiftKeyState.
		aTitle ifNotNil:  [aMenu addTitle: aTitle].
		^ aMenu].
	^ self error: 'The getMenuSelector has an unsupported number of arguments'! !


!PluggableTextMorph methodsFor: 'accessing' stamp: 'jmv 7/30/2009 11:36'!
editorClass
	^editorClass! !

!PluggableTextMorph methodsFor: 'initialization' stamp: 'jmv 7/30/2009 11:36'!
on: anObject editorClass: anEditorClass text: getTextSel accept: setTextSel readSelection: getSelectionSel menu: getMenuSel

	editorClass _ anEditorClass.
	self model: anObject.
	getTextSelector _ getTextSel.
	setTextSelector _ setTextSel.
	getSelectionSelector _ getSelectionSel.
	getMenuSelector _ getMenuSel.
	self borderWidth: 1.
	self setText: self getText.
	self setSelection: self getSelection.! !

!PluggableTextMorph methodsFor: 'menu' stamp: 'jmv 7/30/2009 16:47'!
getMenu: shiftKeyState
	"Answer the menu for this text view, supplying an empty menu to be filled in. If the menu selector takes an extra argument, pass in the current state of the shift key. The third argument, if required, is the editorClass."
	| menu aMenu aTitle |
	getMenuSelector == nil ifTrue: [^ nil].
	getMenuSelector numArgs = 3 ifFalse: [
		^super getMenu: shiftKeyState ].
	
	menu _ MenuMorph new defaultTarget: model.
	aTitle _ getMenuTitleSelector ifNotNil: [model perform: getMenuTitleSelector].
	aMenu _ model perform: getMenuSelector with: menu with: shiftKeyState with: editorClass.
	aTitle ifNotNil:  [aMenu addTitle: aTitle].
	^ aMenu! !


!PluggableTextMorph class methodsFor: 'as yet unclassified' stamp: 'jmv 7/30/2009 09:46'!
on: anObject editorClass: anEditorClass text: getTextSel accept: setTextSel

	^ self
		on: anObject
		editorClass: anEditorClass
		text: getTextSel
		accept: setTextSel
		readSelection: nil
		menu: nil! !

!PluggableTextMorph class methodsFor: 'as yet unclassified' stamp: 'jmv 7/30/2009 09:46'!
on: anObject editorClass: anEditorClass text: getTextSel accept: setTextSel readSelection: getSelectionSel menu: getMenuSel

	^ self new 
		on: anObject
		editorClass: anEditorClass
		text: getTextSel
		accept: setTextSel
		readSelection: getSelectionSel
		menu: getMenuSel! !


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

!StringHolder methodsFor: 'initialize-release' stamp: 'jmv 7/30/2009 16:49'!
openAsMorphEditorClass: anEditorClass label: labelString  inWorld: aWorld
	"Workspace new openAsMorphLabel: 'Workspace'"
	| window |
	window _ (SystemWindow labelled: labelString) model: self.

	window addMorph: (PluggableTextMorph 
			on: self 
			editorClass: anEditorClass
			text: #contents 
			accept: #acceptContents:
			readSelection: nil 
			menu: #paneMenu:shifted:editorClass:)
		frame: (0@0 corner: 1@1).

	window openInWorld: aWorld! !

!StringHolder methodsFor: 'initialize-release' stamp: 'jmv 7/30/2009 17:06'!
openAsMorphLabel: labelString inWorld: aWorld
	"Workspace new openAsMorphLabel: 'Workspace'"

	self 
		openAsMorphEditorClass: self editorClass 
		label: labelString 
		inWorld: aWorld! !

!StringHolder methodsFor: 'code pane menu' stamp: 'jmv 7/30/2009 16:40'!
paneMenu: aMenu shifted: shifted editorClass: anEditorClass
	"Note that unless we override perform:orSendTo:, PluggableTextController will respond to all menu items in a text pane"
	| donorMenu |
	donorMenu _ shifted
		ifTrue: [
			anEditorClass shiftedYellowButtonMenu]
		ifFalse: [
			anEditorClass yellowButtonMenu].
	aMenu labels: donorMenu labelString lines: donorMenu lineArray selections: donorMenu selections.
	aMenu addTitle: 'Text Editor'; addStayUpIcons.
	^aMenu! !


!CodeHolder methodsFor: 'annotation' stamp: 'jmv 7/30/2009 10:03'!
addOptionalAnnotationsTo: window at: fractions plus: verticalOffset
	"Add an annotation pane to the window if preferences indicate a desire for it, and return the incoming verticalOffset plus the height of the added pane, if any"

	| aTextMorph divider delta |
	self wantsAnnotationPane ifFalse: [^ verticalOffset].
	aTextMorph _ PluggableTextMorph 
		on: self
		editorClass: self editorClass
		text: #annotation 
		accept: nil.
	aTextMorph
		askBeforeDiscardingEdits: false;
		borderWidth: 0;
		hideScrollBarsIndefinitely.
	divider _ BorderedSubpaneDividerMorph forBottomEdge.
	Preferences alternativeWindowLook ifTrue:[
		divider extent: 4@4; color: Color transparent; borderColor: #raised; borderWidth: 2.
	].
	delta _ self defaultAnnotationPaneHeight.
	window 
		addMorph: aTextMorph 
		fullFrame: (LayoutFrame 
				fractions: fractions 
				offsets: (0@verticalOffset corner: 0@(verticalOffset + delta - 1))).
	window 
		addMorph: divider
		fullFrame: (LayoutFrame 
				fractions: fractions 
				offsets: (0@(verticalOffset + delta - 1) corner: 0@(verticalOffset + delta))).
	^ verticalOffset + delta! !

!CodeHolder methodsFor: 'construction' stamp: 'jmv 7/30/2009 16:48'!
buildMorphicCodePaneWith: editString
	"Construct the pane that shows the code.
	Respect the Preference for standardCodeFont."

	| codePane |
	codePane := PluggableTextMorph
				on: self
				editorClass: self editorClass
				text: #contents
				accept: #contents:notifying:
				readSelection: #contentsSelection
				menu: #paneMenu:shifted:editorClass:.
	codePane font: Preferences standardCodeFont.
	editString
		ifNotNil: [codePane editString: editString.
			codePane hasUnacceptedEdits: true].
	^ codePane! !

!CodeHolder methodsFor: 'categories & search pane' stamp: 'jmv 7/30/2009 09:49'!
newSearchPane
	"Answer a new search pane for the receiver"

	| aTextMorph |
	aTextMorph _ PluggableTextMorph
		on: self
		editorClass: self editorClass
		text: #lastSearchString 
		accept: #lastSearchString:
		readSelection: nil 
		menu: nil.
	aTextMorph setProperty: #alwaysAccept toValue: true.
	aTextMorph askBeforeDiscardingEdits: false.
	aTextMorph acceptOnCR: true.
	aTextMorph setBalloonText: 'Type here and hit ENTER, and all methods whose selectors match what you typed will appear in the list pane below.'.
	^ aTextMorph! !


!Browser methodsFor: 'class comment pane' stamp: 'jmv 7/30/2009 16:47'!
buildMorphicCommentPane
	"Construct the pane that shows the class comment.
	Respect the Preference for standardCodeFont."

	| commentPane |
	commentPane := BrowserCommentTextMorph
				on: self
				editorClass: self editorClass
				text: #classCommentText
				accept: #classComment:notifying:
				readSelection: nil
				menu: #paneMenu:shifted:editorClass:.
	commentPane font: Preferences standardCodeFont.
	^ commentPane! !


!ChangeList methodsFor: 'menu actions' stamp: 'jmv 7/30/2009 16:47'!
buildMorphicCodePaneWith: editString

	| codePane |

	codePane _ AcceptableCleanTextMorph
		on: self
		editorClass: self editorClass
		text: #contents 
		accept: #contents:
		readSelection: #contentsSelection 
		menu: #paneMenu:shifted:editorClass:.
	editString ifNotNil: [
		codePane editString: editString.
		codePane hasUnacceptedEdits: true
	].
	^codePane
! !


!Debugger methodsFor: 'initialize' stamp: 'jmv 7/30/2009 16:49'!
openFullMorphicLabel: aLabelString
	"Open a full morphic debugger with the given label"

	| window aListMorph oldContextStackIndex |
	oldContextStackIndex _ contextStackIndex.
	self expandStack. "Sets contextStackIndex to zero."

	window _ (SystemWindow labelled: aLabelString) model: self.
	aListMorph _ PluggableListMorph
		on: self list: #contextStackList
		selected: #contextStackIndex
		changeSelected: #toggleContextStackIndex:
		menu: #contextStackMenu:shifted:
		keystroke: #contextStackKey:from:.
	aListMorph menuTitleSelector: #messageListSelectorTitle.
	window addMorph: aListMorph
		frame: (0@0 corner: 1@0.25).

	self addLowerPanesTo: window at: (0@0.25 corner: 1@0.8) with: nil.

	window addMorph: (
		PluggableListMorph new
			doubleClickSelector: #inspectSelection;
			on: self receiverInspector
			list: #fieldList
			selected: #selectionIndex 
			changeSelected: #toggleIndex:
			menu: #fieldListMenu: 
			keystroke: #inspectorKey:from:)
		frame: (0@0.8 corner: 0.2@1).
	window addMorph: (PluggableTextMorph 
			on: self receiverInspector
			editorClass: self receiverInspector editorClass
			text: #contents 
			accept: #accept:
			readSelection: #contentsSelection 
			menu: #paneMenu:shifted:editorClass:)
		frame: (0.2@0.8 corner: 0.5@1).
	window addMorph: (
		PluggableListMorph new
			doubleClickSelector: #inspectSelection;
			on: self contextVariablesInspector 
			list: #fieldList
			selected: #selectionIndex 
			changeSelected: #toggleIndex:
			menu: #fieldListMenu: 
			keystroke: #inspectorKey:from:)
		frame: (0.5@0.8 corner: 0.7@1).
	window addMorph: (PluggableTextMorph 
			on: self contextVariablesInspector
			editorClass: self contextVariablesInspector editorClass
			text: #contents 
			accept: #accept:
			readSelection: #contentsSelection 
			menu: #paneMenu:shifted:editorClass:)
		frame: (0.7@0.8 corner: 1@1).
	window openInWorld.
	self toggleContextStackIndex: oldContextStackIndex.
	^ window ! !

!Debugger methodsFor: 'context stack menu' stamp: 'jmv 7/30/2009 09:49'!
buildMorphicNotifierLabelled: label message: messageString 
	| notifyPane window contentTop extentToUse |
	self expandStack.
	window := (PreDebugWindow labelled: label) model: self.
	contentTop := 0.2.
	extentToUse := 650 @ 320.	"nice and wide to show plenty of the error msg"
	window addMorph: (self buttonRowForPreDebugWindow: window)
		frame: (0 @ 0 corner: 1 @ contentTop).
	messageString notNil 
		ifFalse: [
			notifyPane := PluggableListMorph 
						on: self
						list: #contextStackList
						selected: #contextStackIndex
						changeSelected: #debugAt:
						menu: nil
						keystroke: nil]
		ifTrue: [
			notifyPane := PluggableTextMorph 
						on: self
						editorClass: self editorClass
						text: nil
						accept: nil
						readSelection: nil
						menu: #debugProceedMenu:.
			notifyPane
				editString: (self preDebugNotifierContentsFrom: messageString);
				askBeforeDiscardingEdits: false].
	window addMorph: notifyPane frame: (0 @ contentTop corner: 1 @ 1).
	^window openInWorldExtent: extentToUse! !

!Debugger methodsFor: 'as yet unclassified' stamp: 'jmv 7/30/2009 16:39'!
paneMenu: aMenu shifted: shifted editorClass: anEditorClass
	aMenu add: 'run to here' target: self selector: #runToSelection: argument: thisContext sender receiver selectionInterval.
	aMenu addLine.
	super paneMenu: aMenu shifted: shifted editorClass: anEditorClass.
	^aMenu.! !


!FileContentsBrowser methodsFor: 'creation' stamp: 'jmv 7/30/2009 16:48'!
addLowerPanesTo: window at: nominalFractions with: editString

	| verticalOffset column codePane infoPane infoHeight divider |


	column _ AlignmentMorph proportional.

	codePane _ PluggableTextMorph 
		on: self 
		editorClass: self editorClass
		text: #contents 
		accept: #contents:notifying:
		readSelection: #contentsSelection 
		menu: #paneMenu:shifted:editorClass:.
	infoPane _ PluggableTextMorph 
		on: self 
		editorClass: self editorClass
		text: #infoViewContents 
		accept: nil
		readSelection: nil 
		menu: nil.
	infoPane askBeforeDiscardingEdits: false.
	verticalOffset _ 0.

">>not with this browser--- at least not yet ---
	innerFractions _ 0@0 corner: 1@0.
	verticalOffset _ self addOptionalAnnotationsTo: row at: innerFractions plus: verticalOffset.
	verticalOffset _ self addOptionalButtonsTo: row  at: innerFractions plus: verticalOffset.
<<<<"

	infoHeight _ 20.
	column 
		addMorph: (codePane borderWidth: 0)
		fullFrame: (
			LayoutFrame 
				fractions: (0@0 corner: 1@1) 
				offsets: (0@verticalOffset corner: 0@infoHeight negated)
		).
	divider _ BorderedSubpaneDividerMorph forTopEdge.
	Preferences alternativeWindowLook ifTrue:[
		divider extent: 4@4; color: Color transparent; borderColor: #raised; borderWidth: 2.
	].
	column 
		addMorph: divider
		fullFrame: (
			LayoutFrame 
				fractions: (0@1 corner: 1@1) 
				offsets: (0@infoHeight negated corner: 0@(1-infoHeight))
		).
	column 
		addMorph: (infoPane borderWidth: 0; hideScrollBarsIndefinitely)
		fullFrame: (
			LayoutFrame 
				fractions: (0@1 corner: 1@1) 
				offsets: (0@(1-infoHeight) corner: 0@0)
		).
	window 
		addMorph: column
		frame: nominalFractions.

	column on: #mouseEnter send: #paneTransition: to: window.
	column on: #mouseLeave send: #paneTransition: to: window! !


!FileList class methodsFor: 'instance creation' stamp: 'jmv 7/30/2009 11:13'!
addVolumesAndPatternPanesTo: window at: upperFraction plus: offset forFileList: aFileList 
	| column patternHeight volumeListMorph patternMorph divider dividerDelta |
	column _ AlignmentMorph proportional.
	patternHeight _ 25.
	volumeListMorph _ (PluggableListMorph
				on: aFileList
				list: #volumeList
				selected: #volumeListIndex
				changeSelected: #volumeListIndex:
				menu: #volumeMenu:)
				autoDeselect: false.
	volumeListMorph enableDrag: false; enableDrop: true.
	patternMorph _ PluggableTextMorph
				on: aFileList
				editorClass: aFileList editorClass
				text: #pattern
				accept: #pattern:.
	patternMorph acceptOnCR: true.
	patternMorph hideScrollBarsIndefinitely.
	divider _ BorderedSubpaneDividerMorph new.
	dividerDelta _ 0.
	Preferences alternativeWindowLook
		ifTrue: [
			divider
				extent: 4 @ 4;
				color: Color transparent;
				borderColor: #raised;
				borderWidth: 2.
			volumeListMorph borderColor: Color transparent.
			patternMorph borderColor: Color transparent.
			dividerDelta _ 3].
	column
		addMorph: (volumeListMorph autoDeselect: false)
		fullFrame: (LayoutFrame
				fractions: (0 @ 0 corner: 1 @ 1)
				offsets: (0 @ 0 corner: 0 @ patternHeight negated - dividerDelta)).
	column
		addMorph: divider
		fullFrame: (LayoutFrame
				fractions: (0 @ 1 corner: 1 @ 1)
				offsets: (0 @ patternHeight negated - dividerDelta corner: 0 @ patternHeight negated)).
	column
		addMorph: patternMorph
		fullFrame: (LayoutFrame
				fractions: (0 @ 1 corner: 1 @ 1)
				offsets: (0 @ patternHeight negated corner: 0 @ 0)).
	window
		addMorph: column
		fullFrame: (LayoutFrame
				fractions: upperFraction
				offsets: (0 @ offset corner: 0 @ 0)).
	Preferences alternativeWindowLook
		ifTrue: [column borderWidth: 2] ifFalse: [column borderWidth: 0]! !

!FileList class methodsFor: 'instance creation' stamp: 'jmv 7/30/2009 11:17'!
openAsMorph
	"Open a morphic view of a FileList on the default directory."

	| dir aFileList window upperFraction offset |
	dir := FileDirectory default.
	aFileList := self new directory: dir.
	window := (SystemWindow labelled: dir pathName) model: aFileList.
	upperFraction := 0.3.
	offset := 0.
	self 
		addVolumesAndPatternPanesTo: window
		at: (0 @ 0 corner: 0.3 @ upperFraction)
		plus: offset
		forFileList: aFileList.
	self 
		addButtonsAndFileListPanesTo: window
		at: (0.3 @ 0 corner: 1.0 @ upperFraction)
		plus: offset
		forFileList: aFileList.
	window addMorph: (PluggableTextMorph 
			on: aFileList
			editorClass: aFileList editorClass
			text: #contents
			accept: #put:
			readSelection: #contentsSelection
			menu: #fileContentsMenu:shifted:)
		frame: (0 @ 0.3 corner: 1 @ 1).
	^window openInWorld! !

!FileList class methodsFor: 'instance creation' stamp: 'jmv 7/30/2009 11:17'!
openMorphOn: aFileStream editString: editString 
	"Open a morphic view of a FileList on the given file."
	| fileModel window fileContentsView |

	fileModel _ FileList new setFileStream: aFileStream.	"closes the stream"
	window _ (SystemWindow labelled: aFileStream fullName) model: fileModel.

	window addMorph: (fileContentsView _ PluggableTextMorph 
			on: fileModel 
			editorClass: fileModel editorClass
			text: #contents 
			accept: #put:
			readSelection: #contentsSelection 
			menu: #fileContentsMenu:shifted:)
		frame: (0@0 corner: 1@1).
	editString ifNotNil: [fileContentsView editString: editString.
			fileContentsView hasUnacceptedEdits: true].

	^ window! !


!FileList2 methodsFor: 'user interface' stamp: 'jmv 7/30/2009 09:53'!
morphicFileContentsPane

	^PluggableTextMorph 
		on: self 
		editorClass: self editorClass
		text: #contents 
		accept: #put:
		readSelection: #contentsSelection 
		menu: #fileContentsMenu:shifted:
! !

!FileList2 methodsFor: 'user interface' stamp: 'jmv 7/30/2009 10:03'!
morphicPatternPane

	^PluggableTextMorph 
		on: self 
		editorClass: self editorClass
		text: #pattern 
		accept: #pattern:
		
! !


!Inspector class methodsFor: 'instance creation' stamp: 'jmv 7/30/2009 16:49'!
openAsMorphOn: anObject withLabel: aLabel
	"(Inspector openAsMorphOn: SystemOrganization) openInMVC"
	| window inspector |
	inspector _ self inspect: anObject.
	window _ (SystemWindow labelled: aLabel) model: inspector.
	window addMorph: (
		PluggableListMorph new
			doubleClickSelector: #inspectSelection;

			on: inspector 
			list: #fieldList
			selected: #selectionIndex
			changeSelected: #toggleIndex:
			menu: ((inspector isMemberOf: DictionaryInspector)
					ifTrue: [#dictionaryMenu:]
					ifFalse: [#fieldListMenu:])
			keystroke: #inspectorKey:from:)
		frame: (0@0 corner: self horizontalDividerProportion @ self verticalDividerProportion).
	window addMorph: (PluggableTextMorph
			on: inspector 
			editorClass: inspector editorClass 
			text: #contents 
			accept: #accept:
			readSelection: #contentsSelection 
			menu: #paneMenu:shifted:editorClass:)
		frame: (self horizontalDividerProportion @0 corner: 1@self verticalDividerProportion).
	window addMorph: ((PluggableTextMorph 
			on: inspector 
			editorClass: inspector editorClass
			text: #trash 
			accept: #trash:
			readSelection: #contentsSelection 
			menu: #paneMenu:shifted:editorClass:)
					askBeforeDiscardingEdits: false)
		frame: (0@self verticalDividerProportion corner: 1@1).
	window setUpdatablePanesFrom: #(fieldList).
	window position: 16@0.  "Room for scroll bar."
	^ window! !


!InspectorBrowser class methodsFor: 'as yet unclassified' stamp: 'jmv 7/30/2009 16:48'!
openAsMorphOn: anObject
	"(InspectorBrowser openAsMorphOn: SystemOrganization) openInMVC"
	| window inspector |
	inspector _ self inspect: anObject.
	window _ (SystemWindow labelled: anObject defaultLabelForInspector)
				model: inspector.

	window addMorph: (PluggableListMorph 
			on: inspector 
			list: #fieldList
			selected: #selectionIndex 
			changeSelected: #toggleIndex: 
			menu: #fieldListMenu:)
		frame: (0@0 corner: 0.3@0.5).
	window addMorph: (PluggableTextMorph 
			on: inspector 
			editorClass: inspector editorClass 
			text: #contents 
			accept: #accept:
			readSelection: nil 
			menu: #paneMenu:shifted:editorClass:)
		frame: (0.3@0 corner: 1.0@0.5).
	window addMorph: (PluggableListMorph 
			on: inspector 
			list: #msgList
			selected: #msgListIndex 
			changeSelected: #msgListIndex: 
			menu: #msgListMenu:)
		frame: (0@0.5 corner: 0.3@1.0).
	window addMorph: (PluggableTextMorph 
			on: inspector 
			editorClass: inspector editorClass 
			text: #msgText 
			accept: #msgAccept:from:
			readSelection: nil 
			menu: #msgPaneMenu:shifted:)
		frame: (0.3@0.5 corner: 1.0@1.0).
	
	window setUpdatablePanesFrom: #(fieldList msgList).
	window position: 16@0.  "Room for scroll bar."
	^ window! !


!MessageNames methodsFor: 'initialization' stamp: 'jmv 7/30/2009 11:20'!
inMorphicWindowWithInitialSearchString: initialString
	"Answer a morphic window with the given initial search string, nil if none"

"MessageNames openMessageNames"

	| window selectorListView firstDivider secondDivider horizDivider typeInPane searchButton plugTextMor |
	window _ (SystemWindow labelled: 'Message Names') model: self.
	firstDivider _ 0.07.
	secondDivider _ 0.5.
	horizDivider _ 0.5.
	typeInPane _ AlignmentMorph proportional height: 14.

	plugTextMor _ PluggableTextMorph 
		on: self
		editorClass: self editorClass
		text: #searchString 
		accept: #searchString:notifying:
		readSelection: nil 
		menu: nil.
	plugTextMor setProperty: #alwaysAccept toValue: true.
	plugTextMor askBeforeDiscardingEdits: false.
	plugTextMor acceptOnCR: true.
	plugTextMor setTextColor: Color brown.
	plugTextMor hideScrollBarsIndefinitely.
	plugTextMor setTextMorphToSelectAllOnMouseEnter.

	searchButton _ SimpleButtonMorph new 
		target: self;
		beTransparent;
		label: 'Search';
		actionSelector: #doSearchFrom:;
		arguments: {plugTextMor}.
	searchButton setBalloonText: 'Type some letters into the pane at right, and then press this Search button (or hit RETURN) and all method selectors that match what you typed will appear in the list pane below.  Click on any one of them, and all the implementors of that selector will be shown in the right-hand pane, and you can view and edit their code without leaving this tool.'.

	typeInPane addInProportionalRow: { searchButton. plugTextMor. }.
	initialString isEmptyOrNil ifFalse:
		[plugTextMor setText: initialString].

	window addMorph: typeInPane frame: (0@0 corner: horizDivider @ firstDivider).

	selectorListView _ PluggableListMorph on: self
		list: #selectorList
		selected: #selectorListIndex
		changeSelected: #selectorListIndex:
		menu: #selectorListMenu:
		keystroke: #selectorListKey:from:.
	selectorListView menuTitleSelector: #selectorListMenuTitle.
	window addMorph: selectorListView frame: (0 @ firstDivider corner: horizDivider @ secondDivider).

	window addMorph: self buildMorphicMessageList frame: (horizDivider @ 0 corner: 1@ secondDivider).

	self 
		addLowerPanesTo: window 
		at: (0 @ secondDivider corner: 1@1) 
		with: nil.

	initialString isEmptyOrNil ifFalse:
		[self searchString: initialString notifying: nil].
	^ window! !


!SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'jmv 7/30/2009 16:49'!
morphicWindow
	"Create a Browser that lets you type part of a selector, shows a list of selectors, shows the classes of the one you chose, and spawns a full browser on it.  Answer the window
	SelectorBrowser new open "

	| window typeInView selectorListView classListView |
	window := SystemWindow new model: self.
	selectorIndex := classListIndex := 0.
	typeInView := PluggableTextMorph 
				on: self
				editorClass: self editorClass
				text: #contents
				accept: #contents:notifying:
				readSelection: #contentsSelection
				menu: #paneMenu:shifted:editorClass:.
	typeInView acceptOnCR: true.
	typeInView hideScrollBarsIndefinitely.
	window addMorph: typeInView frame: (0 @ 0 corner: 0.5 @ 0.14).
	selectorListView := PluggableListMorph 
				on: self
				list: #messageList
				selected: #messageListIndex
				changeSelected: #messageListIndex:
				menu: #selectorMenu:
				keystroke: #messageListKey:from:.
	selectorListView menuTitleSelector: #selectorMenuTitle.
	window addMorph: selectorListView frame: (0 @ 0.14 corner: 0.5 @ 0.6).
	classListView := PluggableListMorph 
				on: self
				list: #classList
				selected: #classListIndex
				changeSelected: #classListIndex:
				menu: nil
				keystroke: #arrowKey:from:.
	classListView menuTitleSelector: #classListSelectorTitle.
	window addMorph: classListView frame: (0.5 @ 0 corner: 1 @ 0.6).
	window 
		addMorph: ((PluggableTextMorph 
				on: self
				editorClass: self editorClass
				text: #byExample
				accept: #byExample:
				readSelection: #contentsSelection
				menu: #paneMenu:shifted:editorClass:) askBeforeDiscardingEdits: false)
		frame: (0 @ 0.6 corner: 1 @ 1).
	window setLabel: 'Method Finder'.
	^window! !


!SyntaxError class methodsFor: 'instance creation' stamp: 'jmv 7/30/2009 16:50'!
buildMorphicViewOn: aSyntaxError
	"Answer an Morphic view on the given SyntaxError."
	| window |
	window _ (SystemWindow labelled: 'Syntax Error') model: aSyntaxError.

	window addMorph: (PluggableListMorph 
			on: aSyntaxError 
			list: #list
			selected: #listIndex 
			changeSelected: nil 
			menu: #listMenu:)
		frame: (0@0 corner: 1@0.15).

	window addMorph: (PluggableTextMorph 
			on: aSyntaxError 
			editorClass: aSyntaxError editorClass
			text: #contents
			accept: #contents:notifying: 
			readSelection: #contentsSelection
			menu: #paneMenu:shifted:editorClass:)
		frame: (0@0.15 corner: 1@1).

	^ window openInWorldExtent: 380@220! !


!TestRunner methodsFor: 'interface opening' stamp: 'jmv 7/30/2009 10:04'!
buildDetailsText
	detailsText _ PluggableTextMorph
		on: self
		editorClass: TextEditor
		text: #details
		accept: nil.
	detailsText hideScrollBarsIndefinitely.
	^detailsText! !

!TestRunner methodsFor: 'interface opening' stamp: 'jmv 7/30/2009 10:04'!
buildPassFailText
	passFailText _ PluggableTextMorph
		on: self
		editorClass: TextEditor
		text: #passFail
		accept: nil.
	passFailText hideScrollBarsIndefinitely.
	^ passFailText! !


!TextMorphForEditView methodsFor: 'private' stamp: 'jmv 7/30/2009 11:05'!
editorClass
	 | m |
	"ARREGLAR!! Nunca deberia ser nil!!"
	editView editorClass ifNotNil: [ ^editView editorClass ].
	m _ editView model.
	(m is: #knowsEditorClass) ifTrue: [
		^m editorClass ].
	^super editorClass! !


!TranscriptStream methodsFor: 'initialization' stamp: 'jmv 7/30/2009 16:50'!
openAsMorphLabel: labelString 
	"Build a morph viewing this transcriptStream"
	| window |
	window _ (SystemWindow labelled: labelString) model: self.
	window addMorph: (PluggableTextMorph 
			on: self 
			editorClass: self editorClass
			text: nil 
			accept: nil
			readSelection: nil 
			menu: #paneMenu:shifted:editorClass:)
		frame: (0@0 corner: 1@1).
	^ window! !

!TranscriptStream methodsFor: 'model protocol' stamp: 'jmv 7/30/2009 16:42'!
paneMenu: aMenu shifted: shifted editorClass: anEditorClass
	"Note that unless we override perform:orSendTo:, PluggableTextController will respond to all menu items"
	^ StringHolder basicNew paneMenu: aMenu shifted: shifted editorClass: anEditorClass
! !

TranscriptStream removeSelector: #paneMenu:shifted:!
Debugger removeSelector: #paneMenu:shifted:!
StringHolder removeSelector: #paneMenu:shifted:!
PluggableTextMorph class removeSelector: #on:text:accept:!
PluggableTextMorph class removeSelector: #on:text:accept:readSelection:menu:!
PluggableTextMorph removeSelector: #on:text:accept:readSelection:menu:!
!classDefinition: #PluggableTextMorph category: #'Morphic-Windows'!
ScrollPane subclass: #PluggableTextMorph
	instanceVariableNames: 'textMorph getTextSelector setTextSelector getSelectionSelector hasUnacceptedEdits askBeforeDiscardingEdits selectionInterval hasEditingConflicts editorClass'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Morphic-Windows'!
ObjectExplorer removeSelector: #paneMenu:shifted:!
FillInTheBlankMorph removeSelector: #paneMenu:shifted:!
"Postscript:
Leave the line above, and replace the rest of this comment by a useful one.
Executable statements should follow this comment, and should
be separated by periods, with no exclamation points (!!).
Be sure to put any further comments in double-quotes, like this one."
| c |
PluggableTextMorph allSubInstancesDo: [ :m | 
	(m instVarNamed: 'editorClass') ifNil: [
		c _ (m model is: #knowsEditorClass) 
			ifTrue: [ m model editorClass ]
			ifFalse: [ TextEditor ].
		m instVarNamed: 'editorClass' put: c ] ]!

