VersionDiffBrowser.st
changeset 14076 fbed27a15014
parent 13951 cc2b571b0591
child 14078 92e2df7adcca
--- a/VersionDiffBrowser.st	Fri Feb 28 13:58:37 2014 +0100
+++ b/VersionDiffBrowser.st	Fri Feb 28 19:27:01 2014 +0100
@@ -21,7 +21,10 @@
 		methodsOnlyInBSelection onlyInALabelHolder onlyInBLabelHolder
 		classHolder versionAHolder versionBHolder infoHolder
 		includeExtensionsHolder canIncludeExtensionsHolder
-		includeCategoryChangesHolder includeVersionMethodsHolder'
+		includeCategoryChangesHolder includeVersionMethodsHolder
+		isMultipleVersionBrowser versionList selectedVersionHolder
+		symbolicVersionList selectedSymbolicVersionHolder
+		symbolicToVersionMapping'
 	classVariableNames:''
 	poolDictionaries:''
 	category:'Interface-Browsers'
@@ -281,6 +284,243 @@
 
 	)
       )
+!
+
+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:VersionDiffBrowser andSelector:#windowSpecForMultipleVersions
+     VersionDiffBrowser new openInterface:#windowSpecForMultipleVersions
+    "
+
+    <resource: #canvas>
+
+    ^ 
+    #(FullSpec
+       name: windowSpecForMultipleVersions
+       window: 
+      (WindowSpec
+         label: 'Version DiffBrowser'
+         name: 'Version DiffBrowser'
+         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)
+             component: 
+            (SpecCollection
+               collection: (
+                (ViewSpec
+                   name: 'Box1'
+                   component: 
+                  (SpecCollection
+                     collection: (
+                      (SequenceViewSpec
+                         name: 'VersionList'
+                         layout: (LayoutFrame 0 0 0 0 0 0.5 0 1)
+                         model: selectedVersionHolder
+                         hasHorizontalScrollBar: true
+                         hasVerticalScrollBar: true
+                         useIndex: false
+                         sequenceList: versionList
+                       )
+                      (SequenceViewSpec
+                         name: 'List1'
+                         layout: (LayoutFrame 0 0.5 0 0 0 1 0 1)
+                         model: selectedSymbolicVersionHolder
+                         hasHorizontalScrollBar: true
+                         hasVerticalScrollBar: true
+                         useIndex: false
+                         sequenceList: symbolicVersionList
+                       )
+                      )
+                    
+                   )
+                 )
+                (HorizontalPanelViewSpec
+                   name: 'TopHorizontalPanel'
+                   horizontalLayout: fit
+                   verticalLayout: fit
+                   horizontalSpace: 3
+                   verticalSpace: 3
+                   component: 
+                  (SpecCollection
+                     collection: (
+                      (ViewSpec
+                         name: 'BoxA'
+                         level: 0
+                         visibilityChannel: boxAVisible
+                         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
+                               doubleClickSelector: methodInADoubleClicked:
+                               valueChangeSelector: methodsOnlyInASelectionChanged
+                               useIndex: true
+                               sequenceList: methodsOnlyInA
+                             )
+                            )
+                          
+                         )
+                         extent: (Point 286 207)
+                       )
+                      (ViewSpec
+                         name: 'BoxM'
+                         visibilityChannel: boxMVisible
+                         component: 
+                        (SpecCollection
+                           collection: (
+                            (LabelSpec
+                               label: 'Changed'
+                               name: 'ChangedLabel'
+                               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
+                               doubleClickSelector: methodInChangedDoubleClicked:
+                               valueChangeSelector: methodsChangedSelectionChanged
+                               useIndex: true
+                               sequenceList: methodsChanged
+                             )
+                            )
+                          
+                         )
+                         extent: (Point 286 207)
+                       )
+                      (ViewSpec
+                         name: 'BoxB'
+                         visibilityChannel: boxBVisible
+                         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
+                               doubleClickSelector: methodInBDoubleClicked:
+                               valueChangeSelector: methodsOnlyInBSelectionChanged
+                               useIndex: true
+                               sequenceList: methodsOnlyInB
+                             )
+                            )
+                          
+                         )
+                         extent: (Point 287 207)
+                       )
+                      )
+                    
+                   )
+                 )
+                (ViewSpec
+                   name: 'DiffBox'
+                   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
+                             )
+                            )
+                          
+                         )
+                       )
+                      (CodeViewSpec
+                         name: 'singleTextView'
+                         layout: (LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
+                         model: methodText
+                         hasHorizontalScrollBar: true
+                         hasVerticalScrollBar: true
+                         miniScrollerHorizontal: true
+                         isReadOnly: true
+                         hasKeyboardFocusInitially: false
+                       )
+                      )
+                    
+                   )
+                 )
+                )
+              
+             )
+             handles: (Any 0.217118997912317 0.666666666666667 1.0)
+           )
+          (LabelSpec
+             name: 'InfoLabel'
+             layout: (LayoutFrame 0 0 -25 1 0 1 0 1)
+             level: -1
+             translateLabel: true
+             labelChannel: infoHolder
+             adjust: left
+           )
+          )
+        
+       )
+     )
 ! !
 
 !VersionDiffBrowser class methodsFor:'menu specs'!
