ApplicationModel subclass:#ClassRevisionTree
instanceVariableNames:'selectionHolder semaphoreCritical revisionInfoList revisionTask
currentClassItemInTask'
classVariableNames:''
poolDictionaries:''
category:'Interface-Browsers'
!
!ClassRevisionTree class methodsFor:'interface spec'!
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:ClassRevisionTree andSelector:#windowSpec
ClassRevisionTree new openInterface:#windowSpec
ClassRevisionTree open
"
<resource: #canvas>
^
#(#FullSpec
#name: #windowSpec
#window:
#(#WindowSpec
#label: 'ClassVersionTree'
#name: 'ClassVersionTree'
#min: #(#Point 10 10)
#max: #(#Point 9999 9999)
#bounds: #(#Rectangle 16 51 881 580)
)
#component:
#(#SpecCollection
#collection: #(
#(#HierarchicalListViewSpec
#name: 'HierarchicalItemListView'
#layout: #(#LayoutFrame 0 0.0 0 0.0 0 1.0 0 1.0)
#model: #hierarchicalItemSelectionAspect
#menu: #selectHierarchicalItemMenu
#hasHorizontalScrollBar: true
#hasVerticalScrollBar: true
#listModel: #hierarchicalItemListModel
#multipleSelectOk: true
#highlightMode: #label
#doubleClickSelector: #doubleClick:
#selectConditionSelector: #isHierarchicalItemSelectable:
#indicatorSelector: #doubleClick:
#retrieveIconsSelector: #icons
)
)
)
)
! !
!ClassRevisionTree class methodsFor:'menu specs'!
resourceItemMenu
"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:ClassRevisionTree andSelector:#resourceItemMenu
(Menu new fromLiteralArrayEncoding:(ClassRevisionTree resourceItemMenu)) startUp
"
<resource: #menu>
^
#(#Menu
#(
#(#MenuItem
#label: 'Compare Changes'
#translateLabel: true
#value: #menuActionCompareChanges
)
)
nil
nil
)
! !
!ClassRevisionTree class methodsFor:'startup'!
openOnClasses:aClassColl withSelectionHolder:aValueHolder
|theTree theClassItemColl|
theTree := self new.
theTree allButOpen.
theClassItemColl := aClassColl collect:[:eachClass |
|theClassItem theClass|
theClassItem := ClassItem new.
theClass := Smalltalk resolveName:eachClass inClass:self.
theClassItem myClass:theClass.
theClassItem].
theTree hierarchicalItemList addAll: theClassItemColl.
theTree selectionHolder:aValueHolder.
theTree openWindow.
^theTree
"
|theSelectionHolder|
theSelectionHolder := ValueHolder new.
theSelectionHolder compute:[:el |
Transcript showCR: el first revisionString.
Transcript showCR: el second revisionString].
ClassRevisionTree openOnClasses:(Smalltalk allClasses asOrderedCollection sort:[:x : y|x name < y name])
withSelectionHolder:theSelectionHolder.
"
! !
!ClassRevisionTree methodsFor:'accessing'!
hierarchicalListItemForSelectionIndex: anIndex
^self hierarchicalItemListModel at:anIndex ifAbsent:nil
!
hierarchicalListSelectionIndexColl
^self hierarchicalItemSelectionAspect value
!
hierarchicalListSelectionIndexColl:anArray
^self hierarchicalItemSelectionAspect value:anArray
!
revisionInfoList
"return the value of the instance variable 'revisionInfoList' (automatically generated)"
^ revisionInfoList ifNil:[revisionInfoList := IdentitySet new]
!
selectionHolder
"return the value of the instance variable 'selectionHolder' (automatically generated)"
^ selectionHolder!
selectionHolder:something
"set the value of the instance variable 'revisionItemSelection' (automatically generated)"
selectionHolder := something.
!
semaphoreCritical
"return the value of the instance variable 'semaphoreCritical' (automatically generated)"
^ semaphoreCritical ifNil:[semaphoreCritical := RecursionLock new]
! !
!ClassRevisionTree methodsFor:'actions'!
doubleClick: anIndex
"automatically generated by UIPainter ..."
"*** the code below performs no action"
"*** (except for some feedback on the Transcript)"
"*** Please change as required and accept in the browser."
"action to be added ..."
(self hierarchicalItemListModel at: anIndex) toggleExpand
!
getRevisionInfoForClassItem: aClassItem
self semaphoreCritical critical:[
|theList|
currentClassItemInTask == aClassItem ifTrue:[^self].
(theList := self revisionInfoList) removeIdentical:aClassItem ifAbsent:[nil].
theList add:aClassItem.
Transcript showCR:theList.
self startRevisionTask]
!
isHierarchicalItemSelectable: anIndex
|theSelectionIndexColl theSelectionIndexSize theSelectedItem|
"nur eine Revision kann selektiert werden"
(theSelectedItem := self hierarchicalListItemForSelectionIndex: anIndex) isRevisionItem
ifFalse:[^false].
"ist keine selektiert ist alles ok -> mit true zurueck"
(theSelectionIndexColl := self hierarchicalListSelectionIndexColl) size == 0
ifTrue:[^true].
"wurde deselektiert"
(self window sensor ctrlDown)
ifTrue: [
"ist eine Rev selektiert und die Klassen sind nicht gleich, dann falsch"
(self hierarchicalListItemForSelectionIndex:theSelectionIndexColl first) parent myClass == theSelectedItem parent myClass
ifFalse:[^false].
theSelectionIndexColl size ~~ 2
ifTrue:[^true].
(theSelectionIndexColl includes:anIndex)
ifTrue: [^true]
ifFalse:[self hierarchicalListSelectionIndexColl:(Array with:theSelectionIndexColl first).
^true]]
ifFalse:[
(theSelectionIndexColl size == 2)
ifTrue:[self hierarchicalListSelectionIndexColl:(Array with:anIndex)].
^true]
!
menuActionCompareChanges
|theSelectionIndexColl theFirstRevisionItem theSecondRevisionItem|
theSelectionIndexColl := self hierarchicalListSelectionIndexColl.
theFirstRevisionItem := self hierarchicalListItemForSelectionIndex:theSelectionIndexColl first.
theSecondRevisionItem := self hierarchicalListItemForSelectionIndex:theSelectionIndexColl last.
self selectionHolder notNil
ifTrue:[self selectionHolder value:(Array with:theFirstRevisionItem with:theSecondRevisionItem)]
!
selectHierarchicalItemMenu
"
<return: Block>
"
^[|menu|
self checkIfTwoResourceItemsSelected
ifFalse:[menu := nil]
ifTrue: [menu := Menu new fromLiteralArrayEncoding:(self class resourceItemMenu).
menu receiver:self].
menu
]
! !
!ClassRevisionTree methodsFor:'aspects'!
hierarchicalItemList
"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 it in the browser."
^ self hierarchicalItemListModel root
!
hierarchicalItemListModel
"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 it in the browser."
|holder|
(holder := builder bindingAt:#hierarchicalItemListModel) isNil ifTrue:[
holder := HierarchicalList new.
holder root:(ClassItemRoot new).
holder showRoot:false.
builder aspectAt:#hierarchicalItemListModel put:holder.
holder application:self.
].
^ holder.
!
hierarchicalItemSelectionAspect
"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 it in the browser."
|holder|
(holder := builder bindingAt:#hierarchicalItemSelectionAspect) isNil ifTrue:[
holder := ValueHolder new.
builder aspectAt:#hierarchicalItemSelectionAspect put:holder.
holder addDependent: self.
].
^ holder.
!
icons
|icons|
icons := Dictionary new.
icons at:#loadedRevision put:Icon leftIcon.
icons at:#notLoadedRevision put:Icon rightIcon.
^icons
! !
!ClassRevisionTree methodsFor:'interface opening'!
postOpenWith: aBuilder
super postOpenWith: aBuilder.
self hierarchicalItemList expand.
!
release
self stopRevisionTask.
^super release
! !
!ClassRevisionTree methodsFor:'private'!
computeChildrenForClassItem:aClassItem
|theRevisionLog|
theRevisionLog := self computeRevisionInfoForClassItem:aClassItem.
aClassItem setChildrensForRevisionInfo:theRevisionLog
!
computeRevisionInfoForClassItem:aClassItem
|theClass theSourceCodeManager|
theClass := aClassItem myClass.
theSourceCodeManager:=theClass sourceCodeManager.
^theSourceCodeManager revisionLogOf:theClass.
!
revisionTaskCycle
|theClassItem|
[
theClassItem := nil.
self semaphoreCritical critical:[
self revisionInfoList notEmpty
ifTrue:[theClassItem := self revisionInfoList remove:(self revisionInfoList last) ifAbsent:[nil]]
].
theClassItem notNil ifTrue:[
theClassItem isExpanded
ifTrue: [currentClassItemInTask:=theClassItem.
self computeChildrenForClassItem:theClassItem]
ifFalse:[currentClassItemInTask:=nil]
].
theClassItem notNil
] whileTrue.
!
startRevisionTask
self semaphoreCritical critical:[
revisionTask ifNil:[
revisionTask := Process for:[
self revisionTaskCycle
]
priority:(Processor userBackgroundPriority).
revisionTask addExitAction:[revisionTask := nil].
revisionTask resume.
].
].
!
stopRevisionTask
|task|
self semaphoreCritical critical:[
(task := revisionTask) notNil ifTrue:[
revisionTask := nil.
Exception handle:[:ex|] do:[
task terminateWithAllSubprocesses.
task waitUntilTerminated.
]
]
].
! !
!ClassRevisionTree methodsFor:'setup'!
setupOnClasses:aClassColl withSelectionHolder:aValueHolder
|theClassItemColl|
theClassItemColl := aClassColl collect:[:eachClass |
|theClassItem theClass|
theClassItem := ClassItem new.
theClass := Smalltalk resolveName:eachClass inClass:Smalltalk.
theClassItem myClass:theClass.
theClassItem].
self hierarchicalItemList addAll: theClassItemColl.
self selectionHolder:aValueHolder.
"
|theTree|
theTree := ClassRevisionTree new.
theTree open.
theTree setupOnClasses:#(VersionDiffBrowser HierarchicalVersionDiffBrowser SourceRevisionItem Project) withSelectionHolder:nil.
"
! !
!ClassRevisionTree methodsFor:'testing'!
checkIfTwoResourceItemsSelected
|theSelectionIndexColl|
((theSelectionIndexColl := self hierarchicalListSelectionIndexColl) isNil or:
[theSelectionIndexColl size ~~ 2])
ifTrue:[^false].
^((self hierarchicalListItemForSelectionIndex:theSelectionIndexColl first) isRevisionItem
and:[(self hierarchicalListItemForSelectionIndex:theSelectionIndexColl last) isRevisionItem])
! !
!ClassRevisionTree class methodsFor:'documentation'!
version
^ '$Header: /cvs/stx/stx/libtool/ClassRevisionTree.st,v 1.1 1999-12-29 15:32:17 ps Exp $'
! !