InspectorList.st
changeset 38 7b75ce74d9e1
parent 33 eeb1fd7f92aa
child 327 0040d47658c6
equal deleted inserted replaced
37:758be6e05f1d 38:7b75ce74d9e1
    11 !InspectorList class methodsFor:'instance creation'!
    11 !InspectorList class methodsFor:'instance creation'!
    12 
    12 
    13 for:anObject
    13 for:anObject
    14     "create a new list for an instance
    14     "create a new list for an instance
    15     "
    15     "
    16     ^ self basicNew for:anObject
    16     ^ self new inspect:anObject
       
    17 
       
    18 
       
    19 !
       
    20 
       
    21 new
       
    22     "create a new instance and set the inspected object to nil
       
    23     "
       
    24     ^ self basicNew initialize.
       
    25 
       
    26 ! !
       
    27 
       
    28 !InspectorList class methodsFor:'helpers'!
       
    29 
       
    30 asString:aCollection
       
    31     "converts any collection to a string seperated by spaces. If
       
    32      the collection is empty or nil, nil is returned otherwise a
       
    33      string.
       
    34     "
       
    35     |string|
       
    36 
       
    37     aCollection isCollection ifTrue:[
       
    38         aCollection isString ifTrue:[
       
    39             string := aCollection
       
    40         ] ifFalse:[
       
    41             string := aCollection asStringWith:Character space
       
    42                                           from:1 to:(aCollection size)
       
    43                                   compressTabs:true 
       
    44                                          final:nil
       
    45         ].
       
    46         string := string withoutSeparators.
       
    47 
       
    48         string notEmpty ifTrue:[
       
    49             ^ string
       
    50         ]
       
    51     ].
       
    52     ^ nil
    17 
    53 
    18 
    54 
    19 ! !
    55 ! !
    20 
    56 
    21 !InspectorList class methodsFor:'testing'!
    57 !InspectorList class methodsFor:'testing'!
    22 
    58 
    23 isDirectory:anInstance
    59 isDirectory:anInstance
    24     "returns true if the class is a directory
    60     "returns true if the instance is a directory
    25     "
    61     "
    26     |cls|
    62     |cls|
    27 
    63 
    28     anInstance notNil ifTrue:[
    64     anInstance notNil ifTrue:[
    29         cls := anInstance class.
    65         cls := anInstance class.
    41         ].
    77         ].
    42     ].
    78     ].
    43     ^ false
    79     ^ false
    44 
    80 
    45 
    81 
       
    82 !
       
    83 
       
    84 isTraceable:anInstance
       
    85     "returns true if the instance could be traced or traped
       
    86     "
       
    87     |cls|
       
    88 
       
    89     anInstance notNil ifTrue:[
       
    90         cls := anInstance class.
       
    91 
       
    92       ^ (     cls ~~ True
       
    93          and:[cls ~~ False
       
    94          and:[cls ~~ SmallInteger]]
       
    95         )
       
    96     ].
       
    97     ^ false.
       
    98 
    46 ! !
    99 ! !
    47 
   100 
    48 !InspectorList methodsFor:'accessing'!
   101 !InspectorList methodsFor:'accessing'!
    49 
       
    50 includesSelf
       
    51     "returns true if 'self' is included in the list
       
    52     "
       
    53     ^ (self instanceTypeAt:1) == #self
       
    54 
       
    55 
       
    56 !
       
    57 
   102 
    58 includesSelf:aBoolean
   103 includesSelf:aBoolean
    59     "includes 'self' dependant on the boolean
   104     "includes 'self' dependant on the boolean
    60     "
   105     "
    61     (self includesSelf) ~~ aBoolean ifTrue:[
   106     (self includesSelf) ~~ aBoolean ifTrue:[
    62         aBoolean ifTrue:[
   107         aBoolean ifTrue:[
    63             instanceNames addFirst:'self'.
   108             instanceNames addFirst:'self'.
    64             instanceTypes addFirst:#self.
   109             instanceTypes addFirst:#self.
    65 
   110 
    66             selection isNil ifTrue:[selection := 1]
   111             selection notNil ifTrue:[selection := selection + 1]
    67                            ifFalse:[selection := selection + 1]
   112                             ifFalse:[selection := 1]
       
   113 
    68         ] ifFalse:[
   114         ] ifFalse:[
    69             instanceNames removeFirst.
   115             instanceNames removeFirst.
    70             instanceTypes removeFirst.
   116             instanceTypes removeFirst.
    71 
   117 
    72             selection isNil ifFalse:[
   118             selection isNil ifFalse:[
    78     ]
   124     ]
    79 
   125 
    80 
   126 
    81 !
   127 !
    82 
   128 
       
   129 list
       
   130     "returns self
       
   131     "
       
   132     ^ self
       
   133 !
       
   134 
    83 size
   135 size
    84     "returns current list size
   136     "returns size of list
    85     "
   137     "
    86     ^ instanceNames size
   138     ^ instanceNames size
    87 
   139 
       
   140 !
       
   141 
       
   142 update
       
   143     "update list contents
       
   144     "
       
   145     |start stop size|
       
   146 
       
   147     inspectedObject isVariable ifTrue:[
       
   148         start := instanceNames findFirst:[:el|(el at:1) isDigit].
       
   149         stop  := instanceTypes size.
       
   150 
       
   151         start == 0 ifTrue:[
       
   152             size := stop + 10.  "must be > 1: force a resize the first time"   
       
   153         ] ifFalse:[
       
   154             instanceTypes last ~~ #grow ifTrue:[size := stop]
       
   155                                        ifFalse:[size := stop-1].
       
   156 
       
   157             instanceTypes removeFromIndex:start toIndex:stop.
       
   158             instanceNames removeFromIndex:start toIndex:stop.
       
   159         ].
       
   160         self resizeTo:size.
       
   161     ]
    88 ! !
   162 ! !
    89 
   163 
    90 !InspectorList methodsFor:'accessing contents'!
   164 !InspectorList methodsFor:'accessing contents'!
    91 
   165 
    92 inspectedObject
   166 inspectedObject
    95     ^ inspectedObject
   169     ^ inspectedObject
    96 
   170 
    97 
   171 
    98 !
   172 !
    99 
   173 
   100 instanceNameAt:anIndex
       
   101     "returns the name assigned to the index
       
   102     "
       
   103     |idx nm|
       
   104 
       
   105     (anIndex notNil and:[anIndex <= instanceTypes size]) ifTrue:[
       
   106         nm := instanceNames at:anIndex.
       
   107 
       
   108         (nm at:1) isDigit ifFalse:[
       
   109             ^ nm
       
   110         ].
       
   111         idx := Number readFrom:nm onError:0.
       
   112         ^ '[', idx printString, ']'.
       
   113     ].
       
   114     ^ nil
       
   115 
       
   116 
       
   117 !
       
   118 
       
   119 instanceNames
   174 instanceNames
   120     "returns list of instance names
   175     "returns list of instance names
   121     "
   176     "
   122     ^ instanceNames
   177     ^ instanceNames
   123 
   178 
   124 
   179 
   125 !
   180 !
   126 
   181 
   127 instanceTypeAt:anIndex
   182 instanceTypeAt:anIndex
   128     "returns type assigned to the list entry (#directory #normal #self)
   183     "returns type assigned to the list entry (#directory #normal #self #grow)
   129     "
   184      In case of an invalid index nil is returned.
   130     (anIndex notNil and:[anIndex <= instanceTypes size]) ifTrue:[
   185     "
   131         ^ instanceTypes at:anIndex
   186     (anIndex isNil or:[anIndex > instanceTypes size]) ifFalse:[^ instanceTypes at:anIndex]
   132     ].
   187                                                        ifTrue:[^ nil].
   133     ^ nil
       
   134 
   188 
   135 
   189 
   136 !
   190 !
   137 
   191 
   138 instanceTypes
   192 instanceTypes
   139     "returns list of types (#directory #normal #self)
   193     "returns list of types (#directory #normal #self #grow)
   140     "
   194     "
   141     ^ instanceTypes
   195     ^ instanceTypes
   142 
   196 
   143 
   197 
   144 !
   198 !
   145 
   199 
   146 instanceVarAt:anIndex
   200 instanceVarAt:anIndex
   147     "returns the instnace variable assigned to the index
   201     "returns the instnace variable assigned to the index or 
       
   202      nil in case of an invalid index.
   148     "
   203     "
   149     |idx nm|
   204     |idx nm|
   150 
   205 
   151     (anIndex notNil and:[anIndex <= instanceTypes size]) ifTrue:[
   206     (anIndex isNil or:[anIndex > instanceTypes size]) ifFalse:[
   152         nm := instanceNames at:anIndex.
   207         nm := instanceNames at:anIndex.
   153 
   208 
   154         (nm at:1) isDigit ifFalse:[
   209         (nm at:1) isDigit ifFalse:[
   155             self includesSelf ifFalse:[
   210             self includesSelf ifFalse:[
   156                 ^ inspectedObject instVarAt:anIndex
   211                 ^ inspectedObject instVarAt:anIndex
   163     ^ nil
   218     ^ nil
   164 
   219 
   165 
   220 
   166 ! !
   221 ! !
   167 
   222 
   168 !InspectorList methodsFor:'actions'!
       
   169 
       
   170 accept:aText notifying:aView
       
   171     "on error #Error is returned otherwise the inspected object instance
       
   172     "
       
   173     |txt slNr value|
       
   174 
       
   175     (selection isNil or:[(txt := self textToString:aText) isNil]) ifTrue:[
       
   176         ^ #Error
       
   177     ].
       
   178 
       
   179     self includesSelf ifFalse:[slNr := selection]
       
   180                        ifTrue:[slNr := selection -1].
       
   181 
       
   182     value := inspectedObject class evaluatorClass 
       
   183                evaluate:txt
       
   184                receiver:inspectedObject 
       
   185               notifying:aView.
       
   186 
       
   187     slNr ~~ 0 ifTrue:[
       
   188         (inspectedObject class isVariable) ifFalse:[
       
   189             inspectedObject instVarAt:slNr put:value
       
   190         ] ifTrue:[
       
   191             slNr <= (inspectedObject class instSize) ifTrue:[
       
   192                 inspectedObject instVarAt:slNr put:value
       
   193             ] ifFalse:[
       
   194                 slNr := slNr - inspectedObject class instSize.
       
   195                 inspectedObject basicAt:slNr put:value
       
   196             ]
       
   197         ]
       
   198     ].
       
   199     inspectedObject changed.
       
   200     self update.
       
   201   ^ inspectedObject
       
   202 
       
   203 
       
   204 !
       
   205 
       
   206 doIt:aCode notifying:aView
       
   207     "on success the value returned from parser is returned otherwise #Error
       
   208     "
       
   209     |code result evaluator selInstVar state|
       
   210 
       
   211     (selection isNil or:[(code := self textToString:aCode) isNil]) ifFalse:[
       
   212         selInstVar := self selectedInstanceVar.
       
   213         evaluator  := selInstVar class evaluatorClass.
       
   214         state      := true.
       
   215 
       
   216         evaluator notNil ifTrue:[
       
   217             result := evaluator evaluate:code 
       
   218                                       in:nil 
       
   219                                 receiver:selInstVar 
       
   220                                notifying:aView 
       
   221                                   logged:true 
       
   222                                   ifFail:[state := false].
       
   223 
       
   224             state ifTrue:[
       
   225                 self update.
       
   226               ^ result
       
   227             ]
       
   228         ]
       
   229     ].
       
   230     ^ #Error.
       
   231 
       
   232 
       
   233 ! !
       
   234 
       
   235 !InspectorList methodsFor:'initialization'!
   223 !InspectorList methodsFor:'initialization'!
   236 
   224 
   237 for:anObject
   225 initialize
   238     "setup a new instance
   226     "initialize instance attributes
   239     "
   227     "
   240     |varNamesSize|
   228     super initialize.
   241 
   229 
   242     inspectedObject := anObject.
   230     instanceNames := OrderedCollection new.
   243     selection       := nil.
   231     instanceTypes := OrderedCollection new.
   244 
   232 
   245     (self class isDirectory:inspectedObject) ifTrue:[
   233 ! !
   246         instanceNames := inspectedObject class allInstVarNames.
   234 
   247         varNamesSize  := instanceNames size.
   235 !InspectorList methodsFor:'private'!
   248         instanceTypes := OrderedCollection new:varNamesSize.
   236 
   249 
   237 resizeTo:aNumber
   250         1 to:varNamesSize do:[:i|
   238     "resize list to minimum aNumber
   251             (self class isDirectory:(inspectedObject instVarAt:i)) ifTrue:[
   239     "
   252                 instanceTypes add:#directory
   240     |lstVarId basicSize newLastId obj instSize|
   253             ] ifFalse:[
   241 
   254                 instanceTypes add:#normal
   242     (inspectedObject isVariable and:[self class isDirectory:inspectedObject]) ifFalse:[
   255             ]
   243         ^ self
   256         ]
   244     ].
       
   245 
       
   246     instanceTypes size == 0 ifTrue:[
       
   247         lstVarId := 0
   257     ] ifFalse:[
   248     ] ifFalse:[
   258         instanceNames := OrderedCollection new.
   249         instSize := inspectedObject class instSize.
   259         instanceTypes := OrderedCollection new.
   250 
   260     ].
   251         instanceTypes first == #self ifTrue:[
   261     self update.
   252             instSize := instSize + 1
   262 ! !
   253         ].
   263 
       
   264 !InspectorList methodsFor:'private'!
       
   265 
       
   266 lastVariableId
       
   267     "returns last variable id or nil if not growable
       
   268     "
       
   269     |lstId bscSz|
       
   270 
       
   271     (inspectedObject isVariable and:[self class isDirectory:inspectedObject]) ifFalse:[
       
   272         ^ nil
       
   273     ].
       
   274 
       
   275     bscSz := inspectedObject class instSize.
       
   276 
       
   277     self includesSelf ifTrue:[
       
   278         bscSz := bscSz + 1.
       
   279     ].
       
   280     lstId := instanceTypes size - bscSz.
       
   281 
       
   282     (lstId ~~ 0 and:[instanceTypes last == #grow]) ifTrue:[^ lstId-1]
       
   283                                                   ifFalse:[^ lstId].
       
   284 !
       
   285 
       
   286 resizeVariableList:toNumber
       
   287     "resize variable list
       
   288     "
       
   289     |lstVarId basicSize newLastId obj|
       
   290 
       
   291     (lstVarId := self lastVariableId) isNil ifTrue:[
       
   292         ^ self
       
   293     ].
       
   294 
       
   295     basicSize := inspectedObject basicSize.
       
   296 
       
   297     (toNumber <= lstVarId or:[basicSize == lstVarId]) ifTrue:[
       
   298         ^ self
       
   299     ].
       
   300     newLastId := (toNumber + 49) roundTo:100.
       
   301 
       
   302     newLastId > basicSize ifTrue:[
       
   303         newLastId := basicSize
       
   304     ].
       
   305 
       
   306     lstVarId ~~ 0 ifTrue:[
       
   307         instanceTypes last == #grow ifTrue:[
   254         instanceTypes last == #grow ifTrue:[
   308             instanceNames removeLast.       " ..    "
   255             instanceNames removeLast.       " ..    "
   309             instanceTypes removeLast.       " #grow "
   256             instanceTypes removeLast.       " #grow "
   310         ]
   257         ].
       
   258         lstVarId := instanceTypes size - instSize.
       
   259     ].
       
   260 
       
   261     (basicSize := inspectedObject basicSize) == lstVarId ifTrue:[
       
   262         ^ self
       
   263     ].
       
   264     newLastId := (1 bitShift:((aNumber-1) highBit)) max:128.
       
   265 
       
   266     (newLastId + 64) > basicSize ifTrue:[
       
   267         newLastId := basicSize
   311     ].
   268     ].
   312 
   269 
   313     [lstVarId ~~ newLastId] whileTrue:[
   270     [lstVarId ~~ newLastId] whileTrue:[
   314         lstVarId := lstVarId + 1.
   271         lstVarId := lstVarId + 1.
   315         obj := inspectedObject basicAt:lstVarId.
   272         obj := inspectedObject basicAt:lstVarId.
   322 
   279 
   323     lstVarId ~~ basicSize ifTrue:[
   280     lstVarId ~~ basicSize ifTrue:[
   324         instanceNames add:'..'.
   281         instanceNames add:'..'.
   325         instanceTypes add:#grow
   282         instanceTypes add:#grow
   326     ].
   283     ].
   327 
       
   328 
       
   329 !
       
   330 
       
   331 textToString:aText
       
   332     "converts a text to a string
       
   333     "
       
   334     |s|
       
   335 
       
   336     aText isString ifTrue:[
       
   337         s := aText string
       
   338     ] ifFalse:[
       
   339         aText isCollection ifTrue:[
       
   340             s := ''.
       
   341             aText do:[:el|el notNil ifTrue:[s := s, el string]].
       
   342         ]
       
   343     ].
       
   344 
       
   345     s notNil ifTrue:[
       
   346         (s := s withoutSeparators) notEmpty ifTrue:[
       
   347             ^ s
       
   348         ]
       
   349     ].
       
   350     ^ nil.
       
   351 
       
   352 
       
   353 !
       
   354 
       
   355 update
       
   356     "update contents
       
   357     "
       
   358     |delNr lstVarId|
       
   359 
       
   360     (lstVarId := self lastVariableId) isNil ifFalse:[
       
   361         lstVarId == 0 ifTrue:[
       
   362             lstVarId := 100
       
   363         ] ifFalse:[
       
   364             instanceTypes last == #grow ifTrue:[delNr := lstVarId+1]
       
   365                                        ifFalse:[delNr := lstVarId].
       
   366 
       
   367             instanceTypes removeLast:delNr.     
       
   368             instanceNames removeLast:delNr.
       
   369         ].
       
   370         self resizeVariableList:lstVarId.
       
   371     ]
       
   372 ! !
   284 ! !
   373 
   285 
   374 !InspectorList methodsFor:'selections'!
   286 !InspectorList methodsFor:'selections'!
   375 
   287 
   376 selectedInstanceName
       
   377     "returns name of current selection or nil
       
   378     "
       
   379     ^ self instanceNameAt:selection
       
   380 
       
   381 
       
   382 !
       
   383 
       
   384 selectedInstanceType
   288 selectedInstanceType
   385     "returns type of current selection or nil
   289     "returns type assigned to the selected list entry (#directory #normal #self #grow).
       
   290      In case of no selection nil is returned.
   386     "
   291     "
   387     ^ self instanceTypeAt:selection
   292     ^ self instanceTypeAt:selection
   388 
   293 
   389 
   294 
   390 !
   295 !
   403     ^ selection
   308     ^ selection
   404 
   309 
   405 
   310 
   406 !
   311 !
   407 
   312 
   408 selection:aNrOrNil
   313 setSelection:aNrOrNil
   409     "change current selection to a number or nil; may grow a variable list
   314     "change current selection to a number or nil; may resize the lists
   410     "
   315     "
   411     |rsz|
   316     selection := aNrOrNil.
   412 
   317 
   413     aNrOrNil isNil ifTrue:[
   318     (selection isNil or:[instanceTypes size > selection]) ifFalse:[
   414         self includesSelf ifTrue:[selection := 1]
   319         self resizeTo:selection.
   415                          ifFalse:[selection := nil]
   320 
   416     ] ifFalse:[
   321         selection > instanceTypes size ifTrue:[
   417         aNrOrNil >= instanceNames size ifTrue:[
   322             selection := nil
   418             (rsz := self lastVariableId) notNil ifTrue:[
   323         ]
   419                 rsz := rsz * 2.
   324     ]    
   420 
   325 ! !
   421                 rsz < aNrOrNil ifTrue:[
   326 
   422                     rsz := aNrOrNil
   327 !InspectorList methodsFor:'testing'!
   423                 ].
   328 
   424                 self resizeVariableList:rsz
   329 includesSelf
       
   330     "returns true if 'self' is included in the list
       
   331     "
       
   332     ^ (instanceTypes notEmpty and:[instanceTypes first == #self])
       
   333 
       
   334 
       
   335 !
       
   336 
       
   337 isEmpty
       
   338     "returns true if the list is empty
       
   339     "
       
   340     ^ instanceNames isEmpty
       
   341 
       
   342 !
       
   343 
       
   344 notEmpty
       
   345     "returns true if the list is not empty
       
   346     "
       
   347     ^ instanceNames notEmpty
       
   348 
       
   349 ! !
       
   350 
       
   351 !InspectorList methodsFor:'user interaction'!
       
   352 
       
   353 accept:aText notifying:aView
       
   354     "evaluating aText on the selected instance var; if an error occurs #Error
       
   355      is returned otherwise the inspected object instance. On success the list
       
   356      will be updated.
       
   357     "
       
   358     |text slNr value|
       
   359 
       
   360     selection notNil ifTrue:[
       
   361         text := self class asString:aText.
       
   362 
       
   363         text notNil ifTrue:[
       
   364             self includesSelf ifFalse:[slNr := selection]
       
   365                                ifTrue:[slNr := selection-1].
       
   366 
       
   367             value := inspectedObject class evaluatorClass 
       
   368                        evaluate:text
       
   369                        receiver:inspectedObject 
       
   370                       notifying:aView.
       
   371 
       
   372             slNr ~~ 0 ifTrue:[
       
   373                 (inspectedObject class isVariable) ifFalse:[
       
   374                     inspectedObject instVarAt:slNr put:value
       
   375                 ] ifTrue:[
       
   376                     slNr <= (inspectedObject class instSize) ifTrue:[
       
   377                         inspectedObject instVarAt:slNr put:value
       
   378                     ] ifFalse:[
       
   379                         slNr := slNr - inspectedObject class instSize.
       
   380                         inspectedObject basicAt:slNr put:value
       
   381                     ]
       
   382                 ]
       
   383             ].
       
   384             inspectedObject changed.
       
   385             self update.
       
   386           ^ inspectedObject
       
   387         ]
       
   388     ].
       
   389     ^ #Error
       
   390 !
       
   391 
       
   392 doIt:aCode notifying:aView
       
   393     "evaluating aCode on the selected instance var; if an error occurs #Error
       
   394      is returned otherwise the result returned from the evaluator. On success
       
   395      the list will be updated.
       
   396     "
       
   397     |successFg result evaluator selInstVar code|
       
   398 
       
   399     selInstVar := self selectedInstanceVar.
       
   400 
       
   401     selInstVar notNil ifTrue:[
       
   402         code := self class asString:aCode.
       
   403 
       
   404         code notNil ifTrue:[
       
   405             evaluator := selInstVar class evaluatorClass.
       
   406             successFg := true.
       
   407 
       
   408             evaluator notNil ifTrue:[
       
   409                 result := evaluator evaluate:code 
       
   410                                           in:nil 
       
   411                                     receiver:selInstVar 
       
   412                                    notifying:aView 
       
   413                                       logged:true 
       
   414                                       ifFail:[successFg := false].
       
   415 
       
   416                 successFg ifTrue:[
       
   417                     self update. 
       
   418                   ^ result 
       
   419                 ]
   425             ]
   420             ]
   426         ].
   421         ]
   427         aNrOrNil > instanceNames size ifFalse:[selection := aNrOrNil]
   422     ].
   428                                        ifTrue:[selection := nil]
   423     ^ #Error.
   429     ]
   424 
   430 
   425 
       
   426 !
       
   427 
       
   428 inspect:anObject
       
   429     "inspect a new instance; update contents
       
   430     "
       
   431     |varNamesSize|
       
   432 
       
   433     selection := nil.
       
   434 
       
   435     anObject == inspectedObject ifFalse:[
       
   436         inspectedObject := anObject.
       
   437 
       
   438         (self class isDirectory:inspectedObject) ifFalse:[
       
   439             instanceNames := OrderedCollection new.
       
   440             instanceTypes := OrderedCollection new.
       
   441         ] ifTrue:[    
       
   442             instanceNames := inspectedObject class allInstVarNames.
       
   443             varNamesSize  := instanceNames size.
       
   444             instanceTypes := OrderedCollection new:varNamesSize.
       
   445 
       
   446             1 to:varNamesSize do:[:i|
       
   447                 (self class isDirectory:(inspectedObject instVarAt:i)) ifTrue:[
       
   448                     instanceTypes add:#directory
       
   449                 ] ifFalse:[
       
   450                     instanceTypes add:#normal
       
   451                 ]
       
   452             ].
       
   453         ]
       
   454     ].
       
   455     self update
   431 ! !
   456 ! !
   432 
   457 
   433 !InspectorList class methodsFor:'documentation'!
   458 !InspectorList class methodsFor:'documentation'!
   434 
   459 
   435 version
   460 version