VersionDiffBrowser.st
author Claus Gittinger <cg@exept.de>
Mon, 05 Jul 1999 22:30:31 +0200
changeset 2224 0e4250930948
parent 2221 f536ebd184ef
child 2225 6d90bc1df6ee
permissions -rw-r--r--
checkin from browser

ApplicationModel subclass:#VersionDiffBrowser
	instanceVariableNames:'classBeingCompared versionA versionB changeSetA changeSetB
		filteredChangeSetA filteredChangeSetB changedMethodsChangeSet
		indexFromChangedToA indexFromChangedToB diffTextView'
	classVariableNames:''
	poolDictionaries:''
	category:'Interface-Browsers'
!

VersionDiffBrowser comment:'some comment
'!


!VersionDiffBrowser 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:VersionDiffBrowser andSelector:#windowSpec
     VersionDiffBrowser new openInterface:#windowSpec
     VersionDiffBrowser open
    "

    <resource: #canvas>

    ^ 
     #(#FullSpec
        #name: #windowSpec
        #window: 
       #(#WindowSpec
          #label: 'Version DiffBrowser'
          #name: 'Version DiffBrowser'
          #layout: #(#LayoutFrame 220 0 200 0 1084 0 703 0)
          #level: 0
          #min: #(#Point 10 10)
          #max: #(#Point nil nil)
          #bounds: #(#Rectangle 220 200 1085 704)
          #menu: #mainMenu
          #usePreferredExtent: false
          #returnIsOKInDialog: true
          #escapeIsCancelInDialog: true
        )
        #component: 
       #(#SpecCollection
          #collection: #(
           #(#VariableVerticalPanelSpec
              #name: 'VariableVerticalPanel1'
              #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
              #handles: #(#Any 0.319444 1.0)
              #component: 
             #(#SpecCollection
                #collection: #(
                 #(#HorizontalPanelViewSpec
                    #name: 'TopHorizontalPanel'
                    #horizontalLayout: #fit
                    #verticalLayout: #fit
                    #horizontalSpace: 3
                    #verticalSpace: 3
                    #component: 
                   #(#SpecCollection
                      #collection: #(
                       #(#ViewSpec
                          #name: 'BoxA'
                          #level: 0
                          #component: 
                         #(#SpecCollection
                            #collection: #(
                             #(#LabelSpec
                                #label: 'Only in A'
                                #name: 'OnlyInALabel'
                                #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 20 0)
                                #translateLabel: true
                                #labelChannel: #onlyInALabelHolder
                              )
                             #(#SequenceViewSpec
                                #name: 'ListA'
                                #layout: #(#LayoutFrame 0 0.0 20 0.0 0 1.0 -3 1.0)
                                #model: #methodsOnlyInASelection
                                #menu: #menuA
                                #hasHorizontalScrollBar: true
                                #hasVerticalScrollBar: true
                                #miniScrollerHorizontal: true
                                #valueChangeSelector: #methodsOnlyInASelectionChanged
                                #useIndex: true
                                #sequenceList: #methodsOnlyInA
                              )
                             )
                           
                          )
                          #extent: #(#Point 286 160)
                        )
                       #(#ViewSpec
                          #name: 'BoxM'
                          #component: 
                         #(#SpecCollection
                            #collection: #(
                             #(#LabelSpec
                                #label: 'Changed'
                                #name: 'Label2'
                                #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 20 0)
                                #translateLabel: true
                                #labelChannel: #changedLabelHolder
                              )
                             #(#SequenceViewSpec
                                #name: 'ListM'
                                #layout: #(#LayoutFrame 0 0.0 20 0.0 0 1.0 -3 1.0)
                                #model: #methodsChangedSelection
                                #menu: #menuM
                                #hasHorizontalScrollBar: true
                                #hasVerticalScrollBar: true
                                #miniScrollerHorizontal: true
                                #valueChangeSelector: #methodsChangedSelectionChanged
                                #useIndex: true
                                #sequenceList: #methodsChanged
                              )
                             )
                           
                          )
                          #extent: #(#Point 286 160)
                        )
                       #(#ViewSpec
                          #name: 'BoxB'
                          #component: 
                         #(#SpecCollection
                            #collection: #(
                             #(#LabelSpec
                                #label: 'Only in B'
                                #name: 'OnlyInBLabel'
                                #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 20 0)
                                #translateLabel: true
                                #labelChannel: #onlyInBLabelHolder
                              )
                             #(#SequenceViewSpec
                                #name: 'ListB'
                                #layout: #(#LayoutFrame 0 0.0 20 0.0 0 1.0 -3 1.0)
                                #model: #methodsOnlyInBSelection
                                #menu: #menuB
                                #hasHorizontalScrollBar: true
                                #hasVerticalScrollBar: true
                                #miniScrollerHorizontal: true
                                #valueChangeSelector: #methodsOnlyInBSelectionChanged
                                #useIndex: true
                                #sequenceList: #methodsOnlyInB
                              )
                             )
                           
                          )
                          #extent: #(#Point 287 160)
                        )
                       )
                     
                    )
                  )
                 #(#ViewSpec
                    #name: 'Box4'
                    #component: 
                   #(#SpecCollection
                      #collection: #(
                       #(#ViewSpec
                          #name: 'diffTextViewBox'
                          #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
                          #initiallyInvisible: true
                          #component: 
                         #(#SpecCollection
                            #collection: #(
                             #(#LabelSpec
                                #label: 'A'
                                #name: 'DiffTextLabelA'
                                #layout: #(#LayoutFrame 0 0 0 0 0 0.5 20 0)
                                #translateLabel: true
                                #labelChannel: #diffTextLabelA
                              )
                             #(#LabelSpec
                                #label: 'B'
                                #name: 'DiffTextLabelB'
                                #layout: #(#LayoutFrame 0 0.5 0 0 0 1 20 0)
                                #translateLabel: true
                                #labelChannel: #diffTextLabelB
                              )
                             #(#ArbitraryComponentSpec
                                #name: 'diffTextView'
                                #layout: #(#LayoutFrame 0 0.0 20 0.0 0 1.0 0 1.0)
                                #hasBorder: false
                                #component: #diffTextView
                              )
                             )
                           
                          )
                        )
                       #(#TextEditorSpec
                          #name: 'singleTextView'
                          #layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
                          #initiallyInvisible: true
                          #model: #methodText
                          #hasHorizontalScrollBar: true
                          #hasVerticalScrollBar: true
                          #miniScrollerHorizontal: true
                        )
                       )
                     
                    )
                  )
                 )
               
              )
            )
           )
         
        )
      )
