"{ Package: 'stx:libtool' }"
"{ NameSpace: Tools }"
NavigatorModel subclass:#BrowserList
instanceVariableNames:'menuHolder inGeneratorHolder outGeneratorHolder
selectionChangeCondition immediateUpdate doubleClickChannel
filter updateTrigger forceGeneratorTrigger hideUnloadedClasses
showClassPackages selectionHolder packageFilter nameSpaceFilter
organizerMode slaveMode listValid pseudoListLabelHolder icons
sortBy'
classVariableNames:'SynchronousUpdate Icons'
poolDictionaries:''
category:'Interface-Browsers-New'
!
!BrowserList class methodsFor:'documentation'!
documentation
"
embeddable application displaying the class-categories.
Provides an outputGenerator, which enumerates the classes in
the selected categories.
[author:]
Claus Gittinger (cg@exept.de)
"
! !
!BrowserList class methodsFor:'image specs'!
nameSpaceIcon
^ SystemBrowser nameSpaceIcon
!
packageIcon
^ SystemBrowser packageIcon
!
padLockBlueMiniIcon
^ SystemBrowser padLockBlueMiniIcon
!
padLockGrayMiniIcon
^ SystemBrowser padLockGrayMiniIcon
!
padLockGreenMiniIcon
^ SystemBrowser padLockGreenMiniIcon
!
padLockRedMiniIcon
^ SystemBrowser padLockRedMiniIcon
!
programImageIcon
^ SystemBrowser programImageIcon
!
protectedMethod
^ self padLockRedMiniIcon
!
redLockIcon
^ SystemBrowser redLockIcon
! !
!BrowserList methodsFor:'aspects'!
defaultSlaveModeValue
^ nil.
"Created: / 25.2.2000 / 22:36:40 / cg"
!
doubleClickChannel
doubleClickChannel isNil ifTrue:[
doubleClickChannel := TriggerValue new.
].
^ doubleClickChannel.
"Modified: / 31.1.2000 / 00:42:44 / cg"
"Created: / 5.2.2000 / 22:38:32 / cg"
!
doubleClickChannel:aChannel
doubleClickChannel := aChannel
!
filter:aValueHolder
filter notNil ifTrue:[
filter removeDependent:self
].
filter := aValueHolder.
filter notNil ifTrue:[
filter addDependent:self
].
"Modified: / 4.2.2000 / 23:29:30 / cg"
"Created: / 5.2.2000 / 13:42:12 / cg"
!
forceGeneratorTrigger
forceGeneratorTrigger isNil ifTrue:[
forceGeneratorTrigger := TriggerValue new.
forceGeneratorTrigger addDependent:self.
].
^ forceGeneratorTrigger.
"Modified: / 18.2.2000 / 02:02:52 / cg"
"Created: / 18.2.2000 / 02:46:40 / cg"
!
forceGeneratorTrigger:aTriggerValue
forceGeneratorTrigger notNil ifTrue:[
forceGeneratorTrigger removeDependent:self
].
forceGeneratorTrigger := aTriggerValue.
forceGeneratorTrigger notNil ifTrue:[
forceGeneratorTrigger addDependent:self
].
"Modified: / 4.2.2000 / 23:29:30 / cg"
"Created: / 18.2.2000 / 02:46:52 / cg"
!
hideUnloadedClasses
hideUnloadedClasses isNil ifTrue:[
hideUnloadedClasses := false asValue.
hideUnloadedClasses addDependent:self.
].
^ hideUnloadedClasses.
"Modified: / 18.2.2000 / 02:02:52 / cg"
"Created: / 18.2.2000 / 17:36:30 / cg"
!
hideUnloadedClasses:aValueHolder
hideUnloadedClasses notNil ifTrue:[
hideUnloadedClasses removeDependent:self
].
hideUnloadedClasses := aValueHolder.
hideUnloadedClasses notNil ifTrue:[
hideUnloadedClasses addDependent:self
].
"Modified: / 4.2.2000 / 23:29:30 / cg"
"Created: / 18.2.2000 / 17:46:36 / cg"
!
menuHolder
^ menuHolder
"Created: / 5.2.2000 / 13:42:06 / cg"
!
menuHolder:aValueHolder
menuHolder := aValueHolder.
"Created: / 5.2.2000 / 13:42:06 / cg"
!
nameSpaceFilter
nameSpaceFilter isNil ifTrue:[
nameSpaceFilter := ValueHolder new.
nameSpaceFilter addDependent:self.
].
^ nameSpaceFilter.
"Modified: / 24.2.2000 / 23:57:13 / cg"
"Created: / 18.8.2000 / 14:18:56 / cg"
!
nameSpaceFilter:aValueHolder
nameSpaceFilter notNil ifTrue:[
nameSpaceFilter removeDependent:self
].
nameSpaceFilter := aValueHolder.
nameSpaceFilter notNil ifTrue:[
nameSpaceFilter addDependent:self
].
"Modified: / 24.2.2000 / 23:56:22 / cg"
"Created: / 18.8.2000 / 14:19:06 / cg"
!
organizerMode
organizerMode isNil ifTrue:[
organizerMode := #category asValue.
organizerMode addDependent:self.
].
^ organizerMode
"Modified: / 31.1.2000 / 00:51:06 / cg"
"Created: / 25.2.2000 / 22:36:15 / cg"
!
organizerMode:aValueHolder
organizerMode notNil ifTrue:[
organizerMode removeDependent:self
].
organizerMode := aValueHolder.
organizerMode notNil ifTrue:[
organizerMode addDependent:self
].
"Modified: / 4.2.2000 / 23:34:28 / cg"
"Created: / 25.2.2000 / 22:36:28 / cg"
!
packageFilter
packageFilter isNil ifTrue:[
packageFilter := ValueHolder new.
packageFilter addDependent:self.
"/ debug-check only
"/ packageFilter onChangeEvaluate:[packageFilter value isValueModel ifTrue:[self halt:'debug halt']].
].
^ packageFilter.
"Modified: / 18.8.2000 / 19:26:36 / cg"
!
packageFilter:aValueHolder
packageFilter notNil ifTrue:[
packageFilter removeDependent:self
].
packageFilter := aValueHolder.
packageFilter notNil ifTrue:[
packageFilter addDependent:self.
"/ debug-check only
"/ packageFilter onChangeEvaluate:[packageFilter value isValueModel ifTrue:[self halt:'debug halt']].
].
"Modified: / 18.8.2000 / 19:26:40 / cg"
!
pseudoListLabelHolder
pseudoListLabelHolder isNil ifTrue:[
pseudoListLabelHolder := '' asValue.
].
^ pseudoListLabelHolder
!
selectionChangeCondition:aBlockOrValueHolder
selectionChangeCondition := aBlockOrValueHolder
!
selectionHolder
selectionHolder isNil ifTrue:[
selectionHolder := ValueHolder new.
selectionHolder addDependent:self
].
^ selectionHolder.
!
selectionHolder:aValueHolder
|prevSelection|
prevSelection := selectionHolder value ? #().
selectionHolder notNil ifTrue:[
selectionHolder removeDependent:self
].
selectionHolder := aValueHolder.
selectionHolder notNil ifTrue:[
selectionHolder addDependent:self
].
(selectionHolder value ? #()) ~= prevSelection ifTrue:[
"/ update
self update:#value with:nil from:selectionHolder
].
!
showClassPackages
showClassPackages isNil ifTrue:[
showClassPackages := false asValue.
showClassPackages addDependent:self.
].
^ showClassPackages.
"Modified: / 18.2.2000 / 02:02:52 / cg"
"Created: / 18.2.2000 / 17:36:30 / cg"
!
showClassPackages:aValueHolder
showClassPackages notNil ifTrue:[
showClassPackages removeDependent:self
].
showClassPackages := aValueHolder.
showClassPackages notNil ifTrue:[
showClassPackages addDependent:self
].
!
slaveMode
slaveMode isNil ifTrue:[
slaveMode := self defaultSlaveModeValue asValue.
slaveMode addDependent:self.
].
^ slaveMode.
"Created: / 25.2.2000 / 22:36:40 / cg"
!
slaveMode:aValueHolder
|prev|
slaveMode notNil ifTrue:[
slaveMode removeDependent:self.
prev := slaveMode value.
].
slaveMode := aValueHolder.
slaveMode notNil ifTrue:[
slaveMode addDependent:self
].
prev ~~ slaveMode value ifTrue:[
(prev isNil and:[slaveMode value]) ifFalse:[
self update:#value with:nil from:slaveMode.
]
].
!
sortBy
sortBy isNil ifTrue:[
sortBy := nil asValue.
sortBy addDependent:self.
].
^ sortBy.
"Created: / 25.2.2000 / 22:36:40 / cg"
!
sortBy:aValueHolder
|prev|
prev := sortBy value.
sortBy notNil ifTrue:[
sortBy removeDependent:self
].
sortBy := aValueHolder.
sortBy notNil ifTrue:[
sortBy addDependent:self
].
prev ~~ sortBy value ifTrue:[
self update:#value with:nil from:sortBy.
].
"Modified: / 4.2.2000 / 23:29:30 / cg"
"Created: / 5.2.2000 / 13:42:12 / cg"
!
updateTrigger
updateTrigger isNil ifTrue:[
updateTrigger := TriggerValue new.
updateTrigger addDependent:self.
].
^ updateTrigger.
"Created: / 18.2.2000 / 01:59:58 / cg"
"Modified: / 18.2.2000 / 02:02:52 / cg"
!
updateTrigger:aTriggerValue
updateTrigger notNil ifTrue:[
updateTrigger removeDependent:self
].
updateTrigger := aTriggerValue.
updateTrigger notNil ifTrue:[
updateTrigger addDependent:self
].
"Modified: / 4.2.2000 / 23:29:30 / cg"
"Created: / 18.2.2000 / 02:03:15 / cg"
! !
!BrowserList methodsFor:'change & update'!
delayedUpdate:something with:aParameter from:changedObject
"/ if any of my subclasses want those, they should look for them.
changedObject == Smalltalk ifTrue:[
(something == #Language or:[something == #LanguageTerritory]) ifTrue:[
^ self
].
something == #organization ifTrue:[
^ self
].
something == #classDefinition ifTrue:[
^ self
].
something == #classVariables ifTrue:[
^ self
].
something == #methodTrap ifTrue:[
^ self
].
something == #methodInClassRemoved ifTrue:[
^ self.
].
something == #methodDictionary ifTrue:[
^ self
].
something == #newClass ifTrue:[
^ self
].
].
changedObject == slaveMode ifTrue:[
slaveMode value ~~ true ifTrue:[
listValid ~~ true ifTrue:[
self updateList.
].
self updateOutputGenerator.
].
^ self.
].
changedObject == selectionHolder ifTrue:[
listValid ifFalse:[
self updateList.
].
^ self selectionChanged
].
changedObject == forceGeneratorTrigger ifTrue:[
self updateOutputGenerator.
^ self.
].
changedObject == hideUnloadedClasses ifTrue:[
self invalidateList.
slaveMode value ~~ true ifTrue:[
self updateOutputGenerator.
].
^ self.
].
changedObject == updateTrigger ifTrue:[
self enqueueDelayedUpdateList.
^ self
].
changedObject == inGeneratorHolder ifTrue:[
self invalidateList.
^ self
].
"/ changedObject == outGeneratorHolder ifTrue:[
"/ self enqueueDelayedUpdateList.
"/ ^ self
"/ ].
changedObject == packageFilter ifTrue:[
self invalidateList.
^ self
].
changedObject == nameSpaceFilter ifTrue:[
self invalidateList.
^ self
].
changedObject == organizerMode ifTrue:[
^ self
].
self invalidateList.
^ self
"Created: / 5.2.2000 / 13:42:06 / cg"
"Modified: / 18.8.2000 / 14:19:24 / cg"
!
enqueueDelayedUpdate:something with:aParameter from:changedObject
"support for delayed updates - to be invoked from a concrete classes
#update:with:from: method.
This will enqueue a delayed update, and resend #delayedUpdate:with:from:
whenever the receiver is handling events.
Especially useful, if many updates arrive at high frequency, to avoid
multiple redraws."
^ self
enqueueMessage:#delayedUpdate:with:from:
for:self
arguments:(Array
with:something
with:aParameter
with:changedObject).
!
enqueueDelayedUpdateList
(NewSystemBrowser synchronousUpdate == true
or:[ immediateUpdate value == true ])
ifTrue:[
self updateList.
^ self.
].
self enqueueMessage:#updateList for:self arguments:#()
!
enqueueDelayedUpdateOutputGenerator
slaveMode value == true ifTrue:[
self halt:'should not be invoked'
].
(NewSystemBrowser synchronousUpdate == true
or:[ immediateUpdate value == true ])
ifTrue:[
self updateOutputGenerator.
^ self.
].
listValid := false.
self enqueueMessage:#updateOutputGenerator for:self arguments:#()
!
forceReselect
|selectionHolder prevSelection|
selectionHolder := self selectionHolder.
prevSelection := selectionHolder value.
selectionHolder setValue:nil.
selectionHolder value:prevSelection.
!
forceSelectionClear
self selectionHolder setValue:nil
!
forceUpdateList
|listView|
listView := builder componentAt:#List.
listView notNil ifTrue:[
listView list:#()
].
self updateList
!
immediateUpdate:aBooleanOrBooleanHolder
immediateUpdate := aBooleanOrBooleanHolder
"Created: / 13.2.2000 / 22:26:06 / cg"
"Modified: / 13.2.2000 / 22:28:09 / cg"
!
prioDelayedUpdate:something with:aParameter from:changedObject
Processor activeProcess withPriority:7 do:[
self delayedUpdate:something with:aParameter from:changedObject
]
!
selectionChangeAllowed
selectionChangeCondition isNil ifTrue:[^ true].
selectionChangeCondition isBlock ifTrue:[
selectionChangeCondition numArgs == 1 ifTrue:[
^ selectionChangeCondition value:self
]
].
^ selectionChangeCondition value
!
selectionChanged
slaveMode value ~~ true ifTrue:[
self enqueueDelayedUpdateOutputGenerator
"/ self updateOutputGenerator.
]
"Modified: / 4.2.2000 / 15:49:23 / cg"
"Created: / 5.2.2000 / 13:42:07 / cg"
!
selectionChangedByClick
"Created: / 25.2.2000 / 21:19:25 / cg"
!
syncDelayedUpdateList
|sensor|
sensor := self window sensor.
sensor isNil ifTrue:[
^ self
].
"/
"/ if an update is in the queue, process it.
"/
(sensor
hasEvent:#updateList
for:self
withArguments:#()
) ifTrue:[
sensor flushEventsFor:self withType:#updateList.
self updateList.
^ self
].
!
update:something with:aParameter from:changedObject
(NewSystemBrowser synchronousUpdate == true
or:[ immediateUpdate value == true ])
ifTrue:[
self delayedUpdate:something with:aParameter from:changedObject.
^ self.
].
"/ (changedObject == ChangeSet)
"/ ifTrue:[
"/ self delayedUpdate:something with:aParameter from:changedObject.
"/ ^ self.
"/ ].
"/ changedObject == selectionHolder ifTrue:[
"/ listValid ifFalse:[
"/ self slaveMode value ifTrue:[
"/ ^ self
"/ ]
"/ ]
"/ ].
changedObject == inGeneratorHolder ifTrue:[
listValid := false.
].
self enqueueDelayedUpdate:something with:aParameter from:changedObject.
"Created: / 5.2.2000 / 13:42:07 / cg"
"Modified: / 13.11.2001 / 11:30:19 / cg"
! !
!BrowserList methodsFor:'generators'!
inGeneratorHolder
^ inGeneratorHolder
"Created: / 5.2.2000 / 13:42:07 / cg"
!
inGeneratorHolder:aConditionBlockHolder
|prevHolder|
(prevHolder := inGeneratorHolder) notNil ifTrue:[
inGeneratorHolder removeDependent:self
].
inGeneratorHolder := aConditionBlockHolder.
inGeneratorHolder notNil ifTrue:[
inGeneratorHolder addDependent:self
].
(prevHolder isNil and:[inGeneratorHolder isNil]) ifFalse:[
(prevHolder value isNil
and:[
(inGeneratorHolder value isNil
or:[inGeneratorHolder value isArray
and:[inGeneratorHolder value size == 0]])])
ifFalse:[
self update:#value with:nil from:inGeneratorHolder
].
].
!
makeGenerator
self subclassResponsibility
"Created: / 5.2.2000 / 13:42:07 / cg"
!
outGeneratorHolder
outGeneratorHolder isNil ifTrue:[
outGeneratorHolder := ValueHolder new
].
^ outGeneratorHolder
"Modified: / 4.2.2000 / 17:17:16 / cg"
"Created: / 5.2.2000 / 13:42:07 / cg"
!
outGeneratorHolder:aConditionBlockHolder
outGeneratorHolder := aConditionBlockHolder.
"Created: / 5.2.2000 / 13:42:08 / cg"
!
updateOutputGenerator
"create a generator which enumerates my elements,
and place it into the outputGenerator holder"
self outGeneratorHolder value: self makeGenerator.
"Modified: / 4.2.2000 / 17:16:34 / cg"
"Created: / 5.2.2000 / 13:42:08 / cg"
! !
!BrowserList methodsFor:'icons'!
abstractMethodIcon
"answer an icon to mark abstract methods"
^ self fetchIcon:#abstractMethod selector:#abstractMethodIcon
!
canvasIcon
"answer an icon to mark canvas spec methods"
^ self fetchIcon:#canvas selector:#canvasIcon
!
fetchIcon:name selector:fetchSelector
"answer an icon to mark breakPointed methods"
icons isNil ifTrue:[icons := IdentityDictionary new].
Icons isNil ifTrue:[Icons := IdentityDictionary new].
^ icons at:name ifAbsentPut:[
|fh icn h|
(icn := Icons at:name ifAbsent:nil) isNil ifTrue: [
Icons at:name put:(icn := (SystemBrowser perform:fetchSelector) onDevice:Display).
icn clearMaskedPixels.
].
h := icn height.
h > (fh := SelectionInListView defaultFont heightOn:device) ifTrue:[
icn := icn magnifiedBy:(fh / h)
].
icn onDevice:device
]
"
Icons := nil
Icon flushCachedIcons
"
!
fileImageIcon
"answer an icon to mark file-image spec methods"
^ self fetchIcon:#fileImage selector:#fileImageIcon
!
helpIcon
"answer an icon to mark help spec methods"
^ self fetchIcon:#help selector:#helpIcon
!
hierarchicalListIcon
"answer an icon to mark hierarchicalList spec methods"
^ self fetchIcon:#hierarchicalList selector:#hierarchicalListIcon
!
imageIcon
"answer an icon to mark image spec methods"
^ self fetchIcon:#image selector:#imageIcon
!
menuIcon
"answer an icon to mark menu spec methods"
^ self fetchIcon:#menu selector:#menuIcon
!
methodEmptyInheritedIcon
^ self fetchIcon:#methodEmptyInherited selector:#methodEmptyInheritedIcon
!
methodInheritedFromAboveAndRedefinedBelowIcon
^ self fetchIcon:#methodInheritedFromAboveAndRedefinedBelow selector:#methodInheritedFromAboveAndRedefinedBelowIcon
!
methodInheritedFromAboveIcon
^ self fetchIcon:#methodInheritedFromAbove selector:#methodInheritedFromAboveIcon
!
methodRedefinedBelowIcon
^ self fetchIcon:#methodRedefinedBelow selector:#methodRedefinedBelowIcon
!
privateMethodIcon
"answer an icon to mark private methods"
^ self fetchIcon:#privateMethod selector:#privateMethodIcon
!
programImageIcon
"answer an icon to mark image spec methods"
^ self fetchIcon:#programImage selector:#programImageIcon
!
programMenuIcon
"answer an icon to mark program generated menu methods"
^ self fetchIcon:#programMenu selector:#programMenuIcon
!
protectedMethodIcon
"answer an icon to mark protected methods"
^ self fetchIcon:#protectedMethod selector:#protectedMethodIcon
!
stopIcon
"answer an icon to mark breakPointed methods"
^ self fetchIcon:#stop selector:#stopIcon
!
tabListIcon
"answer an icon to mark tabList spec methods"
^ self fetchIcon:#tabList selector:#tabListIcon
!
tableColumnsIcon
"answer an icon to mark tableColumns spec methods"
^ self fetchIcon:#tableColumns selector:#tableColumnsIcon
!
timeIcon
"answer an icon to mark timed methods"
^ self fetchIcon:#time selector:#timeIcon
!
traceIcon
"answer an icon to mark traced methods"
"/ ^ self fetchIcon:#watch selector:#watchIcon
^ self fetchIcon:#trace selector:#traceIcon
! !
!BrowserList methodsFor:'misc'!
invalidateList
listValid := false.
slaveMode value ~~ true ifTrue:[
self enqueueDelayedUpdateList.
]
!
resources
|master|
(master := self masterApplication) notNil ifTrue:[^ master resources].
^ super resources
! !
!BrowserList methodsFor:'private'!
browserNameList
self subclassResponsibility
!
classesToProcessForClasses:classes withVisibility:visibility
|classesToProcess classesToProcessInOrder|
visibility isNil ifTrue:[^classes].
visibility == #class ifTrue:[^classes].
classesToProcess := IdentitySet new.
classesToProcessInOrder := OrderedCollection new.
classes notNil ifTrue:[
classes do:[:eachClass |
|withAllSupers|
withAllSupers := eachClass withAllSuperclasses.
visibility == #allButObject ifTrue:[
eachClass isMeta ifTrue:[
withAllSupers removeAllFoundIn:(Object class withAllSuperclasses)
] ifFalse:[
withAllSupers remove:Object ifAbsent:nil
]
].
withAllSupers do:[:each |
(classesToProcess includes:each) ifFalse:[
classesToProcess add:each.
classesToProcessInOrder add:each.
]
]
].
].
^ classesToProcessInOrder
!
colorizeForChangedCode:someString
^ someString asText emphasisAllAdd:(UserPreferences current emphasisForChangedCode)
"Created: / 31.10.2001 / 10:17:56 / cg"
!
colorizeForDifferentPackage:someString
^ someString asText emphasisAllAdd:(UserPreferences current emphasisForDifferentPackage)
!
colorizeGrey:someString
^ someString asText emphasisAllAdd:(#color->Color darkGrey)
!
emphasizeForChangedCode:someString
^ self colorizeForChangedCode:someString
"Modified: / 31.10.2001 / 10:18:57 / cg"
!
emphasizeForDifferentPackage:someString
^ self colorizeForDifferentPackage:(' [' , (' ' , someString , ' ') allItalic , ']')
"Modified: / 31.10.2001 / 10:13:35 / cg"
!
inSlaveModeOrInvisible
(self slaveMode value == true) ifTrue:[^ true].
"/ self slaveMode value isNil ifTrue:[
"/ self window shown ifFalse:[
"/ ^ true
"/ ].
"/ ].
^ false
!
isClass:aClass shownWithNameSpaceFilter:nameSpaceFilter
|nsName|
nameSpaceFilter isNil ifTrue:[^ true].
nsName := aClass topNameSpace name.
(nameSpaceFilter includes:nsName) ifTrue:[^ true].
(nameSpaceFilter contains:[:ns | nsName startsWith:(ns , '::')]) ifTrue:[^ true].
^ false
!
isClass:aClass shownWithPackageFilter:packageFilter
packageFilter isNil ifTrue:[^ true].
(packageFilter includes:aClass package) ifTrue:[^ true].
aClass instAndClassSelectorsAndMethodsDo:[:sel :mthd |
(packageFilter includes:mthd package) ifTrue:[^ true].
].
^ false
!
makeDependent
self subclassResponsibility
"Created: / 5.2.2000 / 13:42:08 / cg"
!
makeIndependent
self subclassResponsibility
"Created: / 5.2.2000 / 13:42:08 / cg"
!
release
self makeIndependent.
super release.
filter removeDependent:self.
forceGeneratorTrigger removeDependent:self.
hideUnloadedClasses removeDependent:self.
inGeneratorHolder removeDependent:self.
nameSpaceFilter removeDependent:self.
organizerMode removeDependent:self.
packageFilter removeDependent:self.
selectionHolder removeDependent:self.
showClassPackages removeDependent:self.
slaveMode removeDependent:self.
sortBy removeDependent:self.
updateTrigger removeDependent:self.
"Created: / 5.2.2000 / 13:42:09 / cg"
"Modified: / 13.2.2000 / 23:32:23 / cg"
!
releaseAsSubCanvas
self makeIndependent.
super releaseAsSubCanvas.
"Created: / 13.2.2000 / 23:11:29 / cg"
"Modified: / 13.2.2000 / 23:32:29 / cg"
!
updateList
self subclassResponsibility.
!
updateListFor:newList
"update the browsers list in a way which avoids scrolls
and flicker; returns true, if the newList is the same."
|"oldListSize newListSize" sameContents sameStrings oldEntry browserNameList
"firstDifferentFromBeginning firstDifferentFromEnd" listView prevMode sav|
browserNameList := self browserNameList value.
sameContents := sameStrings := (newList size == browserNameList size).
sameContents ifTrue:[
newList with:browserNameList do:[:newLine :oldLine |
sameStrings ifTrue:[
sameStrings := ((newLine ? '') = (oldLine ? '')).
].
sameContents ifTrue:[
((newLine ? '') sameStringAndEmphasisAs:(oldLine ? '')) ifFalse:[
sameContents := false
]
].
]
].
listView := builder componentAt:#List.
listView isNil ifTrue:[
"/ called early during setup ...
browserNameList contents:newList.
^ sameContents.
].
sameContents ifTrue:[
^ sameContents
].
sameStrings ifTrue:[
newList keysAndValuesDo:[:lineNr :line |
oldEntry := browserNameList at:lineNr.
(oldEntry sameStringAndEmphasisAs:line) ifFalse:[
browserNameList at:lineNr put:line.
]
].
^ sameContents
].
listView := listView scrolledView.
listView isNil ifTrue:[self halt. ^ self].
prevMode := listView scrollWhenUpdating.
listView scrollWhenUpdating:nil.
[
"/ dont want to be called if selection is changed by selListView
sav := listView action.
listView action:nil.
browserNameList contents:newList.
] ensure:[
listView action:sav.
].
listView scrollWhenUpdating:prevMode.
^ sameContents.
"/ oldListSize := browserNameList size.
"/ newListSize := newList size.
"/ newListSize == 0 ifTrue:[
"/ oldListSize == 0 ifTrue:[
"/ ^ true "/ same
"/ ].
"/ browserNameList removeAll.
"/ ^ false "/ not same
"/ ].
"/
"/ oldListSize == 0 ifTrue:[
"/ browserNameList contents:newList.
"/ ^ false. "/ not same
"/ ].
"/
"/ (newListSize between:(oldListSize-1) and:(oldListSize+1)) ifTrue:[
"/ "/ individually exchange changed lines, to avoid flicker.
"/ "/ the old code was: self browserNameList value:newList
"/ "/ but if only a single method is changed (or an instrumentation icon changes),
"/ "/ this results in avoidable flicker.
"/
"/ newListSize > oldListSize ifTrue:[
"/ "/ an entry seems to be added
"/ "/ try to find it.
"/ firstDifferentFromBeginning := 1.
"/
"/ [firstDifferentFromBeginning <= oldListSize
"/ and:[(newList at:firstDifferentFromBeginning) sameStringAndEmphasisAs: (browserNameList at:firstDifferentFromBeginning)]]
"/ whileTrue:[
"/ firstDifferentFromBeginning := firstDifferentFromBeginning + 1.
"/ ].
"/ firstDifferentFromEnd := newListSize.
"/ [firstDifferentFromEnd >= 1
"/ and:[(newList at:firstDifferentFromEnd) sameStringAndEmphasisAs: (browserNameList at:firstDifferentFromEnd-1)]]
"/ whileTrue:[
"/ firstDifferentFromEnd := firstDifferentFromEnd - 1.
"/ ].
"/ (firstDifferentFromEnd - firstDifferentFromBeginning) > (newList size // 10) ifTrue:[
"/ "/ too many differences - exchange the list en-bloque
"/ browserNameList contents:newList.
"/ ^ false. "/ not same
"/ ].
"/ "/ entries from firstDifferentFromBeginning to firstDifferentFromEnd in newList are different
"/
"/ (firstDifferentFromEnd - firstDifferentFromBeginning + 1 "number of different items") == (newListSize - oldListSize) ifTrue:[
"/ "/ for now, only handle single-added-item case
"/ firstDifferentFromEnd ~~ firstDifferentFromBeginning ifTrue:[
"/ self halt
"/ ].
"/
"/ "/ item at firstDifferentFromBeginning has been inserted.
"/ browserNameList add:(newList at:firstDifferentFromBeginning) beforeIndex:firstDifferentFromEnd.
"/ ^ false "/ not the same
"/ ].
"/ ] ifFalse:[
"/ newListSize < oldListSize ifTrue:[
"/ "/ an entry seems to be removed
"/ "/ try to find it.
"/ firstDifferentFromBeginning := 1.
"/
"/ [firstDifferentFromBeginning <= newListSize
"/ and:[(newList at:firstDifferentFromBeginning) sameStringAndEmphasisAs: (browserNameList at:firstDifferentFromBeginning)]]
"/ whileTrue:[
"/ firstDifferentFromBeginning := firstDifferentFromBeginning + 1.
"/ ].
"/ firstDifferentFromEnd := newListSize.
"/ [firstDifferentFromEnd >= 1
"/ and:[(newList at:firstDifferentFromEnd) sameStringAndEmphasisAs: (browserNameList at:firstDifferentFromEnd+1)]]
"/ whileTrue:[
"/ firstDifferentFromEnd := firstDifferentFromEnd - 1.
"/ ].
"/ (firstDifferentFromEnd - firstDifferentFromBeginning) > (newList size // 10) ifTrue:[
"/ "/ too many differences - exchange the list en-bloque
"/ browserNameList contents:newList.
"/ ^ false. "/ not same
"/ ].
"/ "/ entries from firstDifferentFromBeginning to firstDifferentFromEnd in newList are different
"/
"/ (firstDifferentFromBeginning - firstDifferentFromEnd) == (oldListSize - newListSize) ifTrue:[
"/ "/ for now, only handle single-removed-item case
"/ firstDifferentFromEnd ~~ (firstDifferentFromBeginning-1) ifTrue:[self halt].
"/
"/ "/ item at firstDifferentFromBeginning has been removed.
"/ browserNameList removeFromIndex:firstDifferentFromBeginning toIndex:firstDifferentFromBeginning.
"/ ^ false "/ not the same
"/ ].
"/ ]
"/ ].
"/
"/ sameContents := true.
"/ newList keysAndValuesDo:[:lineNr :line |
"/ lineNr > browserNameList size ifTrue:[
"/ browserNameList add:line.
"/ sameContents := false.
"/ ] ifFalse:[
"/ oldEntry := browserNameList at:lineNr.
"/ (oldEntry ~= line
"/ or:[(oldEntry sameStringAndEmphasisAs:line) not]) ifTrue:[
"/ browserNameList at:lineNr put:line.
"/ sameContents := false.
"/ ]
"/ ]
"/ ].
"/ newList size < browserNameList size ifTrue:[
"/ browserNameList removeFromIndex:(newList size + 1) toIndex:(browserNameList size).
"/ sameContents := false.
"/ ].
"/ ^ sameContents
"/ ].
"/
"/ browserNameList contents:newList.
"/ ^ false "/ not the same
! !
!BrowserList methodsFor:'setup'!
commonPostBuildWith:aBuilder
|list|
self slaveMode value == true ifFalse:[
self updateList.
] ifTrue:[
self invalidateList
].
self makeDependent.
list := aBuilder componentAt:#List.
list notNil ifTrue:[
list selectConditionBlock:[:item | self selectionChangeAllowed].
list ignoreReselect:false.
].
"Modified: / 13.11.2001 / 10:27:49 / cg"
!
postBuildAsSubcanvasWith:aBuilder
self commonPostBuildWith:aBuilder.
super postBuildAsSubcanvasWith:aBuilder.
!
postBuildWith:aBuilder
self commonPostBuildWith:aBuilder.
super postBuildWith:aBuilder.
"Modified: / 4.2.2000 / 22:59:45 / cg"
"Created: / 5.2.2000 / 13:42:09 / cg"
! !
!BrowserList class methodsFor:'documentation'!
version
^ '$Header: /cvs/stx/stx/libtool/Tools_BrowserList.st,v 1.2 2004-02-26 20:07:57 cg Exp $'
! !