'From Cuis 2.6 of 10 August 2010 [latest update: #540] on 24 August 2010 at 12:51:17 pm'!

!CodeHolder methodsFor: 'diffs' stamp: 'jmv 8/24/2010 12:24'!
lineDiffButton
	"Return a checkbox that lets the user decide whether regular diffs should be shown or not"
	| outerButton button |
	outerButton _ AlignmentMorph proportional.
	outerButton
		 borderWidth: 2;
		 borderColor: #raised.
	outerButton color: Color transparent.
	button _ UpdatingThreePhaseButtonMorph checkBox.
	button
		 target: self;
		 actionSelector: #toggleLineDiffing;
		 getSelector: #showingLineDiffs.
	outerButton
		addMorph: button
		fullFrame:
			(LayoutFrame
				fractions: (0 @ 0 corner: 0 @ 1)
				offsets: (2 @ 3 corner: 18 @ 0));
		addMorph: (StringMorph contents: 'lineDiffs') lock
		fullFrame:
			(LayoutFrame
				fractions: (0 @ 0 corner: 1 @ 1)
				offsets: (18 @ 2 corner: 0 @ 0)).
	outerButton setBalloonText: 'Show code differences from the previous version, line by line.'.
	^ outerButton! !

!CodeHolder methodsFor: 'diffs' stamp: 'jmv 8/24/2010 12:24'!
prettyLineDiffButton
	"Return a checkbox that lets the user decide whether prettyDiffs should be shown or not"
	| outerButton button |
	outerButton _ AlignmentMorph proportional.
	outerButton
		 borderWidth: 2;
		 borderColor: #raised.
	outerButton color: Color transparent.
	button _ UpdatingThreePhaseButtonMorph checkBox.
	button
		 target: self;
		 actionSelector: #togglePrettyLineDiffing;
		 getSelector: #showingPrettyLineDiffs.
	outerButton
		addMorph: button
		fullFrame:
			(LayoutFrame
				fractions: (0 @ 0 corner: 0 @ 1)
				offsets: (2 @ 3 corner: 18 @ 0));
		addMorph: (StringMorph contents: 'linePrettyDiffs') lock
		fullFrame:
			(LayoutFrame
				fractions: (0 @ 0 corner: 1 @ 1)
				offsets: (18 @ 2 corner: 0 @ 0)).
	(self isKindOf: VersionsBrowser)
		ifTrue: [ outerButton setBalloonText: 'Show pretty-printed code differences from the previous version, line by line.' ]
		ifFalse: [ outerButton setBalloonText: 'Show pretty-printed code differences between the file-based method and the in-memory version, line by line.' ].
	^ outerButton.! !

!CodeHolder methodsFor: 'diffs' stamp: 'jmv 8/24/2010 12:24'!
prettyWordDiffButton
	"Return a checkbox that lets the user decide whether prettyDiffs should be shown or not"
	| outerButton button |
	outerButton _ AlignmentMorph proportional.
	outerButton
		 borderWidth: 2;
		 borderColor: #raised.
	outerButton color: Color transparent.
	button _ UpdatingThreePhaseButtonMorph checkBox.
	button
		 target: self;
		 actionSelector: #togglePrettyWordDiffing;
		 getSelector: #showingPrettyWordDiffs.
	outerButton
		addMorph: button
		fullFrame:
			(LayoutFrame
				fractions: (0 @ 0 corner: 0 @ 1)
				offsets: (2 @ 3 corner: 18 @ 0));
		addMorph: (StringMorph contents: 'wordPrettyDiffs') lock
		fullFrame:
			(LayoutFrame
				fractions: (0 @ 0 corner: 1 @ 1)
				offsets: (18 @ 2 corner: 0 @ 0)).
	(self isKindOf: VersionsBrowser)
		ifTrue: [ outerButton setBalloonText: 'Show pretty-printed code differences from the previous version, word by word.' ]
		ifFalse: [ outerButton setBalloonText: 'Show pretty-printed code differences between the file-based method and the in-memory version, word by word.' ].
	^ outerButton.! !

!CodeHolder methodsFor: 'diffs' stamp: 'jmv 8/24/2010 12:27'!
shouldDiffWords
	"Answer whether the receiver is currently set to use the word based differ"

	^ #(wordDiffs prettyWordDiffs) includes: contentsSymbol! !