! !

!VersionDiffBrowser 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:VersionDiffBrowser andSelector:#mainMenu
     (Menu new fromLiteralArrayEncoding:(VersionDiffBrowser mainMenu)) startUp
    "

    <resource: #menu>

    ^ 
     #(#Menu
        #(
         #(#MenuItem
            #label: 'File'
            #translateLabel: true
            #submenu: 
           #(#Menu
              #(
               #(#MenuItem
                  #label: 'Exit'
                  #translateLabel: true
                  #value: #closeRequest
                )
               )
              nil
              nil
            )
          )
         #(#MenuItem
            #label: 'Help'
            #translateLabel: true
            #startGroup: #right
            #submenu: 
           #(#Menu
              #(
               #(#MenuItem
                  #label: 'Documentation'
                  #translateLabel: true
                  #value: #openDocumentation
                )
               #(#MenuItem
                  #label: '-'
                )
               #(#MenuItem
                  #label: 'About this Application'
                  #translateLabel: true
                  #value: #openAboutThisApplication
                )
               )
              nil
              nil
            )
          )
         )
        nil
        nil
      )
!

menuA
    "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:#menu1
     (Menu new fromLiteralArrayEncoding:(VersionDiffBrowser menu1)) startUp
    "

    <resource: #menu>

    ^ 
     #(#Menu
        #(
         #(#MenuItem
            #label: 'Inspect'
            #translateLabel: true
            #value: #inspectSelectedChangeInA
            #choiceValue: 'nil "UndefinedObject" '
          )
         )
        nil
        nil
      )
