cg@809: " cg@809: COPYRIGHT (c) 1997 by eXept Software AG cg@2621: All Rights Reserved cg@809: cg@809: This software is furnished under a license and may be used cg@809: only in accordance with the terms of that license and with the cg@809: inclusion of the above copyright notice. This software may not cg@809: be provided or otherwise made available to, or used by, any cg@809: other person. No title to or ownership of the software is cg@809: hereby transferred. cg@809: " cg@809: cg@809: cg@2621: "{ NameSpace: Tools }" ca@33: cg@1213: Object subclass:#NewInspectorList ca@33: instanceVariableNames:'inspectedObject instanceNames instanceTypes selection' ca@33: classVariableNames:'' ca@33: poolDictionaries:'' cg@1213: category:'Interface-NewInspector' ca@33: ! ca@33: cg@1213: !NewInspectorList class methodsFor:'documentation'! cg@809: cg@809: copyright cg@809: " cg@809: COPYRIGHT (c) 1997 by eXept Software AG cg@2621: All Rights Reserved cg@809: cg@809: This software is furnished under a license and may be used cg@809: only in accordance with the terms of that license and with the cg@809: inclusion of the above copyright notice. This software may not cg@809: be provided or otherwise made available to, or used by, any cg@809: other person. No title to or ownership of the software is cg@809: hereby transferred. cg@809: " cg@809: cg@809: ! ! ca@33: cg@1213: !NewInspectorList class methodsFor:'instance creation'! ca@33: ca@33: for:anObject ca@33: "create a new list for an instance ca@33: " ca@38: ^ self new inspect:anObject ca@38: ca@38: ca@38: ! ca@38: ca@38: new ca@38: "create a new instance and set the inspected object to nil ca@38: " ca@38: ^ self basicNew initialize. ca@38: ca@38: ! ! ca@38: cg@1213: !NewInspectorList class methodsFor:'helpers'! ca@38: ca@38: asString:aCollection ca@38: "converts any collection to a string seperated by spaces. If ca@38: the collection is empty or nil, nil is returned otherwise a ca@38: string. ca@38: " ca@38: |string| ca@38: ca@38: aCollection isCollection ifTrue:[ cg@2621: aCollection isString ifTrue:[ cg@2621: string := aCollection cg@2621: ] ifFalse:[ cg@2621: string := aCollection asStringWith:Character space cg@2621: from:1 to:(aCollection size) cg@2621: compressTabs:true cg@2621: final:nil cg@2621: ]. cg@2621: string := string withoutSeparators. ca@38: cg@2621: string notEmpty ifTrue:[ cg@2621: ^ string cg@2621: ] ca@38: ]. ca@38: ^ nil ca@33: ca@33: ca@33: ! ! ca@33: cg@1213: !NewInspectorList class methodsFor:'testing'! ca@33: ca@33: isDirectory:anInstance ca@38: "returns true if the instance is a directory ca@33: " ca@33: |cls| ca@33: ca@33: anInstance notNil ifTrue:[ cg@2621: cls := anInstance class. ca@33: cg@2621: cls == Character ifTrue:[ ^ false ]. cg@2621: cls == Symbol ifTrue:[ ^ false ]. cg@2621: cls == String ifTrue:[ ^ false ]. cg@2621: cls == Float ifTrue:[ ^ false ]. cg@2621: cls == ShortFloat ifTrue:[ ^ false ]. ca@33: cg@2621: cls allInstVarNames notEmpty ifTrue:[ cg@2621: ^ true cg@2621: ]. ca@33: cg@2621: anInstance isVariable ifTrue:[ cg@2621: ^ true cg@2621: ]. ca@33: ]. ca@33: ^ false ca@33: cg@1022: "Modified: / 4.2.1999 / 20:00:11 / cg" ca@38: ! ca@38: ca@38: isTraceable:anInstance ca@38: "returns true if the instance could be traced or traped ca@38: " ca@38: |cls| ca@38: ca@38: anInstance notNil ifTrue:[ cg@2621: cls := anInstance class. ca@38: ca@38: ^ ( cls ~~ True cg@2621: and:[cls ~~ False cg@2621: and:[cls ~~ SmallInteger]] cg@2621: ) ca@38: ]. ca@38: ^ false. ca@38: ca@33: ! ! ca@33: cg@1213: !NewInspectorList methodsFor:'accessing'! ca@33: ca@33: includesSelf:aBoolean ca@33: "includes 'self' dependant on the boolean ca@33: " ca@33: (self includesSelf) ~~ aBoolean ifTrue:[ cg@2621: aBoolean ifTrue:[ cg@2621: instanceNames addFirst:'self'. cg@2621: instanceTypes addFirst:#self. ca@33: cg@2621: selection notNil ifTrue:[selection := selection + 1] cg@2621: ifFalse:[selection := 1] ca@38: cg@2621: ] ifFalse:[ cg@2621: instanceNames removeFirst. cg@2621: instanceTypes removeFirst. ca@33: cg@2621: selection isNil ifFalse:[ cg@2621: (selection := selection - 1) == 0 ifTrue:[ cg@2621: selection := nil cg@2621: ] cg@2621: ] cg@2621: ] ca@33: ] ca@33: ca@33: ca@33: ! ca@33: ca@38: list ca@38: "returns self ca@38: " ca@38: ^ self ca@38: ! ca@38: ca@33: size ca@38: "returns size of list ca@33: " ca@33: ^ instanceNames size ca@33: ca@38: ! ca@38: ca@38: update ca@38: "update list contents ca@38: " ca@38: |start stop size| ca@38: ca@38: inspectedObject isVariable ifTrue:[ cg@2621: start := instanceNames findFirst:[:el|(el at:1) isDigit]. cg@2621: stop := instanceTypes size. ca@38: cg@2621: start == 0 ifTrue:[ cg@2621: size := stop + 10. "must be > 1: force a resize the first time" cg@2621: ] ifFalse:[ cg@2621: instanceTypes last ~~ #grow ifTrue:[size := stop] cg@2621: ifFalse:[size := stop-1]. ca@38: cg@2621: instanceTypes removeFromIndex:start toIndex:stop. cg@2621: instanceNames removeFromIndex:start toIndex:stop. cg@2621: ]. cg@2621: self resizeTo:size. ca@38: ] cg@1022: cg@1022: "Modified: / 4.2.1999 / 20:00:38 / cg" ca@33: ! ! ca@33: cg@1213: !NewInspectorList methodsFor:'accessing contents'! ca@33: ca@33: inspectedObject ca@33: "returns current inspected object ca@33: " ca@33: ^ inspectedObject ca@33: ca@33: ca@33: ! ca@33: ca@33: instanceNames ca@33: "returns list of instance names ca@33: " ca@33: ^ instanceNames ca@33: ca@33: ca@33: ! ca@33: ca@33: instanceTypeAt:anIndex ca@38: "returns type assigned to the list entry (#directory #normal #self #grow) ca@38: In case of an invalid index nil is returned. ca@33: " ca@38: (anIndex isNil or:[anIndex > instanceTypes size]) ifFalse:[^ instanceTypes at:anIndex] cg@2621: ifTrue:[^ nil]. ca@33: ca@33: ca@33: ! ca@33: ca@33: instanceTypes ca@38: "returns list of types (#directory #normal #self #grow) ca@33: " ca@33: ^ instanceTypes ca@33: ca@33: ca@33: ! ca@33: ca@33: instanceVarAt:anIndex cg@2621: "returns the instnace variable assigned to the index or ca@38: nil in case of an invalid index. ca@33: " cg@327: |nm| ca@33: ca@38: (anIndex isNil or:[anIndex > instanceTypes size]) ifFalse:[ cg@2621: nm := instanceNames at:anIndex. ca@33: cg@2621: (nm at:1) isDigit ifFalse:[ cg@2621: self includesSelf ifFalse:[ cg@2621: ^ inspectedObject instVarAt:anIndex cg@2621: ]. cg@2621: anIndex == 1 ifFalse:[^ inspectedObject instVarAt:(anIndex-1)] cg@2621: ifTrue:[^ inspectedObject] cg@2621: ]. ca@33: ^ inspectedObject basicAt:(Number readFrom:nm onError:0) ca@33: ]. ca@33: ^ nil ca@33: ca@33: ca@33: ! ! ca@33: cg@1213: !NewInspectorList methodsFor:'initialization'! ca@33: ca@38: initialize ca@38: "initialize instance attributes ca@33: " ca@38: super initialize. ca@33: ca@38: instanceNames := OrderedCollection new. ca@38: instanceTypes := OrderedCollection new. ca@38: ca@33: ! ! ca@33: cg@1213: !NewInspectorList methodsFor:'private'! ca@33: ca@38: resizeTo:aNumber ca@38: "resize list to minimum aNumber ca@33: " ca@38: |lstVarId basicSize newLastId obj instSize| ca@33: ca@33: (inspectedObject isVariable and:[self class isDirectory:inspectedObject]) ifFalse:[ cg@2621: ^ self ca@33: ]. ca@33: ca@38: instanceTypes size == 0 ifTrue:[ cg@2621: lstVarId := 0 ca@38: ] ifFalse:[ cg@2621: instSize := inspectedObject class instSize. ca@33: cg@2621: instanceTypes first == #self ifTrue:[ cg@2621: instSize := instSize + 1 cg@2621: ]. cg@2621: instanceTypes last == #grow ifTrue:[ cg@2621: instanceNames removeLast. " .. " cg@2621: instanceTypes removeLast. " #grow " cg@2621: ]. cg@2621: lstVarId := instanceTypes size - instSize. ca@38: ]. ca@38: ca@38: (basicSize := inspectedObject basicSize) == lstVarId ifTrue:[ cg@2621: ^ self ca@38: ]. ca@38: newLastId := (1 bitShift:((aNumber-1) highBit)) max:128. ca@38: ca@38: (newLastId + 64) > basicSize ifTrue:[ cg@2621: newLastId := basicSize ca@33: ]. ca@33: ca@33: [lstVarId ~~ newLastId] whileTrue:[ cg@2621: lstVarId := lstVarId + 1. cg@2621: obj := inspectedObject basicAt:lstVarId. ca@33: cg@2621: (self class isDirectory:obj) ifTrue:[instanceTypes add:#directory] cg@2621: ifFalse:[instanceTypes add:#normal]. ca@33: cg@2621: instanceNames add:(lstVarId printString, ' ', obj class name printString). ca@33: ]. ca@33: ca@33: lstVarId ~~ basicSize ifTrue:[ cg@2621: instanceNames add:'..'. cg@2621: instanceTypes add:#grow ca@33: ]. ca@33: ! ! ca@33: cg@1213: !NewInspectorList methodsFor:'selections'! ca@33: ca@33: selectedInstanceType ca@38: "returns type assigned to the selected list entry (#directory #normal #self #grow). ca@38: In case of no selection nil is returned. ca@33: " ca@33: ^ self instanceTypeAt:selection ca@33: ca@33: ca@33: ! ca@33: ca@33: selectedInstanceVar ca@33: "returns current inspected instance variable or nil ca@33: " ca@33: ^ self instanceVarAt:selection ca@33: ca@33: ca@33: ! ca@33: ca@33: selection ca@33: "returns current selection number or nil ca@33: " ca@33: ^ selection ca@33: ca@33: ca@33: ! ca@33: ca@38: setSelection:aNrOrNil ca@38: "change current selection to a number or nil; may resize the lists ca@38: " ca@38: selection := aNrOrNil. ca@38: ca@38: (selection isNil or:[instanceTypes size > selection]) ifFalse:[ cg@2621: self resizeTo:selection. ca@38: cg@2621: selection > instanceTypes size ifTrue:[ cg@2621: selection := nil cg@2621: ] cg@2621: ] ca@38: ! ! ca@38: cg@1213: !NewInspectorList methodsFor:'testing'! ca@38: ca@38: includesSelf ca@38: "returns true if 'self' is included in the list ca@38: " ca@38: ^ (instanceTypes notEmpty and:[instanceTypes first == #self]) ca@38: ca@38: ca@38: ! ca@38: ca@38: isEmpty ca@38: "returns true if the list is empty ca@33: " ca@38: ^ instanceNames isEmpty ca@38: ca@38: ! ca@38: ca@38: notEmpty ca@38: "returns true if the list is not empty ca@38: " ca@38: ^ instanceNames notEmpty ca@38: ca@38: ! ! ca@38: cg@1213: !NewInspectorList methodsFor:'user interaction'! ca@38: ca@38: accept:aText notifying:aView ca@38: "evaluating aText on the selected instance var; if an error occurs #Error ca@38: is returned otherwise the inspected object instance. On success the list ca@38: will be updated. ca@38: " ca@38: |text slNr value| ca@38: ca@38: selection notNil ifTrue:[ cg@2621: text := self class asString:aText. ca@38: cg@2621: text notNil ifTrue:[ cg@2621: self includesSelf ifFalse:[slNr := selection] cg@2621: ifTrue:[slNr := selection-1]. ca@38: cg@2621: value := inspectedObject class evaluatorClass cg@2621: evaluate:text cg@2621: receiver:inspectedObject cg@2621: notifying:aView. ca@33: cg@2621: slNr ~~ 0 ifTrue:[ cg@2621: (inspectedObject class isVariable) ifFalse:[ cg@2621: inspectedObject instVarAt:slNr put:value cg@2621: ] ifTrue:[ cg@2621: slNr <= (inspectedObject class instSize) ifTrue:[ cg@2621: inspectedObject instVarAt:slNr put:value cg@2621: ] ifFalse:[ cg@2621: slNr := slNr - inspectedObject class instSize. cg@2621: inspectedObject basicAt:slNr put:value cg@2621: ] cg@2621: ] cg@2621: ]. cg@2621: inspectedObject changed. cg@2621: self update. cg@2621: ^ inspectedObject cg@2621: ] ca@38: ]. ca@38: ^ #Error ca@38: ! ca@38: ca@38: doIt:aCode notifying:aView ca@38: "evaluating aCode on the selected instance var; if an error occurs #Error ca@38: is returned otherwise the result returned from the evaluator. On success ca@38: the list will be updated. ca@38: " ca@38: |successFg result evaluator selInstVar code| ca@38: ca@38: selInstVar := self selectedInstanceVar. ca@38: ca@38: selInstVar notNil ifTrue:[ cg@2621: code := self class asString:aCode. ca@38: cg@2621: code notNil ifTrue:[ cg@2621: evaluator := selInstVar class evaluatorClass. cg@2621: successFg := true. ca@33: cg@2621: evaluator notNil ifTrue:[ cg@2621: result := evaluator evaluate:code cg@2621: in:nil cg@2621: receiver:selInstVar cg@2621: notifying:aView cg@2621: logged:true cg@2621: ifFail:[successFg := false]. ca@38: cg@2621: successFg ifTrue:[ cg@2621: self update. cg@2621: ^ result cg@2621: ] cg@2621: ] cg@2621: ] ca@38: ]. ca@38: ^ #Error. ca@38: ca@38: ca@38: ! ca@38: ca@38: inspect:anObject ca@38: "inspect a new instance; update contents ca@38: " ca@38: |varNamesSize| ca@38: ca@38: selection := nil. ca@38: ca@38: anObject == inspectedObject ifFalse:[ cg@2621: inspectedObject := anObject. ca@33: cg@2621: (self class isDirectory:inspectedObject) ifFalse:[ cg@2621: instanceNames := OrderedCollection new. cg@2621: instanceTypes := OrderedCollection new. cg@2621: ] ifTrue:[ cg@2621: instanceNames := inspectedObject class allInstVarNames. cg@2621: varNamesSize := instanceNames size. cg@2621: instanceTypes := OrderedCollection new:varNamesSize. ca@38: cg@2621: 1 to:varNamesSize do:[:i| cg@2621: (self class isDirectory:(inspectedObject instVarAt:i)) ifTrue:[ cg@2621: instanceTypes add:#directory cg@2621: ] ifFalse:[ cg@2621: instanceTypes add:#normal cg@2621: ] cg@2621: ]. cg@2621: ] ca@38: ]. ca@38: self update ca@33: ! ! ca@33: cg@1213: !NewInspectorList class methodsFor:'documentation'! ca@33: ca@33: version ca@33: ^ '$Header$' ca@33: ! !