The Trunk: EToys-ul.293.mcz

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

The Trunk: EToys-ul.293.mcz

commits-2
Levente Uzonyi uploaded a new version of EToys to project The Trunk:
http://source.squeak.org/trunk/EToys-ul.293.mcz

==================== Summary ====================

Name: EToys-ul.293
Author: ul
Time: 24 April 2017, 1:01:48.504154 pm
UUID: d935e150-2a96-4b3f-9ce4-cbe3926044f4
Ancestors: EToys-nice.292

- rewrote senders of #clone to use #shallowCopy
- removed the long time obsoleted Etoys-Squeakland-Tools-File Contents Browser category

=============== Diff against EToys-nice.292 ===============

Item was changed:
  SystemOrganization addCategory: #'Etoys-Buttons'!
  SystemOrganization addCategory: #'Etoys-CustomEvents'!
  SystemOrganization addCategory: #'Etoys-Experimental'!
  SystemOrganization addCategory: #'Etoys-Outliner'!
  SystemOrganization addCategory: #'Etoys-Protocols'!
  SystemOrganization addCategory: #'Etoys-Protocols-Type Vocabularies'!
  SystemOrganization addCategory: #'Etoys-Scripting'!
  SystemOrganization addCategory: #'Etoys-Scripting Support'!
  SystemOrganization addCategory: #'Etoys-Scripting Tiles'!
  SystemOrganization addCategory: #'Etoys-Squeakland-BroomMorphs-Base'!
  SystemOrganization addCategory: #'Etoys-Squeakland-BroomMorphs-Connectors'!
  SystemOrganization addCategory: #'Etoys-Squeakland-EToys-Kedama'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Buttons'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Calendar'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Debugger'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Help'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Input'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Scripting'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Scripting Support'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Scripting Tiles'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-SpeechBubbles'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Etoys-Tile Scriptors'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Graphics-External'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Graphics-Text'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Graphics-Tools-Intersection'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Graphics-Tools-Simplification'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Graphics-Tools-Triangulation'!
  SystemOrganization addCategory: #'Etoys-Squeakland-MorphicExtras-AdditionalMorphs'!
  SystemOrganization addCategory: #'Etoys-Squeakland-MorphicExtras-Charts'!
  SystemOrganization addCategory: #'Etoys-Squeakland-MorphicExtras-Postscript Filters'!
  SystemOrganization addCategory: #'Etoys-Squeakland-MorphicExtras-WebCam'!
  SystemOrganization addCategory: #'Etoys-Squeakland-MorphicExtras-Widgets'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Basic'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Books'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Components'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Demo'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Experimental'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Games'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Games-Chess'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-GeeMail'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Kernel'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Mentoring'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Navigators'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-PartsBin'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-PDA'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Support'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Widgets'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Windows'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Morphic-Worlds'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Multilingual-Languages'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Multilingual-TextConversion'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Network-HTML-Formatter'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Network-HTML-Forms'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Network-HTML-Parser'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Network-HTML-Parser Entities'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Network-HTML-Tokenizer'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Network-MIME'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Network-TelNet WordNet'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Network-UI'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Network-Url'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Protocols-Type Vocabularies'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Sound-Interface'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Sound-Ogg'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Sound-Scores'!
  SystemOrganization addCategory: #'Etoys-Squeakland-ST80-Morphic'!
  SystemOrganization addCategory: #'Etoys-Squeakland-SUnit'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Sugar'!
  SystemOrganization addCategory: #'Etoys-Squeakland-System-Clipboard-Extended'!
  SystemOrganization addCategory: #'Etoys-Squeakland-System-Compiler'!
  SystemOrganization addCategory: #'Etoys-Squeakland-System-Exceptions Kernel'!
  SystemOrganization addCategory: #'Etoys-Squeakland-System-Support'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Tools-Changes'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Tools-Explorer'!