!

menuB
    "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:#menuB
     (Menu new fromLiteralArrayEncoding:(VersionDiffBrowser menuB)) startUp
    "

    <resource: #menu>

    ^ 
     #(#Menu
        #(
         #(#MenuItem
            #label: 'Inspect'
            #translateLabel: true
            #value: #inspectSelectedChangeInB
            #choiceValue: 'nil "UndefinedObject" '
          )
         )
        nil
        nil
      )
!

menuM
    "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:#menu1
     (Menu new fromLiteralArrayEncoding:(VersionDiffBrowser menu1)) startUp
    "

    <resource: #menu>

    ^ 
     #(#Menu
        #(
         #(#MenuItem
            #label: 'Inspect both'
            #translateLabel: true
            #value: #inspectSelectedChangeInM
            #choiceValue: 'nil "UndefinedObject" '
          )
         )
        nil
        nil
      )
! !

!VersionDiffBrowser class methodsFor:'startup'!

openOnClass:aClass labelA:lblA sourceA:srcA labelB:lblB sourceB:srcB 
    |browser|

    browser := self new.
    browser allButOpen.

    browser classBeingCompared:aClass.
    browser 
        labelA:lblA sourceA:srcA
        labelB:lblB sourceB:srcB.

    browser openWindow.

    ^ browser.

    "
     self openOnClass:Array versionA:'1.116' versionB:'1.113'
    "
!

openOnClass:aClass versionA:vsnA versionB:vsnB
    |browser|

    browser := self new.
    browser allButOpen.

    browser classBeingCompared:aClass.
    browser versionA:vsnA.
    browser versionB:vsnB.

    browser openWindow.

    ^ browser.

    "
     self openOnClass:Array versionA:'1.116' versionB:'1.113'
    "
! !

!VersionDiffBrowser methodsFor:'accessing'!

classBeingCompared
    "return the value of the instance variable 'classBeingCompared' (automatically generated)"

    ^ classBeingCompared!

classBeingCompared:something
    "set the value of the instance variable 'classBeingCompared' (automatically generated)"

    classBeingCompared := something.
    self updateViewsIfPossible.
!

labelA:lblA sourceA:srcA labelB:lblB sourceB:srcB
    |s|

    changeSetA := ChangeSet fromStream:(s := srcA readStream).
    s close.
    changeSetB := ChangeSet fromStream:(s := srcB readStream).
    s close.
    versionA := lblA.
    versionB := lblB.
    self updateLabels.
    self updateLists.

!

versionA
    "return the value of the instance variable 'versionA' (automatically generated)"

    ^ versionA!

versionA:something
    "set the value of the instance variable 'versionA' (automatically generated)"

    versionA := something.
    self updateViewsIfPossible.

!

versionB
    "return the value of the instance variable 'versionB' (automatically generated)"

    ^ versionB!

versionB:something
    "set the value of the instance variable 'versionB' (automatically generated)"

    versionB := something.
    self updateViewsIfPossible.

! !

!VersionDiffBrowser methodsFor:'actions'!

methodsChangedSelectionChanged
    |sel idxA idxB changeA changeB|

    sel := self methodsChangedSelection value.
    sel notNil ifTrue:[
        self methodsOnlyInASelection value:nil.
        self methodsOnlyInBSelection value:nil.

        idxA := indexFromChangedToA at:sel ifAbsent:nil.
        idxB := indexFromChangedToB at:sel ifAbsent:nil.

        changeA := changeSetA at:idxA.
        changeB := changeSetB at:idxB.

        self diffTextView text1:changeA source text2:changeB source.
        self diffTextView moveToNextChanged.

        self showDiffTextView.

    ]
!

methodsOnlyInASelectionChanged
    |change sel|

    sel := self methodsOnlyInASelection value.
    sel notNil ifTrue:[
        self methodsOnlyInBSelection value:nil.
        self methodsChangedSelection value:nil.

        change := filteredChangeSetA at:sel.
        self methodText value:(change source).    
        self showSingleTextView.
    ]