@@ -567,15 +807,35 @@
      (if this app is embedded in a subCanvas)."
 
     ^ #(
-	#changedLabelHolder
-	#onlyInALabelHolder
-	#onlyInBLabelHolder
+        #changedLabelHolder
+        #onlyInALabelHolder
+        #onlyInBLabelHolder
       ).
 
 ! !
 
 !VersionDiffBrowser class methodsFor:'startup'!
 
+openOnAllVersionsOfClass:aClass
+    "create a VersionDiffBrowser instance and set the class change set of the
+     browser. The class diff set is generated from aClasses current version against
+     the selected version in the top selection list"
+
+    |theBrowser|
+
+    theBrowser := self new.
+    theBrowser allButOpenInterface:#windowSpecForMultipleVersions.
+    theBrowser beMultipleVersionBrowser.
+    theBrowser classHolder:(ValueHolder with:aClass).
+    theBrowser setupForClass:aClass againstVersion:nil.
+    theBrowser openWindow.
+    ^ theBrowser.
+
+    "
+     self openOnAllVersionsOfClass:Object
+    "
+!
+
 openOnClass:aClass againstVersion:aVersionA
     "create a VersionDiffBrowser instance and set the class change set of the
      browser. The class diff set is generated from aClasses current against some version
@@ -798,6 +1058,10 @@
 
 !VersionDiffBrowser methodsFor:'accessing'!
 
+beMultipleVersionBrowser
+    isMultipleVersionBrowser := true
+!
+
 canIncludeExtensions:something
     self canIncludeExtensionsHolder value:something.
 !
@@ -887,6 +1151,10 @@
     "Modified: / 06-03-2012 / 15:37:32 / cg"
 !
 
+isMultipleVersionBrowser
+    ^ isMultipleVersionBrowser
+!
+
 selectedChangeInA
     "
     gets the selected method change for the 'method only in version A'.
@@ -1300,6 +1568,36 @@
     ^ onlyInBLabelHolder.
 
     "Modified: / 25-07-2006 / 11:15:07 / cg"
+!
+
+selectedSymbolicVersionHolder
+    selectedSymbolicVersionHolder isNil ifTrue:[
+        selectedSymbolicVersionHolder := nil asValue.
+        selectedSymbolicVersionHolder onChangeSend:#selectedSymbolicVersionHolderChanged to:self.
+    ].
+    ^ selectedSymbolicVersionHolder
+!
+
+selectedVersionHolder
+    selectedVersionHolder isNil ifTrue:[
+         selectedVersionHolder := nil asValue.
+        selectedVersionHolder onChangeSend:#selectedVersionHolderChanged to:self.
+    ].
+    ^ selectedVersionHolder
+!
+
+symbolicVersionList
+    symbolicVersionList isNil ifTrue:[
+         symbolicVersionList := List new.
+    ].
+    ^ symbolicVersionList
+!
+
+versionList
+    versionList isNil ifTrue:[
+         versionList := List new.
+    ].
+    ^ versionList
 ! !
 
 !VersionDiffBrowser methodsFor:'aspects-exported'!