- SystemOrganization addCategory: #'Etoys-Squeakland-Tools-File Contents Browser'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Tools-Process Browser'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Tweak-Kedama-ObjectVectors'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Tweak-Kedama-ParseTreeTransformer'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Tweak-Kedama-ParseTree-AttributeDefinition'!
  SystemOrganization addCategory: #'Etoys-Stacks'!
  SystemOrganization addCategory: #'Etoys-StarSqueak'!
  SystemOrganization addCategory: #'Etoys-Support'!
  SystemOrganization addCategory: #'Etoys-Tests'!
  SystemOrganization addCategory: #'Etoys-Tile Scriptors'!
  SystemOrganization addCategory: #'Etoys-Widgets'!
  SystemOrganization addCategory: #'Etoys-Squeakland-Support'!
  SystemOrganization addCategory: #'Etoys-Squeakland-SISS-Serialization'!
  SystemOrganization addCategory: #'Etoys-OLPC-Display'!
  SystemOrganization addCategory: #'Etoys-ReleaseBuilder'!
  SystemOrganization addCategory: #'Etoys-UserInterfaceTheme'!

Item was removed:
- ----- Method: ChessBoard>>copy (in category 'copying') -----
- copy
- ^self shallowCopy postCopy!

Item was removed:
- ----- Method: ChessPlayer>>copy (in category 'copying') -----
- copy
- ^self shallowCopy postCopy!

Item was changed:
  ----- Method: ChessPlayer>>postCopy (in category 'copying') -----
  postCopy
+
+ pieces := pieces copy!
- pieces := pieces clone.!

Item was changed:
  ----- Method: ChessTranspositionTable>>initialize: (in category 'initialize') -----
  initialize: nBits
  "Initialize the receiver using 1<<nBits entries. See also ChessPlayerAI>>initializeTranspositionTable."
  | entry |
  array := Array new: 1 << nBits.
  used := ReadWriteStream on: (Array new: 50000). "<- will grow if not sufficient!!"
  entry := ChessTTEntry new clear.
+ 1 to: array size do:[:i| array at: i put: entry shallowCopy].
- 1 to: array size do:[:i| array at: i put: entry clone].
  collisions := 0.
  Smalltalk garbageCollect. "We *really* want them old here"!

Item was changed:
  ----- Method: DeepCopier>>mapUniClassMethods: (in category '*Etoys-Squeakland-full copy') -----
  mapUniClassMethods: pool
  "Players also refer to each other using associations in the References dictionary.  Search the literals of the methods of our Players for those.  There are already new entries in project-local References and point to them."
  | newKey newAssoc oldSelList newSelList newValue |
 
  uniClasses "values" do: [:newClass |
  oldSelList := OrderedCollection new.   newSelList := OrderedCollection new.
  newClass selectorsDo: [:sel |
  (newClass compiledMethodAt: sel) literals do: [:assoc |
  assoc isVariableBinding ifTrue: [
  newValue := references at: assoc value ifAbsent: [].
  newValue ifNotNil: [
  newKey := newValue externalName asSymbol.
  (assoc key ~= newKey) & (pool includesKey: newKey) ifTrue: [
  newAssoc := pool associationAt: newKey.
  newClass methodDictionary at: sel put:
+ (newClass compiledMethodAt: sel) shallowCopy. "were sharing it"
- (newClass compiledMethodAt: sel) clone. "were sharing it"
  (newClass compiledMethodAt: sel)
  literalAt: ((newClass compiledMethodAt: sel) literals indexOf: assoc)
  put: newAssoc.
  (oldSelList includes: assoc key) ifFalse: [
  oldSelList add: assoc key.  newSelList add: newKey]]]]]].
  oldSelList with: newSelList do: [:old :new |
  newClass replaceSilently: old to: new]]. "This is text replacement and can be wrong"!

