--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/FileVersionDiffBrowser.st Mon Jul 08 01:37:03 2019 +0200
@@ -0,0 +1,1701 @@
+"
+ COPYRIGHT (c) 2019 by eXept Software AG
+ All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
+"
+"{ Package: 'stx:libtool2' }"
+
+"{ NameSpace: Smalltalk }"
+
+ApplicationModel subclass:#FileVersionDiffBrowser
+ instanceVariableNames:'diffTextView diffTextLabelA diffTextLabelB versionAHolder
+ versionBHolder infoHolder isMultipleVersionBrowser
+ versionInfoList versionList versionEntriesList
+ selectedVersionHolder symbolicVersionList symbolicVersionNameList
+ selectedSymbolicVersionHolder selectedSymbolicVersionIndexHolder
+ symbolicToVersionMapping selectedVersionIndexHolder
+ isMultipleFilesVersionBrowser fileListHolder
+ selectedFileIndexHolder fileHolder diffTextHolder
+ versionAIfSingleFileDiff versionBIfSingleFileDiff
+ fileIfSingleFileDiff'
+ classVariableNames:''
+ poolDictionaries:''
+ category:'Interface-Tools-File'
+!
+
+!FileVersionDiffBrowser class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 2019 by eXept Software AG
+ All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice. This software may not
+ be provided or otherwise made available to, or used by, any
+ other person. No title to or ownership of the software is
+ hereby transferred.
+"
+!
+
+documentation
+"
+ A quickly hacked up browser to show differences between file versions,
+ allowing easy comparison; will also eventually add capabilities
+ to checkIn / load files into / from the repository.
+
+ [usages:]
+ FileVersionDiffBrowser openOnAllVersionsOfFile:'Make.proto'.
+ FileVersionDiffBrowser openOnAllFilesChangedSince:(Date today - 7 days) in:('../../libbasic' asFilename).
+
+ [see also:]
+
+ [instance variables:]
+
+ [class variables:]
+"
+! !
+
+!FileVersionDiffBrowser class methodsFor:'interface specs'!
+
+windowSpec
+ "This resource specification was automatically generated
+ by the UIPainter of ST/X."
+
+ "Do not manually edit this!! If it is corrupted,
+ the UIPainter may not be able to read the specification."
+
+ "
+ UIPainter new openOnClass:FileVersionDiffBrowser andSelector:#windowSpec
+ FileVersionDiffBrowser new openInterface:#windowSpec
+ FileVersionDiffBrowser open
+ "
+
+ <resource: #canvas>
+
+ ^
+ #(FullSpec
+ name: windowSpec
+ uuid: '34d3baee-a108-11e9-a652-b8f6b1108e05'
+ window:
+ (WindowSpec
+ label: 'Version DiffBrowser'
+ name: 'Version DiffBrowser'
+ uuid: '90e45e00-7175-11e9-a23a-b8f6b1108e05'
+ min: (Point 10 10)
+ bounds: (Rectangle 0 0 865 504)
+ menu: mainMenu
+ )
+ component:
+ (SpecCollection
+ collection: (
+ (VariableVerticalPanelSpec
+ name: 'VariableVerticalPanel1'
+ layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 -25 1.0)
+ uuid: '90e460c6-7175-11e9-a23a-b8f6b1108e05'
+ component:
+ (SpecCollection
+ collection: (
+ (ViewSpec
+ name: 'DiffOrSingleMethodCodeBox'
+ uuid: '90e471a6-7175-11e9-a23a-b8f6b1108e05'
+ component:
+ (SpecCollection
+ collection: (
+ (ViewSpec
+ name: 'diffTextViewBox'
+ layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+ uuid: '90e47264-7175-11e9-a23a-b8f6b1108e05'
+ component:
+ (SpecCollection
+ collection: (
+ (LabelSpec
+ label: 'A'
+ name: 'DiffTextLabelA'
+ layout: (LayoutFrame 0 0 0 0 0 0.5 20 0)
+ uuid: '90e47318-7175-11e9-a23a-b8f6b1108e05'
+ translateLabel: true
+ labelChannel: diffTextLabelA
+ )
+ (LabelSpec
+ label: 'B'
+ name: 'DiffTextLabelB'
+ layout: (LayoutFrame 0 0.5 0 0 0 1 20 0)
+ uuid: '90e47412-7175-11e9-a23a-b8f6b1108e05'
+ translateLabel: true
+ labelChannel: diffTextLabelB
+ )
+ (ArbitraryComponentSpec
+ name: 'diffTextView'
+ layout: (LayoutFrame 0 0.0 20 0.0 0 1.0 0 1.0)
+ uuid: '90e47502-7175-11e9-a23a-b8f6b1108e05'
+ hasBorder: false
+ component: diffTextView
+ )
+ )
+
+ )
+ )
+ )
+
+ )
+ )
+ )
+
+ )
+ handles: (Any 1.0)
+ )
+ (LabelSpec
+ name: 'InfoLabel'
+ layout: (LayoutFrame 0 0 -25 1 0 1 0 1)
+ uuid: '90e47868-7175-11e9-a23a-b8f6b1108e05'
+ level: -1
+ translateLabel: true
+ labelChannel: infoHolder
+ adjust: left
+ )
+ )
+
+ )
+ )
+!
+
+windowSpecForMultipleFiles
+ "This resource specification was automatically generated
+ by the UIPainter of ST/X."
+
+ "Do not manually edit this!! If it is corrupted,
+ the UIPainter may not be able to read the specification."
+
+ "
+ UIPainter new openOnClass:FileVersionDiffBrowser andSelector:#windowSpecForMultipleFiles
+ FileVersionDiffBrowser new openInterface:#windowSpecForMultipleFiles
+ "
+
+ <resource: #canvas>
+
+ ^
+ #(FullSpec
+ name: windowSpecForMultipleFiles
+ uuid: '3c5c60f4-a108-11e9-a652-b8f6b1108e05'
+ window:
+ (WindowSpec
+ label: 'Version DiffBrowser'
+ name: 'Version DiffBrowser'
+ uuid: '2b3f2546-d4fd-11e7-af82-c42c033b4871'
+ min: (Point 10 10)
+ bounds: (Rectangle 0 0 865 504)
+ menu: mainMenu
+ )
+ component:
+ (SpecCollection
+ collection: (
+ (VariableVerticalPanelSpec
+ name: 'VariableVerticalPanel1'
+ layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 -25 1.0)
+ uuid: '2b3f297e-d4fd-11e7-af82-c42c033b4871'
+ component:
+ (SpecCollection
+ collection: (
+ (VariableHorizontalPanelSpec
+ name: 'FileAndVersionAndTagPanel'
+ uuid: '17c6805c-7184-11e9-a23a-b8f6b1108e05'
+ component:
+ (SpecCollection
+ collection: (
+ (SequenceViewSpec
+ name: 'List2'
+ uuid: '2b3f2d20-d4fd-11e7-af82-c42c033b4871'
+ model: selectedFileIndexHolder
+ menu: fileListMenu
+ hasHorizontalScrollBar: true
+ hasVerticalScrollBar: true
+ useIndex: true
+ sequenceList: fileNameListHolder
+ )
+ (VariableHorizontalPanelSpec
+ name: 'VersionAndTagPanel'
+ uuid: '2b3f2c08-d4fd-11e7-af82-c42c033b4871'
+ component:
+ (SpecCollection
+ collection: (
+ (SequenceViewSpec
+ name: 'VersionList'
+ uuid: '2b3f2d20-d4fd-11e7-af82-c42c033b4871'
+ model: selectedVersionIndexHolder
+ menu: versionsMenu
+ hasHorizontalScrollBar: true
+ hasVerticalScrollBar: true
+ useIndex: true
+ sequenceList: versionEntriesList
+ )
+ (SequenceViewSpec
+ name: 'List1'
+ uuid: '2b3f3086-d4fd-11e7-af82-c42c033b4871'
+ model: selectedSymbolicVersionIndexHolder
+ menu: symbolicVersionsMenu
+ hasHorizontalScrollBar: true
+ hasVerticalScrollBar: true
+ useIndex: true
+ sequenceList: symbolicVersionNameList
+ )
+ )
+
+ )
+ handles: (Any 0.5 1.0)
+ )
+ )
+
+ )
+ handles: (Any 0.5 1.0)
+ )
+ (ViewSpec
+ name: 'DiffBox'
+ uuid: '2b3f408a-d4fd-11e7-af82-c42c033b4871'
+ component:
+ (SpecCollection
+ collection: (
+ (ViewSpec
+ name: 'diffTextViewBox'
+ layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+ uuid: '2b3f415c-d4fd-11e7-af82-c42c033b4871'
+ component:
+ (SpecCollection
+ collection: (
+ (LabelSpec
+ label: 'A'
+ name: 'DiffTextLabelA'
+ layout: (LayoutFrame 0 0 0 0 0 0.5 20 0)
+ uuid: '2b3f426a-d4fd-11e7-af82-c42c033b4871'
+ translateLabel: true
+ labelChannel: diffTextLabelA
+ )
+ (LabelSpec
+ label: 'B'
+ name: 'DiffTextLabelB'
+ layout: (LayoutFrame 0 0.5 0 0 0 1 20 0)
+ uuid: '2b3f43d2-d4fd-11e7-af82-c42c033b4871'
+ translateLabel: true
+ labelChannel: diffTextLabelB
+ )
+ (ArbitraryComponentSpec
+ name: 'diffTextView'
+ layout: (LayoutFrame 0 0.0 20 0.0 0 1.0 0 1.0)
+ uuid: '2b3f4508-d4fd-11e7-af82-c42c033b4871'
+ hasBorder: false
+ component: diffTextView
+ )
+ )
+
+ )
+ )
+ )
+
+ )
+ )
+ )
+
+ )
+ handles: (Any 0.5 1.0)
+ )
+ (LabelSpec
+ name: 'InfoLabel'
+ layout: (LayoutFrame 0 0 -25 1 0 1 0 1)
+ uuid: '2b3f4a44-d4fd-11e7-af82-c42c033b4871'
+ level: -1
+ translateLabel: true
+ labelChannel: infoHolder
+ adjust: left
+ )
+ )
+
+ )
+ )
+!
+
+windowSpecForMultipleVersions
+ "This resource specification was automatically generated
+ by the UIPainter of ST/X."
+
+ "Do not manually edit this!! If it is corrupted,
+ the UIPainter may not be able to read the specification."
+
+ "
+ UIPainter new openOnClass:FileVersionDiffBrowser andSelector:#windowSpecForMultipleVersions
+ FileVersionDiffBrowser new openInterface:#windowSpecForMultipleVersions
+ "
+
+ <resource: #canvas>
+
+ ^
+ #(FullSpec
+ name: windowSpecForMultipleVersions
+ uuid: '441c0448-a108-11e9-a652-b8f6b1108e05'
+ window:
+ (WindowSpec
+ label: 'Version DiffBrowser'
+ name: 'Version DiffBrowser'
+ uuid: '2b3f2546-d4fd-11e7-af82-c42c033b4871'
+ min: (Point 10 10)
+ bounds: (Rectangle 0 0 865 504)
+ menu: mainMenu
+ )
+ component:
+ (SpecCollection
+ collection: (
+ (VariableVerticalPanelSpec
+ name: 'VariableVerticalPanel1'
+ layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 -25 1.0)
+ uuid: '2b3f297e-d4fd-11e7-af82-c42c033b4871'
+ component:
+ (SpecCollection
+ collection: (
+ (VariableHorizontalPanelSpec
+ name: 'VersionAndTagBox'
+ uuid: '2b3f2c08-d4fd-11e7-af82-c42c033b4871'
+ component:
+ (SpecCollection
+ collection: (
+ (SequenceViewSpec
+ name: 'VersionList'
+ uuid: '2b3f2d20-d4fd-11e7-af82-c42c033b4871'
+ model: selectedVersionIndexHolder
+ menu: versionsMenu
+ hasHorizontalScrollBar: true
+ hasVerticalScrollBar: true
+ useIndex: true
+ sequenceList: versionEntriesList
+ )
+ (SequenceViewSpec
+ name: 'List1'
+ uuid: '2b3f3086-d4fd-11e7-af82-c42c033b4871'
+ model: selectedSymbolicVersionIndexHolder
+ menu: symbolicVersionsMenu
+ hasHorizontalScrollBar: true
+ hasVerticalScrollBar: true
+ useIndex: true
+ sequenceList: symbolicVersionNameList
+ )
+ )
+
+ )
+ handles: (Any 0.5 1.0)
+ )
+ (ViewSpec
+ name: 'DiffBox'
+ uuid: '2b3f408a-d4fd-11e7-af82-c42c033b4871'
+ component:
+ (SpecCollection
+ collection: (
+ (ViewSpec
+ name: 'diffTextViewBox'
+ layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+ uuid: '2b3f415c-d4fd-11e7-af82-c42c033b4871'
+ component:
+ (SpecCollection
+ collection: (
+ (LabelSpec
+ label: 'A'
+ name: 'DiffTextLabelA'
+ layout: (LayoutFrame 0 0 0 0 0 0.5 20 0)
+ uuid: '2b3f426a-d4fd-11e7-af82-c42c033b4871'
+ translateLabel: true
+ labelChannel: diffTextLabelA
+ )
+ (LabelSpec
+ label: 'B'
+ name: 'DiffTextLabelB'
+ layout: (LayoutFrame 0 0.5 0 0 0 1 20 0)
+ uuid: '2b3f43d2-d4fd-11e7-af82-c42c033b4871'
+ translateLabel: true
+ labelChannel: diffTextLabelB
+ )
+ (ArbitraryComponentSpec
+ name: 'diffTextView'
+ layout: (LayoutFrame 0 0.0 20 0.0 0 1.0 0 1.0)
+ uuid: '2b3f4508-d4fd-11e7-af82-c42c033b4871'
+ hasBorder: false
+ component: diffTextView
+ )
+ )
+
+ )
+ )
+ )
+
+ )
+ )
+ )
+
+ )
+ handles: (Any 0.5 1.0)
+ )
+ (LabelSpec
+ name: 'InfoLabel'
+ layout: (LayoutFrame 0 0 -25 1 0 1 0 1)
+ uuid: '2b3f4a44-d4fd-11e7-af82-c42c033b4871'
+ level: -1
+ translateLabel: true
+ labelChannel: infoHolder
+ adjust: left
+ )
+ )
+
+ )
+ )
+! !
+
+!FileVersionDiffBrowser class methodsFor:'menu specs'!
+
+mainMenu
+ "This resource specification was automatically generated
+ by the MenuEditor of ST/X."
+
+ "Do not manually edit this!! If it is corrupted,
+ the MenuEditor may not be able to read the specification."
+
+
+ "
+ MenuEditor new openOnClass:FileVersionDiffBrowser andSelector:#mainMenu
+ (Menu new fromLiteralArrayEncoding:(FileVersionDiffBrowser mainMenu)) startUp
+ "
+
+ <resource: #menu>
+
+ ^
+ #(Menu
+ (
+ (MenuItem
+ label: 'File'
+ submenu:
+ (Menu
+ (
+ (MenuItem
+ label: 'Create PatchFile...'
+ itemValue: createPatchFile
+ )
+ (MenuItem
+ label: '-'
+ )
+ (MenuItem
+ label: 'Exit'
+ itemValue: closeRequest
+ )
+ )
+ nil
+ nil
+ )
+ )
+ (MenuItem
+ label: 'View'
+ submenuChannel: viewMenu
+ )
+ (MenuItem
+ label: 'MENU_Help'
+ startGroup: conditionalRight
+ submenu:
+ (Menu
+ (
+ (MenuItem
+ label: 'Documentation'
+ itemValue: openDocumentation
+ )
+ (MenuItem
+ label: '-'
+ )
+ (MenuItem
+ label: 'About this Application...'
+ itemValue: openAboutThisApplication
+ )
+ )
+ nil
+ nil
+ )
+ )
+ )
+ nil
+ nil
+ )
+!
+
+versionsMenu
+ "This resource specification was automatically generated
+ by the MenuEditor of ST/X."
+
+ "Do not manually edit this!! If it is corrupted,
+ the MenuEditor may not be able to read the specification."
+
+
+ "
+ MenuEditor new openOnClass:VersionDiffBrowser andSelector:#mainMenu
+ (Menu new fromLiteralArrayEncoding:(VersionDiffBrowser mainMenu)) startUp
+ "
+
+ <resource: #menu>
+
+ ^
+ #(Menu
+ (
+ (MenuItem
+ label: 'Compare against Previous (Older) Version'
+ nameKey: CompareAgainstPreviousVersion
+ itemValue: versionMenuCompareAgainstPreviousVersion
+ enabled: hasPreviousVersionInVersionList
+ )
+ (MenuItem
+ label: 'Compare against Next (Younger) Version'
+ nameKey: CompareAgainstNextVersion
+ itemValue: versionMenuCompareAgainstNextVersion
+ enabled: hasNextVersionInVersionList
+ )
+
+ )
+ nil
+ nil
+ )
+
+ "Created: / 05-02-2017 / 11:11:30 / cg"
+ "Modified: / 06-02-2017 / 09:27:22 / cg"
+!
+
+viewMenu
+ "This resource specification was automatically generated
+ by the MenuEditor of ST/X."
+
+ "Do not manually edit this!! If it is corrupted,
+ the MenuEditor may not be able to read the specification."
+
+
+ "
+ MenuEditor new openOnClass:FileVersionDiffBrowser andSelector:#viewMenu
+ (Menu new fromLiteralArrayEncoding:(FileVersionDiffBrowser viewMenu)) startUp
+ "
+
+ <resource: #menu>
+
+ ^
+ #(Menu
+ (
+ (MenuItem
+ label: 'Show Log Messages'
+ itemValue: showLogMessages
+ )
+ )
+ nil
+ nil
+ )
+! !
+
+!FileVersionDiffBrowser class methodsFor:'startup'!
+
+openOnAllFilesChangedSince:aDateOrTimestamp in:aSetOfFilesOrADirectoryFilename
+ "create a FileVersionDiffBrowser instance and set the list of files.
+ When a file is selected, the version list is extracted,
+ and the diff list is generated from the file's current version against
+ the selected version in the top selection list"
+
+ |setOfFiles theBrowser filesChangedSince sinceTimestamp|
+
+ sinceTimestamp := aDateOrTimestamp asTimestamp.
+
+ setOfFiles := aSetOfFilesOrADirectoryFilename.
+ setOfFiles isFilename ifTrue:[
+ setOfFiles := setOfFiles directoryContentsAsFilenames.
+ ].
+
+ filesChangedSince := setOfFiles
+ select:[:fn | fn modificationTime > sinceTimestamp].
+ filesChangedSince sort:[:a :b | a name < b name].
+
+ theBrowser := self new.
+ theBrowser allButOpenInterface:#windowSpecForMultipleFiles.
+ theBrowser beMultipleFilesVersionBrowser.
+ theBrowser fileList:filesChangedSince.
+
+ "/ theBrowser classHolder:(ValueHolder with:aClass).
+ "/ theBrowser setupForClass:aClass againstVersion:nil.
+ theBrowser window label:(self resources string:'Versions of %1 files' with:setOfFiles size).
+ theBrowser openWindow.
+ ^ theBrowser.
+
+ "
+ FileVersionDiffBrowser
+ openOnAllFilesChangedSince:(Date today - 7 days)
+ in:('../../libbasic' asFilename files).
+ "
+
+ "Created: / 07-07-2019 / 18:58:01 / Claus Gittinger"
+ "Modified: / 08-07-2019 / 01:36:01 / Claus Gittinger"
+!
+
+openOnAllVersionsOfFile:aFilename
+ "create a VersionDiffBrowser instance and set the file.
+ The diff is generated from aFilename's current version against
+ the selected version in the top selection list"
+
+ |theBrowser|
+
+ theBrowser := self new.
+ theBrowser allButOpenInterface:#windowSpecForMultipleVersions.
+ theBrowser beMultipleVersionBrowser.
+ theBrowser fileHolder value:aFilename.
+ theBrowser setupForAllVersionsOfFile:aFilename.
+ theBrowser window label:(self resources string:'Versions of %1' with:aFilename baseName).
+ theBrowser openWindow.
+ ^ theBrowser.
+
+ "
+ self openOnAllVersionsOfFile:'Make.proto' asFilename
+ self openOnAllVersionsOfFile:'../../libbasic/Array.st' asFilename
+ "
+
+ "Created: / 07-07-2019 / 19:26:28 / Claus Gittinger"
+ "Modified: / 07-07-2019 / 22:40:38 / Claus Gittinger"
+ "Modified (comment): / 08-07-2019 / 01:27:03 / Claus Gittinger"
+!
+
+openOnAllVersionsOfFiles:aSetOfFilenames
+ "create a VersionDiffBrowser instance and set the list of files.
+ When a file is selected, the version list is extracted,
+ and the diff set is generated from the file's current version against
+ the selected version in the top selection list"
+
+ |theBrowser|
+
+ theBrowser := self new.
+ theBrowser allButOpenInterface:#windowSpecForMultipleFiles.
+ theBrowser beMultipleFilesVersionBrowser.
+ theBrowser beMultipleVersionBrowser.
+ theBrowser fileList:(aSetOfFilenames collect:#asFilename).
+ theBrowser window label:(self resources string:'Versions of %1 files' with:aSetOfFilenames size).
+ theBrowser openWindow.
+ ^ theBrowser.
+
+ "
+ self openOnAllVersionsOfFiles:#('Make.proto' 'Make.spec')
+ "
+
+ "Created: / 07-07-2019 / 19:29:38 / Claus Gittinger"
+ "Modified: / 08-07-2019 / 00:30:31 / Claus Gittinger"
+!
+
+openOnFile:aFilename againstVersion:aVersionA
+ "create a VersionDiffBrowser instance and set the diffs of the
+ browser. The diffs are generated from aFilename's current against some version
+ via the source code manager."
+
+ |theBrowser fn|
+
+ fn := aFilename asFilename.
+ theBrowser := self new.
+ theBrowser allButOpen.
+ theBrowser setupForFile:fn againstVersion:aVersionA.
+ theBrowser window label:(self resources string:'Diffs of %1 %2 against current' with:fn baseName with:aVersionA).
+ theBrowser openWindow.
+ ^ theBrowser.
+
+ "
+ self openOnFile:'Make.proto' againstVersion:'1.2'
+ self openOnFile:'Make.proto' againstVersion:#newest - against the newest repository version
+ "
+
+ "Created: / 07-07-2019 / 19:31:13 / Claus Gittinger"
+ "Modified: / 08-07-2019 / 00:42:22 / Claus Gittinger"
+!
+
+openOnFile:file1 andFile:file2
+ |fn1 fn2|
+
+ fn1 := file1 asFilename.
+ fn2 := file2 asFilename.
+ ^ self
+ openOnFile:fn1 labelA:fn1 baseName andFile:fn2 labelB:fn2 baseName
+ title:(self resources string:'%1 vs. %2'
+ with:fn1 baseName with:fn2 baseName)
+ ifSame:nil
+
+ "
+ FileVersionDiffBrowser
+ openOnFile:'../../libbasic/FloatArray.st'
+ andFile:'../../libbasic/DoubleArray.st'
+ "
+
+ "Created: / 08-07-2019 / 00:52:18 / Claus Gittinger"
+!
+
+openOnFile:fileA labelA:aLabelA andFile:fileB labelB:aLabelB title:title
+ "create a VersionDiffBrowser instance and set the difflist of the
+ browser. The diffs are generated from two files."
+
+ ^ self
+ openOnFile:fileA labelA:aLabelA
+ andFile:fileB labelB:aLabelB
+ title:title ifSame:nil
+
+ "
+ self
+ openOnFile:'../../libbasic/FloatArray.st' labelA:'FloatArray'
+ andFile:'../../libbasic/DoubleArray.st' labelB:'DoubleArray'
+ title:'FloatArray vs. DoubleArray'
+ "
+
+ "Created: / 07-07-2019 / 19:32:07 / Claus Gittinger"
+ "Modified (comment): / 08-07-2019 / 00:37:50 / Claus Gittinger"
+!
+
+openOnFile:fileA labelA:aLabelA andFile:fileB labelB:aLabelB title:title ifSame:sameAction
+ "create a VersionDiffBrowser instance and set the class change set of the
+ browser. The class diff set is generated from two classes."
+
+ |theBrowser fn1 fn2|
+
+ fn1 := fileA asFilename.
+ fn2 := fileB asFilename.
+
+ theBrowser := self new.
+ theBrowser allButOpen.
+ theBrowser setupForFile:fn1 labelA:aLabelA andFile:fn2 labelB:aLabelB.
+ theBrowser window label:title.
+ theBrowser openWindow.
+ ^ theBrowser.
+
+ "
+ FileVersionDiffBrowser
+ openOnFile:'../../libbasic/FloatArray.st' labelA:'FloatArray'
+ andFile:'../../libbasic/DoubleArray.st' labelB:'DoubleArray'
+ title:'Some diffs' ifSame:nil
+ "
+
+ "Created: / 07-07-2019 / 20:05:16 / Claus Gittinger"
+ "Modified (comment): / 08-07-2019 / 00:51:29 / Claus Gittinger"
+!
+
+openOnFile:aFilename versionA:versionA versionB:versionB
+ "create a VersionDiffBrowser instance and set the class change set of the
+ browser. The class diff set is generated from two versions of aClass via
+ the source code manager."
+
+ |theBrowser|
+
+ theBrowser := self new.
+ theBrowser allButOpen.
+ theBrowser setupForFile:aFilename versionA:versionA versionB:versionB.
+ theBrowser window label:(self resources
+ string:'%1 Versions %2 vs. %3'
+ with:aFilename baseName with:versionA with:versionB).
+ theBrowser openWindow.
+ ^ theBrowser.
+
+ "
+ self openOnFile:'Make.proto' versionA:'1.1' versionB:'1.2'
+ "
+
+ "Created: / 07-07-2019 / 20:06:15 / Claus Gittinger"
+! !
+
+!FileVersionDiffBrowser methodsFor:'accessing'!
+
+beMultipleFilesVersionBrowser
+ isMultipleFilesVersionBrowser := true
+
+ "Created: / 07-07-2019 / 18:58:49 / Claus Gittinger"
+!
+
+beMultipleVersionBrowser
+ isMultipleVersionBrowser := true
+!
+
+isMultipleFilesVersionBrowser
+ ^ isMultipleFilesVersionBrowser
+
+ "Created: / 07-07-2019 / 19:53:15 / Claus Gittinger"
+!
+
+isMultipleVersionBrowser
+ ^ isMultipleVersionBrowser
+
+ "Modified: / 08-05-2019 / 10:59:40 / Claus Gittinger"
+! !
+
+!FileVersionDiffBrowser methodsFor:'aspects'!
+
+diffTextHolder
+ diffTextHolder isNil ifTrue:[
+ diffTextHolder := '' asValue
+ ].
+ ^ diffTextHolder
+
+ "Created: / 07-07-2019 / 20:04:23 / Claus Gittinger"
+!
+
+diffTextLabelA
+ "aspect for the label for version A"
+
+ ^ diffTextLabelA.
+
+ "Modified: / 08-05-2019 / 11:03:23 / Claus Gittinger"
+!
+
+diffTextLabelB
+ "aspect for the label for version B"
+
+ ^ diffTextLabelB.
+
+ "Modified: / 08-05-2019 / 11:03:32 / Claus Gittinger"
+!
+
+diffTextView
+ "
+ return the component for the diff text view.
+
+ <return: HVScrollableView>
+ "
+ |v|
+
+ diffTextView isNil ifTrue:[
+ v := DiffCodeView new.
+ v textViewClass:CodeView.
+ v initialize.
+ diffTextView := HVScrollableView
+ forView:v
+ miniScrollerH:true miniScrollerV:false.
+ diffTextView addNextPreviousButtons.
+ ].
+ ^ diffTextView
+
+ "Modified: / 06-10-2006 / 14:30:42 / cg"
+!
+
+fileHolder
+ fileHolder isNil ifTrue:[
+ fileHolder := nil asValue
+ ].
+ ^ fileHolder
+
+ "Created: / 07-07-2019 / 20:10:47 / Claus Gittinger"
+!
+
+fileList:aList
+ self fileListHolder contents:aList
+
+ "Created: / 08-07-2019 / 00:28:32 / Claus Gittinger"
+!
+
+fileListHolder
+ "aspect for the 'list of files' list.
+ <return: List>"
+
+ fileListHolder isNil ifTrue:[
+ fileListHolder := List new
+ ].
+ ^ fileListHolder
+
+ "Created: / 07-07-2019 / 19:46:44 / Claus Gittinger"
+!
+
+fileNameListHolder
+ "aspect for the 'list of file' list.
+ <return: List>"
+
+ ^ BlockValue
+ with:[:l | l collect:#baseName]
+ argument:(self fileListHolder)
+
+ "Created: / 07-07-2019 / 19:47:13 / Claus Gittinger"
+!
+
+infoHolder
+ ^ infoHolder.
+
+ "Modified: / 08-05-2019 / 11:05:10 / Claus Gittinger"
+!
+
+selectedFileIndexHolder
+ selectedFileIndexHolder isNil ifTrue:[
+ selectedFileIndexHolder := nil asValue.
+ selectedFileIndexHolder onChangeSend:#selectedFileIndexHolderChanged to:self.
+ ].
+ ^ selectedFileIndexHolder
+
+ "Created: / 07-07-2019 / 19:00:13 / Claus Gittinger"
+!
+
+selectedSymbolicVersionHolder
+ ^ selectedSymbolicVersionHolder
+
+ "Modified: / 08-05-2019 / 11:08:42 / Claus Gittinger"
+!
+
+selectedSymbolicVersionIndexHolder
+ ^ selectedSymbolicVersionIndexHolder
+
+ "Created: / 28-05-2019 / 15:32:03 / Claus Gittinger"
+!
+
+selectedVersionHolder
+ ^ selectedVersionHolder
+
+ "Modified: / 08-05-2019 / 11:09:18 / Claus Gittinger"
+!
+
+selectedVersionIndex
+ ^ selectedVersionIndexHolder value ? 0
+
+ "Created: / 23-05-2018 / 11:35:50 / Claus Gittinger"
+ "Modified: / 08-05-2019 / 11:09:50 / Claus Gittinger"
+!
+
+selectedVersionIndexHolder
+ ^ selectedVersionIndexHolder
+
+ "Created: / 29-11-2017 / 13:02:49 / cg"
+ "Modified: / 08-05-2019 / 11:09:46 / Claus Gittinger"
+!
+
+symbolicVersionList
+ ^ symbolicVersionList
+
+ "Modified: / 08-05-2019 / 11:10:23 / Claus Gittinger"
+!
+
+symbolicVersionNameList
+ ^ symbolicVersionNameList
+
+ "Created: / 28-05-2019 / 15:42:12 / Claus Gittinger"
+!
+
+versionEntriesList
+ ^ versionEntriesList
+
+ "Created: / 29-11-2017 / 13:06:14 / cg"
+ "Modified: / 08-05-2019 / 11:10:38 / Claus Gittinger"
+!
+
+versionList
+ ^ versionList
+
+ "Modified: / 08-05-2019 / 11:10:53 / Claus Gittinger"
+! !
+
+!FileVersionDiffBrowser methodsFor:'aspects-menu'!
+
+hasNextVersionInVersionList
+ "versions are sorted youngest first.
+ If the current selected one is the first, there is no next version"
+
+ ^ (self selectedVersionIndex) > 1.
+
+ "Modified: / 23-05-2018 / 11:36:33 / Claus Gittinger"
+!
+
+hasPreviousVersionInVersionList
+ "versions are sorted youngest first.
+ If the current selected one is the last, there is no previous version"
+
+ ^ (self selectedVersionIndex) < versionList value size.
+
+ "Modified: / 23-05-2018 / 11:36:38 / Claus Gittinger"
+!
+
+versionsMenu
+ ^ [
+ |m item nextVersion prevVersion|
+
+ m := self class versionsMenu.
+ m := m decodeAsLiteralArray.
+ m findGuiResourcesIn:self.
+
+ self hasNextVersionInVersionList ifTrue:[
+ nextVersion := self versionList at:(self selectedVersionIndex - 1).
+ item := m atNameKey:#CompareAgainstNextVersion.
+ item label:(resources string:(item label,' (%1)') with:nextVersion).
+ ].
+ self hasPreviousVersionInVersionList ifTrue:[
+ prevVersion := self versionList at:(self selectedVersionIndex + 1).
+ item := m atNameKey:#CompareAgainstPreviousVersion.
+ item label:(resources string:(item label,'(%1)') with:prevVersion).
+ ].
+ m
+ ]
+
+ "Modified: / 23-05-2018 / 11:36:18 / Claus Gittinger"
+! !
+
+!FileVersionDiffBrowser methodsFor:'change & update'!
+
+selectVersion:version
+ |idx numShownBefore numShownAfter|
+
+ idx := versionList indexOf:version.
+ "/ if not found, get more version infos
+ [idx == 0] whileTrue:[
+ numShownBefore := versionList size.
+ self updateVersionList.
+ numShownAfter := versionList size.
+ idx := versionList indexOf:version.
+ idx == 0 ifTrue:[
+ numShownBefore == numShownAfter ifTrue:[
+ ^ self
+ ].
+ ].
+ ].
+ self selectedVersionIndexHolder value:idx.
+
+ "Created: / 28-05-2019 / 14:58:37 / Claus Gittinger"
+!
+
+selectedFileIndexHolderChanged
+ |fn|
+
+ fn := self fileListHolder value at:(self selectedFileIndexHolder value).
+
+ self fileHolder value:fn.
+ (self isMultipleVersionBrowser or:[self isMultipleFilesVersionBrowser]) ifTrue:[
+ self withWaitCursorDo:[
+ self updateVersionList.
+ ]
+ ]
+
+ "Created: / 07-07-2019 / 19:51:17 / Claus Gittinger"
+ "Modified: / 08-07-2019 / 00:30:51 / Claus Gittinger"
+!
+
+selectedSymbolicVersionHolderChanged
+ |symbolicTag version|
+
+ symbolicTag := self selectedSymbolicVersionHolder value.
+ version := symbolicToVersionMapping at:symbolicTag ifAbsent:nil.
+ version isNil ifTrue:[
+ symbolicTag = '-' ifFalse:[
+ Dialog warn:'No version has this tag ("%1")' with:symbolicTag.
+ ].
+ ^ self.
+ ].
+ self selectVersion:version
+
+ "Modified: / 28-05-2019 / 14:57:56 / Claus Gittinger"
+!
+
+selectedSymbolicVersionIndexHolderChanged
+ self selectedSymbolicVersionHolder value:(symbolicVersionList at:self selectedSymbolicVersionIndexHolder value)
+
+ "Created: / 28-05-2019 / 15:32:47 / Claus Gittinger"
+!
+
+selectedVersionHolderChanged
+
+ self withWaitCursorDo:[
+ |idx|
+
+ "/ possibly expand a contracted list
+ selectedVersionHolder value = '...' ifTrue:[
+ idx := self versionList size.
+ self updateVersionList.
+ selectedVersionHolder setValue:(self versionList at:idx).
+ ].
+
+ "/ update the view
+ self
+ setupForFile:fileHolder value
+ againstVersion:(selectedVersionHolder value).
+
+ "/ self showVersionInfoIfNothingSelected
+ ]
+
+ "Modified: / 06-02-2017 / 02:32:24 / cg"
+ "Modified: / 08-07-2019 / 00:05:30 / Claus Gittinger"
+!
+
+selectedVersionIndexHolderChanged
+ self selectedVersionHolder value:(versionList at:self selectedVersionIndexHolder value)
+
+ "Created: / 29-11-2017 / 13:04:12 / cg"
+!
+
+showActivity:someMessage
+ "some activityNotification shalt be communicated to the user."
+
+ infoHolder value:someMessage.
+
+ "Created: / 28-05-2019 / 15:26:34 / Claus Gittinger"
+!
+
+update:something with:parameter from:changedObject
+ (changedObject == fileHolder
+ or:[changedObject == versionAHolder
+ or:[changedObject == versionBHolder]]) ifTrue:[
+ self setupForFile:(fileHolder value) versionA:(versionAHolder value) versionB:(versionBHolder value).
+ ^ self
+ ].
+ super update:something with:parameter from:changedObject
+
+ "Modified: / 17-07-2012 / 17:48:58 / cg"
+ "Modified: / 08-07-2019 / 00:09:19 / Claus Gittinger"
+!
+
+updateLists
+ "walk over the changeSet(s) and setup the 3 lists:
+ onlyInA, changed, onlyInB,
+ Optionally filter extensions, categoryChanges and versionMethods,
+ changes with same semantic (variable renames)
+ and changes which have been explicitly filtered by the user."
+
+ |listOnlyInA listOnlyInB listChanged
+ printStringGenerator "sortBlockForChangeLists" filteredList
+ numIgnoredExtensions numIgnoredVersionMethods
+ info needFilter entryIsForCommentOrFormatOnly
+ isIgnoredChange|
+
+"/ listOnlyInA := filteredList := self methodsOnlyInA.
+"/ listOnlyInA removeAll.
+"/ classChangeSet notNil ifTrue:[
+"/ "/ classChangeSet methodsOnlyInA sort:sortBlockForChangeLists.
+"/ filteredList := classChangeSet methodsOnlyInA reject:isIgnoredChange.
+"/ listOnlyInA addAll: (filteredList collect:printStringGenerator).
+"/ ].
+"/ methodsOnlyInAFiltered := filteredList.
+"/
+"/ listOnlyInB := filteredList := self methodsOnlyInB.
+"/ listOnlyInB removeAll.
+"/ classChangeSet notNil ifTrue:[
+"/ "/ classChangeSet methodsOnlyInB sort:sortBlockForChangeLists.
+"/ filteredList := classChangeSet methodsOnlyInB reject:isIgnoredChange.
+"/ listOnlyInB addAll: (filteredList collect:printStringGenerator).
+"/ ].
+"/ methodsOnlyInBFiltered := filteredList.
+
+"/ entryIsForCommentOrFormatOnly :=
+"/ [:entry |
+"/ |commentOnly changeA changeB mthdA mthdB|
+"/
+"/ commentOnly := false.
+"/
+"/ changeA := entry first.
+"/ changeB := entry second.
+"/ changeA isMethodChange ifTrue:[
+"/ changeA isMethodCodeChange ifTrue:[
+"/ RBCodeDuplicationRule notNil ifTrue:[
+"/ mthdA := RBMethod forMethodChange:changeA.
+"/ mthdB := RBMethod forMethodChange:changeB.
+"/ commentOnly := RBCodeDuplicationRule hasMethod:mthdA sameSemanticAs:mthdB.
+"/ ].
+"/ ] ifFalse:[
+"/ changeA isMethodCategoryChange ifTrue:[
+"/ commentOnly := true
+"/ ] ifFalse:[
+"/ self breakPoint:#cg
+"/ ].
+"/ ].
+"/ ] ifFalse:[
+"/ changeA isClassDefinitionChange ifTrue:[
+"/ changeA source = changeB source ifTrue:[
+"/ commentOnly := true
+"/ ] ifFalse:[
+"/ self breakPoint:#cg
+"/ ].
+"/ ] ifFalse:[
+"/ self breakPoint:#cg
+"/ ].
+"/ ].
+"/ commentOnly
+"/ ].
+
+"/ listChanged := filteredList := self methodsChanged.
+"/ listChanged removeAll.
+"/ classChangeSet notNil ifTrue:[
+"/ "/ classChangeSet methodsChanged sort:[:a :b | sortBlockForChangeLists value:a first value:b first].
+"/ filteredList := classChangeSet methodsChanged reject:[:entry | isIgnoredChange value:entry first].
+"/
+"/ (self hideDiffsWithCommentOrFormattingChangeOnly) ifTrue:[
+"/ filteredList := filteredList reject:entryIsForCommentOrFormatOnly.
+"/ listChanged addAll: (filteredList collect:[:entry| printStringGenerator value:(entry first)]).
+"/ ] ifFalse:[
+"/ filteredList do:[:entry|
+"/ |string|
+"/
+"/ string := printStringGenerator value:(entry first).
+"/ (entryIsForCommentOrFormatOnly value:entry) ifTrue:[
+"/ string := string withColor:Color grey.
+"/ ].
+"/ listChanged add:string
+"/ ].
+"/ ].
+"/ ].
+"/ methodsChangedFiltered := filteredList.
+
+"/ self boxAVisible value:(listOnlyInA notEmpty).
+"/ self boxBVisible value:(listOnlyInB notEmpty).
+
+"/ self boxMVisible value:(listChanged isEmpty
+"/ and: [(listOnlyInA notEmpty
+"/ or:[listOnlyInB notEmpty])]) not.
+
+ self information:info
+
+ "Modified (comment): / 06-02-2017 / 10:09:11 / cg"
+ "Modified (format): / 16-02-2017 / 11:11:49 / stefan"
+ "Modified: / 07-07-2019 / 19:08:03 / Claus Gittinger"
+!
+
+updateVersionList
+ "asks the classes source code manager for a list of revisions;
+ construct versionInfoList (containing the full info), versionList (containing version numbers only)
+ and tagList (containing symbolic names only).
+ This is only used when comparing multiple versions."
+
+ |fn sourceCodeManager numShown newNumShown numOverallRevisions
+ partialLog newestRev revisions revisionEntries symbolicNames
+ stableRevision releasedRevision tagList logMessages|
+
+ fn := fileHolder value.
+ fn isNil ifTrue:[
+ symbolicVersionList contents:#().
+ symbolicVersionNameList contents:#().
+ self versionList contents:#().
+ self versionEntriesList contents:#().
+ ^ self
+ ].
+
+ sourceCodeManager := CVSSourceCodeManager.
+
+ numShown := versionList size - 1.
+ newNumShown := (numShown + 50) max:30.
+
+ infoHolder value:'Getting version log...'.
+ partialLog := sourceCodeManager revisionLogOfFile:fn numberOfRevisions:newNumShown.
+
+ partialLog isNil ifTrue:[
+ self warn:'Could not find/access the container for ',fn name,' in the repository.
+This could be due to:
+ - invalid/wrong CVS-Root setting
+ - missing CVS access rights
+ (no access / not logged in)
+ - changed CVSRoot after compilation
+ (i.e. wrong CVS-path in classes version method)
+'.
+ ^ nil
+ ].
+
+ numOverallRevisions := partialLog at:#numberOfRevisions.
+ newestRev := partialLog at:#newestRevision.
+ revisions := partialLog at:#revisions.
+
+ "/ fetch the symbolic (tag) version list
+ symbolicNames := partialLog at:#symbolicNames ifAbsent:[].
+ symbolicNames notNil ifTrue:[
+ stableRevision := symbolicNames at:'stable' ifAbsent:[].
+ releasedRevision := symbolicNames at:'released' ifAbsent:[].
+
+ tagList := ((symbolicNames associations
+ sort:[:a :b | sourceCodeManager versionString:(a value) isLessThan:(b value)])
+ collect:[:assoc | assoc key]) reverse.
+"/ tagList := ((symbolicNames associations
+"/ sort:[:a :b | a key < b key])
+"/ collect:[:assoc | assoc key]) reverse.
+
+ tagList remove:'stable' ifAbsent:[].
+ stableRevision notNil ifTrue:[
+ tagList notEmpty ifTrue:[tagList addFirst:'-'].
+ tagList addFirst:'stable'.
+ ].
+ ].
+ logMessages := Dictionary new.
+
+ versionInfoList := revisions.
+
+"/ items := versionInfoList collect:[:each | |rev date who flag|
+"/ rev := each at:#revision.
+"/ logMessages at:rev put:(each at:#logMessage).
+"/ date := (each at:#date ifAbsent:nil) ? '?'.
+"/ who := (each at:#author ifAbsent:nil) ? '?'.
+"/ rev = stableRevision ifTrue:[
+"/ flag := ' Stable' allBold.
+"/ ] ifFalse:[rev = releasedRevision ifTrue:[
+"/ flag := ' Released' allBold.
+"/ ] ifFalse:[
+"/ flag := ' '
+"/ ]].
+"/ rev allBold , flag, ' [' , date , ' by ' , who , ']'
+"/ ].
+"/
+"/ revisions := revisions collect:[:eachItem | eachItem at:#revision].
+ revisions := OrderedCollection new.
+ revisionEntries := OrderedCollection new.
+ versionInfoList do:[:eachVersionInfo |
+ revisions add:eachVersionInfo revision.
+ revisionEntries add:(
+ (eachVersionInfo revision)
+ , ((' (by %2 at %3)'
+ bindWith:(eachVersionInfo revision)
+ with:(eachVersionInfo user)
+ with:(eachVersionInfo date)) withColor:Color grey)).
+ ].
+
+ revisions size < numOverallRevisions ifTrue:[
+ revisions add:'...'.
+ revisionEntries add:'...'.
+ ].
+
+ symbolicToVersionMapping := symbolicNames.
+
+ symbolicVersionList contents:tagList.
+
+ symbolicVersionNameList
+ contents:(
+ tagList
+ collect:[:eachSymbolic |
+ |versionsString|
+
+ eachSymbolic = '-' ifTrue:[
+ eachSymbolic.
+ ] ifFalse:[
+ versionsString := symbolicToVersionMapping at:eachSymbolic ifAbsent:'<<none>>'.
+ eachSymbolic,((' (',versionsString,')') withColor:Color grey)
+ ]
+ ]).
+ self versionList contents:revisions.
+ self versionEntriesList contents:revisionEntries.
+ infoHolder value:'Done.'.
+
+ "Modified: / 29-11-2017 / 13:06:21 / cg"
+ "Modified: / 07-07-2019 / 23:44:42 / Claus Gittinger"
+! !
+
+!FileVersionDiffBrowser methodsFor:'initialization & release'!
+
+initialize
+ super initialize.
+
+ isMultipleVersionBrowser := false.
+ isMultipleFilesVersionBrowser := false.
+
+ diffTextLabelA := ValueHolder new.
+ diffTextLabelB := ValueHolder new.
+ infoHolder := ValueHolder new.
+
+ selectedSymbolicVersionIndexHolder := nil asValue.
+ selectedSymbolicVersionIndexHolder onChangeSend:#selectedSymbolicVersionIndexHolderChanged to:self.
+
+ selectedSymbolicVersionHolder := nil asValue.
+ selectedSymbolicVersionHolder onChangeSend:#selectedSymbolicVersionHolderChanged to:self.
+
+ selectedVersionIndexHolder := nil asValue.
+ selectedVersionIndexHolder onChangeSend:#selectedVersionIndexHolderChanged to:self.
+
+ selectedVersionHolder := nil asValue.
+ selectedVersionHolder onChangeSend:#selectedVersionHolderChanged to:self.
+
+ symbolicVersionList := List new.
+ symbolicVersionNameList := List new.
+ versionEntriesList := List new.
+ versionList := List new.
+
+ "Created: / 08-05-2019 / 10:59:30 / Claus Gittinger"
+ "Modified: / 08-07-2019 / 00:06:27 / Claus Gittinger"
+!
+
+postBuildWith:aBuilder
+ "
+ components which are invisible should be ignored by the panel.
+ Cannot be set via the interface builder.
+
+ <return: self>
+ "
+
+ super postBuildWith:aBuilder
+
+ "Modified: / 07-07-2019 / 23:56:48 / Claus Gittinger"
+!
+
+postOpenWith:aBuilder
+ super postOpenWith:aBuilder.
+
+ self isMultipleVersionBrowser ifTrue:[
+ self withWaitCursorDo:[
+ self updateVersionList.
+ ]
+ ]
+! !
+
+!FileVersionDiffBrowser methodsFor:'menu action'!
+
+mainMenu
+ "if this application runs as an subapplication,
+ the menu bar should not be used."
+
+ self masterApplication isNil ifTrue:[
+ ^ self class mainMenu
+ ].
+ ^ nil
+
+ "Modified: / 25-07-2006 / 11:13:44 / cg"
+!
+
+menuAHolder
+ ^ [ self class menuA ]
+
+ "Created: / 05-02-2017 / 10:07:15 / cg"
+!
+
+menuBHolder
+ ^ [ self class menuB ]
+
+ "Created: / 05-02-2017 / 10:07:22 / cg"
+!
+
+menuMHolder
+ ^ [ self class menuM ]
+
+ "Created: / 05-02-2017 / 10:07:36 / cg"
+!
+
+openDocumentation
+ HTMLDocumentView openFullOnDocumentationFile:'tools/misc/TOP.html#VERSIONDIFF'
+!
+
+versionMenuCompareAgainstNextVersion
+ |fn selectedVersion nextVersion|
+
+ selectedVersion := self selectedVersionHolder value.
+ nextVersion := self versionList at:(self selectedVersionIndex - 1).
+ fn := fileHolder value.
+
+ self class
+ openOnFile:fn versionA:selectedVersion versionB:nextVersion
+
+ "Modified: / 08-07-2019 / 00:09:54 / Claus Gittinger"
+!
+
+versionMenuCompareAgainstPreviousVersion
+ |fn selectedVersion prevVersion|
+
+ selectedVersion := self selectedVersionHolder value.
+ selectedVersion isNil ifTrue:[
+ self selectedVersionIndexHolder value:1
+ ].
+ prevVersion := self versionList at:(self selectedVersionIndex + 1).
+ fn := fileHolder value.
+
+ self class
+ openOnFile:fn versionA:prevVersion versionB:selectedVersion
+
+ "Modified: / 08-07-2019 / 00:10:12 / Claus Gittinger"
+! !
+
+!FileVersionDiffBrowser methodsFor:'private'!
+
+addAcceptToTextViewMenus
+ "add to the standard diff text view or single text views menu an accept entry.
+ The acceptAction will fetch the corresponding change and apply it
+ (not the shown text)
+
+ <return: self>
+ "
+
+ |diffTextView leftView rightView singleView|
+
+ diffTextView := self diffTextView.
+ leftView := diffTextView leftTextView.
+ rightView := diffTextView rightTextView.
+ singleView := self componentAt:#singleTextView.
+
+ (Array
+ with:leftView
+ with:rightView
+ with:singleView)
+ do:[:v |
+ |mGen|
+
+ mGen := [
+ |m|
+
+ m := v editMenu.
+
+ (m selectorAt:#accept) isNil ifTrue:[
+ m addLabels:(resources array:#('-' 'Accept'))
+ selectors:#(nil #accept)
+ after:#copySelection.
+ ].
+ m
+ actionAt:#accept
+ put:[
+ v == singleView ifTrue:[
+ self acceptInSingleView
+ ] ifFalse:[
+ v == leftView ifTrue:[
+ self acceptInLeftView
+ ] ifFalse:[
+ self acceptInRightView
+ ].
+ ].
+ ].
+ m selectorAt:#accept put:nil.
+ m enable:#copySelection.
+ m setEnable:#accept to:[self canAcceptInCodeView].
+ m
+ ].
+ v menuHolder:mGen.
+ v menuMessage:#value.
+ ]
+!
+
+getFile:fileName version:version
+ |errStream errorMessages inStream contents|
+
+ errStream := '' writeStream.
+ [
+ inStream := PipeStream
+ readingFrom:('cvs update -p -r %1 %2'
+ bindWith:(version ? '')
+ with:fileName baseName)
+ errorDisposition:errStream
+ inDirectory:fileName directory pathName.
+ contents := inStream upToEnd.
+ ] ensure:[
+ inStream notNil ifTrue:[
+ inStream close
+ ]
+ ].
+ contents isEmptyOrNil ifTrue:[
+ errorMessages := errStream contents.
+ errorMessages notEmptyOrNil ifTrue:[
+ self halt.
+ ].
+ ].
+ ^ contents
+
+ "Created: / 07-07-2019 / 22:09:21 / Claus Gittinger"
+ "Modified: / 08-07-2019 / 01:24:35 / Claus Gittinger"
+!
+
+informationUntranslated:msg
+ self infoHolder value:msg
+
+ "Created: / 09-08-2018 / 15:40:52 / Claus Gittinger"
+!
+
+resetSelectionHolders
+ "
+ reset all selection holders when a new change set is given.
+ First set the selection to nil.
+
+ <return: self>
+ "
+
+ self diffTextView text1:'' text2:''.
+
+ "Modified (comment): / 08-07-2019 / 00:06:09 / Claus Gittinger"
+!
+
+showDiffTextView
+ "
+ if a method change is selected, then show the diff text view.
+ Add an accept entry to the popup menu.
+
+ <return: self>
+ "
+
+ (self componentAt:#diffTextViewBox) raise; beVisible.
+ (self componentAt:#diffTextView) realizeAllSubViews.
+
+ "/ self addAcceptToTextViewMenus.
+
+ "Modified: / 08-07-2019 / 00:02:19 / Claus Gittinger"
+!
+
+showSingleTextView
+ "
+ if a method is selected which is only in version A or B of the class,
+ then show the text view.
+ Add an accept entry to the popup menu.
+
+ <return: self>
+ "
+
+ (self componentAt:#diffTextViewBox) beInvisible.
+ "/ self addAcceptToTextViewMenus.
+
+ "Modified: / 08-07-2019 / 00:03:10 / Claus Gittinger"
+!
+
+showVersionInfoIfNothingSelected
+ "show the revision info (author, date, time and logMessage),
+ if no method is selected"
+
+ |revInfo infoText|
+
+ "/ self information:''.
+
+ versionInfoList notNil ifTrue:[
+ revInfo := versionInfoList detect:[:info | (info at:#revision) = selectedVersionHolder value] ifNone:nil.
+ revInfo notNil ifTrue:[
+ infoText := 'Revision: %1\Author: %2\Date: %3\Log:\\%4' withCRs
+ bindWith:(revInfo at:#revision)
+ with:(revInfo at:#author)
+ with:(revInfo at:#date)
+ with:(revInfo at:#logMessage).
+ ].
+ ].
+ self showSingleTextView.
+
+ "Modified: / 05-02-2017 / 11:49:47 / cg"
+ "Modified (comment): / 08-07-2019 / 00:06:32 / Claus Gittinger"
+! !
+
+!FileVersionDiffBrowser methodsFor:'setup'!
+
+setupForAllVersionsOfFile:aFilename
+ self fileHolder value:aFilename.
+ self updateVersionList.
+
+ "Created: / 07-07-2019 / 22:42:40 / Claus Gittinger"
+ "Modified: / 07-07-2019 / 23:46:28 / Claus Gittinger"
+!
+
+setupForFile:aFilename againstVersion:aVersionA
+ "compute the diffs for the file's current version against the repository version A.
+ When setting the diffs, the labels, list etc. of the receiver
+ are updated."
+
+ |text1 text2|
+
+ text1 := aFilename contentsAsString.
+ text2 := self getFile:aFilename version:aVersionA.
+
+ self diffTextView text1:text1 text2:text2.
+ self diffTextLabelA value:('File: %1' bindWith:aFilename baseName).
+ self diffTextLabelB value:aVersionA.
+
+ "Created: / 07-07-2019 / 19:57:27 / Claus Gittinger"
+ "Modified: / 08-07-2019 / 01:13:47 / Claus Gittinger"
+!
+
+setupForFile:fileA labelA:labelA andFile:fileB labelB:labelB
+ "generate the diffs from the two files A and B.
+ When setting the diffs, the labels, list etc. of the receiver
+ are updated."
+
+ self diffTextView
+ text1:(fileA contentsAsString)
+ text2:(fileB contentsAsString).
+
+ self diffTextLabelA value:labelA.
+ self diffTextLabelB value:labelB.
+
+ "Created: / 07-07-2019 / 19:59:03 / Claus Gittinger"
+ "Modified: / 08-07-2019 / 01:14:36 / Claus Gittinger"
+! !
+
+!FileVersionDiffBrowser class methodsFor:'documentation'!
+
+version_CVS
+ ^ '$Header$'
+! !
+