!

methodsOnlyInBSelectionChanged
    |change sel|

    sel := self methodsOnlyInBSelection value.
    sel notNil ifTrue:[
        self methodsOnlyInASelection value:nil.
        self methodsChangedSelection value:nil.

        change := filteredChangeSetB at:sel.
        self methodText value:(change source).    
        self showSingleTextView.
    ]
! !

!VersionDiffBrowser methodsFor:'aspects'!

changedLabelHolder
    "automatically generated by UIPainter ..."

    "*** the code below creates a default model when invoked."
    "*** (which may not be the one you wanted)"
    "*** Please change as required and accept in the browser."

    |holder|

    (holder := builder bindingAt:#changedLabelHolder) isNil ifTrue:[
        builder aspectAt:#changedLabelHolder put:(holder :=  ValueHolder new).
    ].
    ^ holder.
!

diffTextLabelA
    "automatically generated by UIPainter ..."

    "*** the code below creates a default model when invoked."
    "*** (which may not be the one you wanted)"
    "*** Please change as required and accept in the browser."

    |holder|

    (holder := builder bindingAt:#diffTextLabelA) isNil ifTrue:[
        builder aspectAt:#diffTextLabelA put:(holder :=  ValueHolder new).
    ].
    ^ holder.
!

diffTextLabelB
    "automatically generated by UIPainter ..."

    "*** the code below creates a default model when invoked."
    "*** (which may not be the one you wanted)"
    "*** Please change as required and accept in the browser."

    |holder|

    (holder := builder bindingAt:#diffTextLabelB) isNil ifTrue:[
        builder aspectAt:#diffTextLabelB put:(holder :=  ValueHolder new).
    ].
    ^ holder.
!

methodText
    "automatically generated by UIPainter ..."

    "*** the code below creates a default model when invoked."
    "*** (which may not be the one you wanted)"
    "*** Please change as required and accept in the browser."

    |holder|

    (holder := builder bindingAt:#methodText) isNil ifTrue:[
        builder aspectAt:#methodText put:(holder :=  ValueHolder new).
    ].
    ^ holder.
!

methodsChanged
    "automatically generated by UIPainter ..."

    "*** the code below creates a default model when invoked."
    "*** (which may not be the one you wanted)"
    "*** Please change as required and accept in the browser."

    |holder|

    (holder := builder bindingAt:#methodsChanged) isNil ifTrue:[
        builder aspectAt:#methodsChanged put:(holder :=  List new).
    ].
    ^ holder.
!

methodsChangedSelection
    "automatically generated by UIPainter ..."

    "*** the code below creates a default model when invoked."
    "*** (which may not be the one you wanted)"
    "*** Please change as required and accept in the browser."

    |holder|

    (holder := builder bindingAt:#methodsChangedSelection) isNil ifTrue:[
        builder aspectAt:#methodsChangedSelection put:(holder :=  ValueHolder new).
    ].
    ^ holder.
!

methodsOnlyInA
    "automatically generated by UIPainter ..."

    "*** the code below creates a default model when invoked."
    "*** (which may not be the one you wanted)"
    "*** Please change as required and accept in the browser."

    |holder|

    (holder := builder bindingAt:#methodsOnlyInA) isNil ifTrue:[
        builder aspectAt:#methodsOnlyInA put:(holder :=  List new).
    ].
    ^ holder.
!

methodsOnlyInASelection
    "automatically generated by UIPainter ..."

    "*** the code below creates a default model when invoked."
    "*** (which may not be the one you wanted)"
    "*** Please change as required and accept in the browser."

    |holder|

    (holder := builder bindingAt:#methodsOnlyInASelection) isNil ifTrue:[
        builder aspectAt:#methodsOnlyInASelection put:(holder :=  ValueHolder new).
    ].
    ^ holder.
!

methodsOnlyInB
    "automatically generated by UIPainter ..."

    "*** the code below creates a default model when invoked."
    "*** (which may not be the one you wanted)"
    "*** Please change as required and accept in the browser."

    |holder|

    (holder := builder bindingAt:#methodsOnlyInB) isNil ifTrue:[
        builder aspectAt:#methodsOnlyInB put:(holder :=  List new).
    ].
    ^ holder.