@@ -1462,6 +1760,27 @@
     "Modified: / 17-07-2012 / 18:31:32 / cg"
 !
 
+selectedSymbolicVersionHolderChanged
+    self selectedVersionHolder 
+        value:(symbolicToVersionMapping at:( self selectedSymbolicVersionHolder value ))
+!
+
+selectedVersionHolderChanged
+    |idx|
+
+    self withWaitCursorDo:[
+        selectedVersionHolder value = '...' ifTrue:[
+            idx := self versionList size.
+            self updateVersionList.
+            selectedVersionHolder setValue:(self versionList at:idx).
+        ].
+
+        self 
+            setupForClass:classHolder value 
+            againstVersion:(selectedVersionHolder value).
+    ]
+!
+
 update:something with:parameter from:changedObject
     ((changedObject == includeExtensionsHolder)
     or:[ changedObject == includeCategoryChangesHolder
@@ -1493,6 +1812,16 @@
 
     (self componentAt:#TopHorizontalPanel) ignoreInvisibleComponents:true.
     super postBuildWith:aBuilder
+!
+
+postOpenWith:aBuilder
+    super postOpenWith:aBuilder.
+
+    self isMultipleVersionBrowser ifTrue:[
+        self withWaitCursorDo:[
+            self updateVersionList.
+        ]
+    ]
 ! !
 
 !VersionDiffBrowser methodsFor:'menu action'!
@@ -2017,6 +2346,67 @@
     self infoHolder value:info
 
     "Modified: / 17-07-2012 / 18:34:36 / cg"
+!
+
+updateVersionList
+    |cls sourceCodeManager numShown newNumShown numOverallRevisions
+     partialLog newestRev revisions symbolicNames
+     stableRevision releasedRevision tagList logMessages items|
+
+    cls := classHolder value.
+    sourceCodeManager := cls sourceCodeManager.
+
+    numShown := versionList size - 1.
+    newNumShown := (numShown + 50) max:30.
+    partialLog := sourceCodeManager revisionLogOf:cls numberOfRevisions:newNumShown.
+
+    partialLog isNil ifTrue:[
+        self warn:'Could not find/access the container for class ',cls 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.
+    symbolicNames := partialLog at:#symbolicNames ifAbsent:[].
+    symbolicNames notNil ifTrue:[
+        stableRevision := symbolicNames at:'stable' ifAbsent:[].
+        releasedRevision := symbolicNames at:'released' ifAbsent:[].
+        tagList := ((symbolicNames associations sort:[:a :b | a key < b key "self versionString:(a value) isLessThan:(b value)"])
+                     collect:[:assoc | assoc key]) reverse.
+        tagList remove:'stable' ifAbsent:[].
+        tagList notEmpty ifTrue:[tagList addFirst:'-'].
+        tagList addFirst:'stable'.
+    ].
+    logMessages := Dictionary new.
+
+    items := revisions 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:[:each | each at:#revision].
+    revisions size < numOverallRevisions ifTrue:[
+        revisions add:'...'
+    ].          
+    symbolicToVersionMapping := symbolicNames.
+    self symbolicVersionList contents:tagList.
+    self versionList contents:revisions.
 ! !
 
 !VersionDiffBrowser methodsFor:'setup'!
@@ -2481,10 +2871,10 @@
 !VersionDiffBrowser class methodsFor:'documentation'!
 
 version
-    ^ '$Header: /cvs/stx/stx/libtool/VersionDiffBrowser.st,v 1.118 2014-02-18 14:17:26 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libtool/VersionDiffBrowser.st,v 1.119 2014-02-28 18:27:01 cg Exp $'
 !
 
 version_CVS
-    ^ '$Header: /cvs/stx/stx/libtool/VersionDiffBrowser.st,v 1.118 2014-02-18 14:17:26 stefan Exp $'
+    ^ '$Header: /cvs/stx/stx/libtool/VersionDiffBrowser.st,v 1.119 2014-02-28 18:27:01 cg Exp $'
 ! !