FileVersionDiffBrowser.st
author Claus Gittinger <cg@exept.de>
Mon, 08 Jul 2019 01:38:17 +0200
changeset 3682 e1ff677dc21a
parent 3676 319c68f831df
child 3686 501ea259b6a8
permissions -rw-r--r--
+ FileVersionDiffBrowser

"
 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$'
! !