!

methodsOnlyInBSelection
    "automatically generated by UIPainter ..."

    "*** the code below creates a default model when invoked."
    "*** (which may not be the one you wanted)"
    "*** Please change as required and accept in the browser."

    |holder|

    (holder := builder bindingAt:#methodsOnlyInBSelection) isNil ifTrue:[
        builder aspectAt:#methodsOnlyInBSelection put:(holder :=  ValueHolder new).
    ].
    ^ holder.
!

onlyInALabelHolder
    "automatically generated by UIPainter ..."

    "*** the code below creates a default model when invoked."
    "*** (which may not be the one you wanted)"
    "*** Please change as required and accept in the browser."

    |holder|

    (holder := builder bindingAt:#onlyInALabelHolder) isNil ifTrue:[
        builder aspectAt:#onlyInALabelHolder put:(holder :=  ValueHolder new).
    ].
    ^ holder.
!

onlyInBLabelHolder
    "automatically generated by UIPainter ..."

    "*** the code below creates a default model when invoked."
    "*** (which may not be the one you wanted)"
    "*** Please change as required and accept in the browser."

    |holder|

    (holder := builder bindingAt:#onlyInBLabelHolder) isNil ifTrue:[
        builder aspectAt:#onlyInBLabelHolder put:(holder :=  ValueHolder new).
    ].
    ^ holder.
! !

!VersionDiffBrowser methodsFor:'initialization & release'!

closeDownViews
    "This is a hook method generated by the Browser.
     It will be invoked when your app/dialog-window is really closed."

    "/ change the code below as required ...
    "/ This should cleanup any leftover resources
    "/ (for example, temporary files)
    "/ super closeRequest will initiate the closeDown

    "/ add your code here

    "/ do not remove the one below ...
    ^ super closeDownViews
!

closeRequest
    "This is a hook method generated by the Browser.
     It will be invoked when your app/dialog-window is about to be
     closed (and has a chance to suppress the close)."

    "/ change the code below as required ...
    "/ Closing can be suppressed, by returning.
    "/ super closeRequest will initiate the closeDown

    ^ super closeRequest
!