Item was changed:
  ----- Method: EFontBDFFontReaderForRanges>>override2:with:ranges:transcodingTable:additionalRange: (in category '*Etoys-Squeakland-as yet unclassified') -----
  override2: chars with: otherFileName ranges: pairArray transcodingTable: table additionalRange: additionalRanges
 
  | other newChars form u j in newArray |
  other := BDFFontReader readOnlyFileNamed: otherFileName.
 
  newChars := PluggableSet new.
  newChars hashBlock: [:elem | (elem at: 2) hash].
  newChars equalBlock: [:a :b | (a at: 2) = (b at: 2)].
 
  other readChars do: [:array |
  j := array at: 2.
  u := table at: (((j // 256) - 33 * 94 + ((j \\ 256) - 33)) + 1).
  u ~= -1 ifTrue: [
  u hex printString displayAt: 0@0.
  in := false.
  pairArray do: [:pair |
  (u between: pair first and: pair second) ifTrue: [
  in := true
  ]
  ].
  in ifTrue: [
  form := array at: 1.
  form ifNotNil: [
+ newArray := array shallowCopy.
- newArray := array clone.
  newArray at: 2 put: u.
  newChars add: newArray.
  ].
  ].
  ].
  ].
 
  newChars addAll: chars.
  ^ newChars.
  !

Item was changed:
  ----- Method: KedamaExamplerPlayer>>clonedSequentialStub (in category 'subclass players management') -----
  clonedSequentialStub
 
+ ^sequentialStub shallowCopy!
- ^ sequentialStub clone.
- !

Item was changed:
  ----- Method: KedamaSequenceExecutionStub>>getReplicated (in category 'player commands') -----
  getReplicated
 
  | proto newWho n |
  proto := (1 to: turtles arrays size) collect: [:i | (turtles arrays at: i) at: self index].
  kedamaWorld makeReplicatedTurtles: 1 examplerPlayer: exampler color: nil ofPrototype: proto randomize: false.
  exampler costume renderedMorph privateTurtleCount: (kedamaWorld turtlesCountOf: exampler).
  newWho := (kedamaWorld lastWhoOf: exampler).
+ n := self shallowCopy.
- n := self clone.
  n who: newWho.
  ^ n.
  !

Item was changed:
  ----- Method: KedamaTurtleVectorPlayer2>>test:ifTrue:ifFalse: (in category 'command execution') -----
  test: cond ifTrue: trueBlock ifFalse: falseBlock
 
  | origPredicate c actualCond condValue |
 
  (cond == true or: [cond == false]) ifTrue: [
  ^ cond ifTrue: [trueBlock value: self] ifFalse: [falseBlock value: self].
  ].
  actualCond := cond.
  cond isBlock ifTrue: [
  actualCond := ByteArray new: predicate size.
  condValue := cond value.
  condValue isCollection
  ifTrue: [
  actualCond := condValue.
  ] ifFalse: [
  1 to: predicate size do: [:i | actualCond at: i put: (cond value ifTrue: [1] ifFalse: [0])]
  ]
  ].
+ origPredicate := predicate shallowCopy.
- origPredicate := predicate clone.
  predicate bytesAnd: actualCond.
  trueBlock value: self.
 
+ c := actualCond shallowCopy.
- c := actualCond clone.
  c not.
  predicate replaceFrom: 1 to: (predicate size min: origPredicate size) with: origPredicate startingAt: 1.
  predicate bytesAnd: c.
  falseBlock value: self.
  predicate replaceFrom: 1 to: (predicate size min: origPredicate size) with: origPredicate startingAt: 1.!

Item was changed:
  ----- Method: MentoringEventRecorder>>nextEventToPlay (in category 'event handling') -----
  nextEventToPlay
  "Return the next event when it is time to be replayed.
  If it is not yet time, then return an interpolated mouseMove.
  Return nil if nothing has happened.
  Return an EOF event if there are no more events to be played."
 
  | nextEvent now nextTime lastP delta |
  (tapeStream isNil or:[tapeStream atEnd])
  ifTrue:[^MorphicUnknownEvent new setType: #EOF argument: nil].
  now := Time millisecondClockValue.
+ nextEvent := tapeStream next shallowCopy. "always copied"
- nextEvent := tapeStream next clone. "always copied"
  areaOffset ifNotNil: [nextEvent isMouse ifTrue:
  [nextEvent position: nextEvent position + areaOffset]].
  nextEvent isKeyboard ifTrue: [ nextEvent setPosition: areaBounds center].
  nextEvent type == #noCondense ifTrue: [^nil]. "ignore in playback"
  deltaTime ifNil:[deltaTime := now - nextEvent timeStamp].
  nextTime := nextEvent timeStamp + deltaTime.
  now < time ifTrue:["clock rollover"
  time := now.
  deltaTime := nil.
  ^nil "continue it on next cycle"].
  time := now.
  (now >= nextTime) ifTrue:[
  nextEvent setTimeStamp: nextTime.
  nextEvent isMouse ifTrue:[lastEvent := nextEvent] ifFalse:[lastEvent := nil].
  ^nextEvent].
  tapeStream skip: -1.
  "Not time for the next event yet, but interpolate the mouse.
  This allows tapes to be compressed when velocity is fairly constant."
  lastEvent ifNil: [^ nil].
  now - lastInterpolation < 20 "WorldState minCycleLapse" ifTrue: [^ nil].
  lastP := lastEvent position.
  delta := (nextEvent position - lastP) * (now - lastEvent timeStamp) // (nextTime - lastEvent timeStamp).
  (delta dist: lastDelta) < 3 ifTrue: [^ nil]. "Almost no movement"
  lastDelta := delta.
  lastInterpolation := now.
  ^ MouseMoveEvent new
  setType: #mouseMove
  startPoint: lastEvent position endPoint: lastP + delta
  trail: nil buttons: lastEvent buttons hand: nil stamp: now.!

Item was changed:
  ----- Method: Morph>>color:sees: (in category '*Etoys-geometry') -----
  color: sensitiveColor sees: soughtColor
  "Return true if any of my pixels of sensitiveColor intersect with pixels of soughtColor."
 
  "Make a mask with black where sensitiveColor is, white elsewhere"
 
  | myImage sensitivePixelMask map patchBelowMe tfm morphAsFlexed i1 pasteUp |
  pasteUp := self world ifNil: [ ^false ].
  tfm := self transformFrom: pasteUp.
  morphAsFlexed := tfm isIdentity
  ifTrue: [self]
+ ifFalse: [TransformationMorph new flexing: self shallowCopy byTransformation: tfm].
- ifFalse: [TransformationMorph new flexing: self clone byTransformation: tfm].
  myImage := morphAsFlexed imageForm offset: 0 @ 0.
  sensitivePixelMask := Form extent: myImage extent depth: 1.
  "ensure at most a 16-bit map"
  map := Bitmap new: (1 bitShift: (myImage depth - 1 min: 15)).
  map at: (i1 := sensitiveColor indexInMap: map) put: 1.
  sensitivePixelMask
  copyBits: sensitivePixelMask boundingBox
  from: myImage form
  at: 0 @ 0
  colorMap: map.
 
  "get an image of the world below me"
  patchBelowMe := pasteUp
  patchAt: morphAsFlexed fullBounds
  without: self
  andNothingAbove: false.
  "
  sensitivePixelMask displayAt: 0@0.
  patchBelowMe displayAt: 100@0.
  "
  "intersect world pixels of the color we're looking for with the sensitive pixels"
  map at: i1 put: 0. "clear map and reuse it"
  map at: (soughtColor indexInMap: map) put: 1.
  sensitivePixelMask
  copyBits: patchBelowMe boundingBox
  from: patchBelowMe
  at: 0 @ 0
  clippingBox: patchBelowMe boundingBox
  rule: Form and
  fillColor: nil
  map: map.
  "
  sensitivePixelMask displayAt: 200@0.
  "
  ^(sensitivePixelMask tallyPixelValues second) > 0!

Item was changed:
  ----- Method: Morph>>touchesColor: (in category '*Etoys-geometry') -----
  touchesColor: soughtColor
  "Return true if any of my pixels overlap pixels of soughtColor."
 
  "Make a shadow mask with black in my shape, white elsewhere"
 
  | map patchBelowMe shadowForm tfm morphAsFlexed pasteUp |
  pasteUp := self world ifNil: [ ^false ].
 
  tfm := self transformFrom: pasteUp.
  morphAsFlexed := tfm isIdentity
  ifTrue: [self]
+ ifFalse: [TransformationMorph new flexing: self shallowCopy byTransformation: tfm].
- ifFalse: [TransformationMorph new flexing: self clone byTransformation: tfm].
  shadowForm := morphAsFlexed shadowForm offset: 0 @ 0.
 
  "get an image of the world below me"
  patchBelowMe := (pasteUp
  patchAt: morphAsFlexed fullBounds
  without: self
  andNothingAbove: false) offset: 0 @ 0.
  "
  shadowForm displayAt: 0@0.
  patchBelowMe displayAt: 100@0.
  "
  "intersect world pixels of the color we're looking for with our shape."
  "ensure a maximum 16-bit map"
  map := Bitmap new: (1 bitShift: (patchBelowMe depth - 1 min: 15)).
  map at: (soughtColor indexInMap: map) put: 1.
  shadowForm
  copyBits: patchBelowMe boundingBox
  from: patchBelowMe
  at: 0 @ 0
  clippingBox: patchBelowMe boundingBox
  rule: Form and
  fillColor: nil
  map: map.
  "
  shadowForm displayAt: 200@0.
  "
  ^(shadowForm tallyPixelValues second) > 0!

Item was changed:
  ----- Method: ParseNode>>normalize (in category '*Etoys-Squeakland-Tweak-Kedama') -----
  normalize
 
  self getAllChildren do: [:child |
  child isLeaf ifTrue: [
+ self replaceNode: child with: child shallowCopy.
- self replaceNode: child with: child clone.
  ] ifFalse: [
  child normalize.
  ].
  ].
  !

Item was changed:
  ----- Method: TileMessageNode>>printIfNilNotNil:indent: (in category 'printing') -----
  printIfNilNotNil: aMorph indent: level
 
  | newNode |
+ newNode := aMorph parseNode shallowCopy.
- newNode := aMorph parseNode clone.
  newNode receiver ifNotNil:
  [newNode receiver: newNode receiver ifNilReceiver]. "fudge so it prints right"
 
  (arguments first isJust: NodeNil) ifTrue:
  [^ newNode morphFromKeywords: #ifNotNil:
  arguments: { arguments second }
  on: aMorph indent: level].
  (arguments second isJust: NodeNil) ifTrue:
  [^ newNode morphFromKeywords: #ifNil:
  arguments: { arguments first }
  on: aMorph indent: level].
  ^ newNode morphFromKeywords: #ifNil:ifNotNil:
  arguments: arguments
  on: aMorph indent: level!

Item was removed:
- Object subclass: #TwoLevelDictionary
- instanceVariableNames: 'firstLevel'
- classVariableNames: ''
- poolDictionaries: ''
- category: 'Etoys-Squeakland-Tools-File Contents Browser'!
-
- !TwoLevelDictionary commentStamp: '<historical>' prior: 0!
- A simple dictionary for the use of the TextDiffBuilder. Keys are presumed to be Points and a significant speed advantage is gained by using a dictionary of dictionaries. The first is keyed by the x-values and the second by the y-values. Only the minimum necessary protocol is implemented.!

Item was removed:
- ----- Method: TwoLevelDictionary>>at: (in category 'as yet unclassified') -----
- at: aPoint
-
- ^(firstLevel at: aPoint x ifAbsent: [^nil]) at: aPoint y ifAbsent: [^nil]
- !

Item was removed:
- ----- Method: TwoLevelDictionary>>at:put: (in category 'as yet unclassified') -----
- at: aPoint put: anObject
-
- (firstLevel at: aPoint x ifAbsentPut: [Dictionary new]) at: aPoint y put: anObject
- !

Item was removed:
- ----- Method: TwoLevelDictionary>>initialize (in category 'as yet unclassified') -----
- initialize
-
- firstLevel := Dictionary new.!

Item was removed:
- ----- Method: TwoLevelDictionary>>keysDo: (in category 'as yet unclassified') -----
- keysDo: aBlock
-
- firstLevel keysAndValuesDo: [ :x :v |
- v keysDo: [ :y | aBlock value: x@y]
- ].!

Item was removed:
- ----- Method: TwoLevelDictionary>>twoLevelKeys (in category 'as yet unclassified') -----
- twoLevelKeys
-
- | twoLevelSet |
-
- twoLevelSet := TwoLevelSet new.
- self keysDo: [ :each | twoLevelSet add: each].
- ^twoLevelSet
- !

Item was removed:
- Object subclass: #TwoLevelSet
- instanceVariableNames: 'firstLevel'
- classVariableNames: ''
- poolDictionaries: ''
- category: 'Etoys-Squeakland-Tools-File Contents Browser'!
-
- !TwoLevelSet commentStamp: '<historical>' prior: 0!
- A simple set for the use of the TextDiffBuilder. Elements are presumed to be Points and a significant speed advantage is gained by using a dictionary of sets. The first is keyed by the x-values and the second contains the y-values. Only the minimum necessary protocol is implemented.!

Item was removed:
- ----- Method: TwoLevelSet>>add: (in category 'as yet unclassified') -----
- add: aPoint
-
- (firstLevel at: aPoint x ifAbsentPut: [Set new]) add: aPoint y
- !

Item was removed:
- ----- Method: TwoLevelSet>>copy (in category 'as yet unclassified') -----
- copy
-
- | answer |
-
- answer := self class new initialize.
- self do: [ :each |
- answer add: each
- ].
- ^answer!

Item was removed:
- ----- Method: TwoLevelSet>>detect: (in category 'as yet unclassified') -----
- detect: aBlock
-
- firstLevel keysAndValuesDo: [ :x :v |
- v do: [ :y | (aBlock value: x@y) ifTrue: [^x@y]]
- ].
- ^nil!

Item was removed:
- ----- Method: TwoLevelSet>>do: (in category 'as yet unclassified') -----
- do: aBlock
-
- firstLevel keysAndValuesDo: [ :x :v |
- v do: [ :y | aBlock value: x@y]
- ].!

Item was removed:
- ----- Method: TwoLevelSet>>includes: (in category 'as yet unclassified') -----
- includes: aPoint
-
- ^(firstLevel at: aPoint x ifAbsent: [^false]) includes: aPoint y!

Item was removed:
- ----- Method: TwoLevelSet>>initialize (in category 'as yet unclassified') -----
- initialize
-
- firstLevel := Dictionary new.!

Item was removed:
- ----- Method: TwoLevelSet>>isEmpty (in category 'as yet unclassified') -----
- isEmpty
-
- ^firstLevel isEmpty!

Item was removed:
- ----- Method: TwoLevelSet>>remove: (in category 'as yet unclassified') -----
- remove: aPoint
-
- | lev2 |
-
- lev2 := firstLevel at: aPoint x ifAbsent: [^self].
- lev2 remove: aPoint y ifAbsent: [].
- lev2 isEmpty ifTrue: [firstLevel removeKey: aPoint x].
-
- !

Item was removed:
- ----- Method: TwoLevelSet>>removeAllXAndY: (in category 'as yet unclassified') -----
- removeAllXAndY: aPoint
-
- | deletes |
-
- deletes := OrderedCollection new.
- firstLevel removeKey: aPoint x ifAbsent: [].
- firstLevel keysAndValuesDo: [ :x :lev2 |
- lev2 remove: aPoint y ifAbsent: [].
- lev2 isEmpty ifTrue: [deletes add: x].
- ].
- deletes do: [ :each | firstLevel removeKey: each ifAbsent: []].!