!CodeHolder methodsFor: 'diffs' stamp: 'jmv 8/24/2010 12:23'!
wordDiffButton
	"Return a checkbox that lets the user decide whether regular diffs should be shown or not"
	| outerButton button |
	outerButton _ AlignmentMorph proportional.
	outerButton
		 borderWidth: 2;
		 borderColor: #raised.
	outerButton color: Color transparent.
	button _ UpdatingThreePhaseButtonMorph checkBox.
	button
		 target: self;
		 actionSelector: #toggleWordDiffing;
		 getSelector: #showingWordDiffs.
	outerButton
		addMorph: button
		fullFrame:
			(LayoutFrame
				fractions: (0 @ 0 corner: 0 @ 1)
				offsets: (2 @ 3 corner: 18 @ 0));
		addMorph: (StringMorph contents: 'wordDiffs') lock
		fullFrame:
			(LayoutFrame
				fractions: (0 @ 0 corner: 1 @ 1)
				offsets: (18 @ 2 corner: 0 @ 0)).
	outerButton setBalloonText: 'Show code differences (better algorithm) from the previous version.'.
	^ outerButton.! !

!CodeHolder methodsFor: 'message list' stamp: 'jmv 8/24/2010 12:34'!
sourceStringPrettifiedAndDiffed
	"Answer a copy of the source code for the selected message, transformed by diffing and pretty-printing exigencies"
	| class selector sourceString |
	class _ self selectedClassOrMetaClass.
	selector _ self selectedMessageName.
	(class isNil or: [ selector isNil ]) ifTrue: [ ^ 'missing' ].
	sourceString _ class
		ultimateSourceCodeAt: selector
		ifAbsent: [ ^ 'error' ].
	self
		validateMessageSource: sourceString
		forSelector: selector.
	(self showingPrettyPrint or: [ self showingAnyKindOfPrettyDiffs ]) ifTrue: [
		sourceString _ class compilerClass new
			format: sourceString
			in: class
			notifying: nil ].
	self showingAnyKindOfDiffs ifTrue: [
		sourceString _ self diffFromPriorSourceFor: sourceString ].
	^ sourceString! !


!DifferenceFinder class methodsFor: 'compatibility' stamp: 'jmv 8/24/2010 12:38'!
displayPatchFrom: srcString to: dstString tryWords: aBoolean prettyPrintedIn: aClass
	| formattedSrcString formattedDstString |
	formattedSrcString _ aClass
		ifNil: [ srcString ]
		ifNotNil: [
			[
			aClass compilerClass new
				format: srcString
				in: aClass
				notifying: nil ]
				on: Error
				do: [ :ex |
					srcString ]].
	formattedDstString _ aClass
		ifNil: [ dstString ]
		ifNotNil: [
			[
			aClass compilerClass new
				format: dstString
				in: aClass
				notifying: nil ]
				on: Error
				do: [ :ex |
					dstString ]].
	^ self
		displayPatchFrom: formattedSrcString
		to: formattedDstString
		tryWords: aBoolean.! !

!DifferenceFinder class methodsFor: 'compatibility' stamp: 'jmv 8/24/2010 12:50'!
wordsDisplayPatchFrom: srcString to: dstString
	| finder answer src1 dst1 changedCount |
	finder _ self base: srcString case: dstString.
	finder compareLines; compute.
	answer _ '' asText.
	src1 _ '' writeStream.
	dst1 _ '' writeStream.
	changedCount _ 0.
	finder differences sort first do: [:item :condition |
		condition caseOf: {
			[ #unchanged ] -> [
				changedCount > 0 ifTrue: [
					"If the sequence of changed lines is large, comparing words gets too slow and less useful"
					changedCount > 30 ifTrue: [
						^nil ].
					"Compare the just ended sequence of changed lines"
					finder base: src1 contents case: dst1 contents.
					finder compareWords; compute.
					answer _ answer append:  finder differences anyOne asText.
					src1 resetToStart.
					dst1 resetToStart.
					changedCount _ 0.
				].
				"This line hasn't changed. Just add it to the result in plain text."
				answer append: item ].
			[ #removed ] -> [
				"A removed line belongs in the source"
				src1 nextPutAll: item.
				changedCount _ changedCount + 1 ].
			[ #inserted ] -> [
				"An added line belongs in the destination"
				dst1 nextPutAll: item.
				changedCount _ changedCount + 1  ].
			}.
		].
	"If the sequence of changed lines is large, comparing words gets too slow and less useful"
	changedCount > 30 ifTrue: [
		^nil ].
	finder base: src1 contents case: dst1 contents.
	finder compareWords; compute.
	answer append:  finder differences anyOne asText.

	^answer! !