postBuildWith:aBuilder
    "This is a hook method generated by the Browser.
     It will be invoked during the initialization of your app/dialog,
     after all of the visual components have been built, 
     but BEFORE the top window is made visible.
     Add any app-specific actions here (reading files, setting up
     values etc.)"

    "/ add any code here ...

    (aBuilder componentAt:#TopHorizontalPanel) ignoreInvisibleComponents:true.

    ^ super postBuildWith:aBuilder
! !

!VersionDiffBrowser methodsFor:'menu action'!

inspectSelectedChangeInA
    |sel|

    sel := self methodsOnlyInASelection value.
    sel notNil ifTrue:[
        (changeSetA at:sel) inspect
    ]
!

inspectSelectedChangeInB
    |sel|

    sel := self methodsOnlyInBSelection value.
    sel notNil ifTrue:[
        (changeSetB at:sel) inspect
    ]
!

inspectSelectedChangeInM
    |sel idxA idxB|

    sel := self methodsChangedSelection value.
    sel notNil ifTrue:[
        idxA := indexFromChangedToA at:sel ifAbsent:nil.
        idxB := indexFromChangedToB at:sel ifAbsent:nil.

        (changeSetA at:idxA) inspect.
        (changeSetB at:idxB) inspect.
    ]
! !

!VersionDiffBrowser methodsFor:'private'!

change:changeA isForSameAs:changeB
    "return true, if the two given changes are for the same method or definition.
     Ought to go to changeSet class"

    changeA isMethodChange ifTrue:[
        ^ self change:changeA isForSameMethodAs:changeB
    ].
    changeA isClassDefinitionChange ifTrue:[
        ^ self change:changeA isForSameClassDefinitionAs:changeB
    ].
    ^ false
!

change:changeA isForSameClassDefinitionAs:changeB
    "return true, if the two given changes are for the same class def.
     Ought to go to changeSet class"

    changeA isClassDefinitionChange ifFalse:[^ false].   
    changeB isClassDefinitionChange ifFalse:[^ false].   

    changeA className ~= changeB className ifTrue:[^ false].
    ^ true.
!

change:changeA isForSameMethodAs:changeB
    "return true, if the two given changes are for the same method.
     Ought to go to changeSet class"

    changeA isMethodChange ifFalse:[^ false].   "/ for now
    changeB isMethodChange ifFalse:[^ false].   "/ for now

    changeA className ~= changeB className ifTrue:[^ false].
    changeA selector ~= changeB selector ifTrue:[^ false].
    ^ true.
!

change:changeA isSameAs:changeB
    "return true, if the two given changes are the same.
     Ought to go to changeSet class"

    |sourceA sourceB|

    changeA isMethodChange ifFalse:[
        "/ A is not a methodChange - B must not be as well.
        changeB isMethodChange ifTrue:[^ false].   

        changeA isClassDefinitionChange ifTrue:[
            changeB isClassDefinitionChange ifFalse:[^ false].  

            changeA className ~= changeB className ifTrue:[^ false].
            changeA source = changeB source ifTrue:[^ true].
            ^ false   "/ for now
        ].

        changeA isDoIt ifTrue:[
            changeB isDoIt ifFalse:[^ false].
            ^ changeA source = changeB source 
        ].

        ^ false   "/ for now
    ].   

    "/ A is a methodChange - B must be as well.
    changeB isMethodChange ifFalse:[^ false].   

    changeA className ~= changeB className ifTrue:[^ false].
    changeA selector ~= changeB selector ifTrue:[^ false].

    (sourceA := changeA source) = (sourceB := changeB source) ifTrue:[^ true].

    sourceA := sourceA asCollectionOfLines.
    sourceB := sourceB asCollectionOfLines.
    sourceA size ~~ sourceB size ifTrue:[^ false].
    sourceA := sourceA collect:[:line | line withTabsExpanded withoutTrailingSeparators].
    sourceB := sourceB collect:[:line | line withTabsExpanded withoutTrailingSeparators].
    sourceA = sourceB ifFalse:[^ false].
    ^ true.
!

showDiffTextView
    (self builder componentAt:#diffTextViewBox) raise; beVisible.
    (self builder componentAt:#singleTextView) beInvisible.
    (self builder componentAt:#diffTextView) realizeAllSubViews.
!

showSingleTextView
    (self builder componentAt:#singleTextView) raise; beVisible.
    (self builder componentAt:#diffTextViewBox) beInvisible.

!

updateFromVersions
    |mgr versionAStream versionBStream|

    mgr := classBeingCompared sourceCodeManager.

    versionAStream := mgr getSourceStreamFor:classBeingCompared revision:versionA.
    changeSetA := ChangeSet fromStream:versionAStream.
    versionAStream close.

    versionBStream := mgr getSourceStreamFor:classBeingCompared revision:versionB.
    changeSetB := ChangeSet fromStream:versionBStream.
    versionBStream close.

    self updateLists

!

updateLabels
    versionA notNil ifTrue:[
        self diffTextLabelA value:versionA.
        self onlyInALabelHolder value:('Only in ' , versionA).
        (self builder componentAt:#OnlyInALabel) backgroundColor:Color green darkened.
    ].
    versionB notNil ifTrue:[
        self diffTextLabelB value:versionB.
        self onlyInBLabelHolder value:('Only in ' , versionB).
        (self builder componentAt:#OnlyInBLabel) backgroundColor:Color red darkened.
    ].
!

updateLists
    |mgr nmListA nmListB nmListM|

    filteredChangeSetA := ChangeSet new.
    filteredChangeSetB := ChangeSet new.
    changedMethodsChangeSet := ChangeSet new.

    indexFromChangedToA := OrderedCollection new.
    indexFromChangedToB := OrderedCollection new.

    changeSetA keysAndValuesDo:[:idxA :aChangeInA |
        |anyFound|

        anyFound := false.

        changeSetB do:[:aChangeInB |
            (self change:aChangeInA isForSameAs:aChangeInB) ifTrue:[
                anyFound := true.

                "/ also in B - is it different ?
                (self change:aChangeInA isSameAs:aChangeInB) ifFalse:[
                    changedMethodsChangeSet add:aChangeInA.
                    indexFromChangedToA add:idxA.
                    indexFromChangedToB add:nil.
                ]
            ] ifFalse:[
                (self change:aChangeInA isSameAs:aChangeInB) ifTrue:[
                    anyFound := true.
                ] ifFalse:[
                ]
            ]
        ].

        anyFound ifFalse:[
            filteredChangeSetA add:aChangeInA.
        ]
    ].

    changeSetB keysAndValuesDo:[:idxB :aChangeInB |
        |anyFound|

        anyFound := false.

        changeSetA do:[:aChangeInA |
            |idxM|

            (self change:aChangeInA isForSameAs:aChangeInB) ifTrue:[
                anyFound := true.

                "/ also in B - is it different ?
                (self change:aChangeInA isSameAs:aChangeInB) ifFalse:[
                    "/ already there ?
                    idxM := changedMethodsChangeSet findFirst:[:c | self change:c isForSameAs:aChangeInB].
                    idxM == 0 ifTrue:[
                        changedMethodsChangeSet add:aChangeInB.
                        indexFromChangedToB add:idxB.
                    ] ifFalse:[
                        indexFromChangedToB at:idxM put:idxB
                    ]
                ]
            ] ifFalse:[
                (self change:aChangeInA isSameAs:aChangeInB) ifTrue:[
                    anyFound := true.
                ] ifFalse:[
                ]
            ]
        ].
        anyFound ifFalse:[
            filteredChangeSetB add:aChangeInB.
        ]
    ].

    nmListA := self methodsOnlyInA.
    nmListA removeAll.
    nmListA addAll:(filteredChangeSetA collect:[:c | c printString]).

    nmListB := self methodsOnlyInB.
    nmListB removeAll.
    nmListB addAll:(filteredChangeSetB collect:[:c | c printString]).

    nmListM := self methodsChanged.
    nmListM removeAll.
    nmListM addAll:(changedMethodsChangeSet collect:[:c | c printString]).


    nmListA isEmpty ifTrue:[
        (self builder componentAt:#BoxA) beInvisible.
    ] ifFalse:[
        (self builder componentAt:#BoxA) beVisible.
    ].

    nmListB isEmpty ifTrue:[
        (self builder componentAt:#BoxB) beInvisible.
    ] ifFalse:[
        (self builder componentAt:#BoxB) beVisible.
    ].

    nmListM isEmpty ifTrue:[
        (nmListA notEmpty or:[nmListB notEmpty]) ifTrue:[
            (self builder componentAt:#BoxM) beInvisible.
        ]
    ] ifFalse:[
        (self builder componentAt:#BoxM) beVisible.
    ]

!

updateViewsIfPossible
    classBeingCompared notNil ifTrue:[
        self window label:'Version Diff Browser on ' , classBeingCompared name.

        self updateLabels.

        changeSetA notNil ifTrue:[
            changeSetB notNil ifTrue:[
                self updateLists.
                ^ self
            ]
        ].

        versionA notNil ifTrue:[
            versionB notNil ifTrue:[
                self updateFromVersions
            ]
        ]
    ]


! !

!VersionDiffBrowser methodsFor:'values'!

diffTextView
    "automatically generated by UIPainter ..."

    diffTextView isNil ifTrue:[
        diffTextView := HVScrollableView
                           for:DiffTextView
                           miniScrollerH:true miniScrollerV:false.
        diffTextView addNextPreviousButtons.
    ].
    ^ diffTextView
! !

!VersionDiffBrowser class methodsFor:'documentation'!

version
    ^ '$Header: /cvs/stx/stx/libtool/VersionDiffBrowser.st,v 1.2 1999-07-05 20:30:31 cg Exp $'
! !