Levente Uzonyi uploaded a new version of 51Deprecated to project The Trunk:
http://source.squeak.org/trunk/51Deprecated-ul.30.mcz
==================== Summary ====================
Name: 51Deprecated-ul.30
Author: ul
Time: 2 June 2016, 8:28:00.97666 pm
UUID: 2a30b91d-0870-412d-8c10-ee96c3c48065
Ancestors: 51Deprecated-mt.29
Deprecated the now unused methods of Heap.
=============== Diff against 51Deprecated-mt.29 ===============
Item was added:
+ ----- Method: Heap>>fullySort (in category '*51Deprecated') -----
+ fullySort
+ "Fully sort the heap.
+ This method preserves the heap invariants and can thus be sent safely"
+
+ self deprecated: 'Use #sort'.
+ self sort!
Item was added:
+ ----- Method: Heap>>reSort (in category '*51Deprecated') -----
+ reSort
+ "Resort the entire heap"
+
+ self deprecated: 'This method should not be used anymore. Use #sortBlock: if you want to change the sort order.'.
+ tally <= 1 ifTrue: [ ^self ].
+ (tally bitShift: -1) to: 1 by: -1 do: [ :index | self downHeap: index ]!
Item was added:
+ ----- Method: Heap>>sorts:before: (in category '*51Deprecated') -----
+ sorts: element1 before: element2
+ "Return true if element1 should be sorted before element2.
+ This method defines the sort order in the receiver"
+
+ self deprecated: 'This method has been inlined for performance.'.
+ ^sortBlock == nil
+ ifTrue:[element1 <= element2]
+ ifFalse:[sortBlock value: element1 value: element2].!
Item was added:
+ ----- Method: Heap>>trim (in category '*51Deprecated') -----
+ trim
+ "Remove any empty slots in the receiver."
+
+ self deprecated: 'Use #compact'.
+ self compact!
Item was added:
+ ----- Method: Heap>>updateObjectIndex: (in category '*51Deprecated') -----
+ updateObjectIndex: index
+ "If indexUpdateBlock is not nil, notify the object at index of its new position in the heap array."
+
+ self deprecated: 'This method has been inlined for performance.'.
+ indexUpdateBlock ifNotNil: [
+ indexUpdateBlock value: (array at: index) value: index]!
Levente Uzonyi uploaded a new version of Collections to project The Trunk:
http://source.squeak.org/trunk/Collections-ul.696.mcz
==================== Summary ====================
Name: Collections-ul.696
Author: ul
Time: 2 June 2016, 5:58:47.938458 pm
UUID: 0ec3a2e6-cd17-46b2-970f-2c1dc1227411
Ancestors: Collections-ul.695
- added #quickSort and #quickSort: to ArrayedCollection
=============== Diff against Collections-ul.695 ===============
Item was added:
+ ----- Method: ArrayedCollection>>quickSort (in category 'sorting') -----
+ quickSort
+ "Sort elements of self to be nondescending according to #<= using an in-place quicksort with simple median-of-three partitioning with guaranteed O(log(n)) space usage."
+
+ self quickSortFrom: 1 to: self size by: nil!
Item was added:
+ ----- Method: ArrayedCollection>>quickSort: (in category 'sorting') -----
+ quickSort: sortBlock
+ "Sort elements of self to be nondescending according to sortBlock using an in-place quicksort with simple median-of-three partitioning with guaranteed O(log(n)) space usage."
+
+ self quickSortFrom: 1 to: self size by: sortBlock!
Levente Uzonyi uploaded a new version of Collections to project The Trunk:
http://source.squeak.org/trunk/Collections-ul.695.mcz
==================== Summary ====================
Name: Collections-ul.695
Author: ul
Time: 2 June 2016, 5:48:18.403513 pm
UUID: be1e0401-02a2-49e4-827f-fe0fee861114
Ancestors: Collections-topa.694
Heap revamp #1:
class side:
- Heaps can be created on an existing array with #on: #on:size: and #on:size:sortBlock:
- #withAll: and #withAll:sortBlock: avoid creating an extra copy if the argument is already an Array
instance side:
- imported and improved #= from Pharo
- #growTo: won't raise an error when newSize is less than array size (e.g. during compaction)
- #sortBlock: restores the heap invariant on its own
- improved #select:, #collect, #at:, #removeAt:, #add:
- added #sort and #compact; compatible with other collections
- #capacity returns the real capacity
- inlined #sorts:before: and #indexUpdateBlock: for performance
- improved performance and legibility of the heap operations #upHeap: #downHeap: and #downHeapSingle:
- added #isValidHeap
- added some comments
=============== Diff against Collections-topa.694 ===============
Item was added:
+ ----- Method: Heap class>>on: (in category 'instance creation') -----
+ on: anArray
+ "Create a new heap using anArray as the internal array"
+
+ ^self on: anArray size: anArray size sortBlock: nil!
Item was added:
+ ----- Method: Heap class>>on:size: (in category 'instance creation') -----
+ on: anArray size: size
+ "Create a new heap using the first size elements of anArray as the internal array"
+
+ ^self
+ on: anArray
+ size: size
+ sortBlock: nil!
Item was added:
+ ----- Method: Heap class>>on:size:sortBlock: (in category 'instance creation') -----
+ on: anArray size: size sortBlock: aBlockOrNil
+ "Create a new heap using the first size elements of anArray as the internal array and sorted by aBlockOrNil"
+
+ anArray isArray ifFalse: [ self error: 'Array expected.' ].
+ anArray size < size ifTrue: [ self error: 'size must not be larger than anArray size' ].
+ ^super new
+ setCollection: anArray tally: size;
+ sortBlock: aBlockOrNil;
+ yourself!
Item was changed:
----- Method: Heap class>>withAll: (in category 'instance creation') -----
withAll: aCollection
"Create a new heap with all the elements from aCollection"
+
+ ^self withAll: aCollection sortBlock: nil!
- ^(self basicNew)
- setCollection: aCollection asArray copy tally: aCollection size;
- reSort;
- yourself!
Item was changed:
----- Method: Heap class>>withAll:sortBlock: (in category 'instance creation') -----
withAll: aCollection sortBlock: sortBlock
+ "Create a new heap with all the elements from aCollection, sorted by sortBlock"
+
+ | array |
+ array := aCollection asArray.
+ array == aCollection ifTrue: [ array := array copy ].
+ ^self on: array size: array size sortBlock: sortBlock!
- "Create a new heap with all the elements from aCollection"
- ^(self basicNew)
- setCollection: aCollection asArray copy tally: aCollection size;
- sortBlock: sortBlock;
- yourself!
Item was changed:
----- Method: Heap>>= (in category 'comparing') -----
= anObject
+ "Heap are considered to be equal when they have the same sortBlock and the same elements. This method is expensive due to the sorted copies of the arrays. Try not to use it."
+ self == anObject ifTrue: [ ^true ].
+ anObject isHeap ifFalse: [ ^false ].
+ anObject size = tally ifFalse: [ ^false ].
+ anObject sortBlock = sortBlock ifFalse: [ ^false ].
+ ^((array first: tally) sort: sortBlock) = ((anObject array first: tally) sort: sortBlock)!
- ^ self == anObject
- ifTrue: [true]
- ifFalse: [anObject isHeap
- ifTrue: [sortBlock = anObject sortBlock and: [super = anObject]]
- ifFalse: [super = anObject]]!
Item was changed:
----- Method: Heap>>add: (in category 'adding') -----
add: anObject
"Include newObject as one of the receiver's elements. Answer newObject."
+
tally = array size ifTrue:[self grow].
array at: (tally := tally + 1) put: anObject.
+ indexUpdateBlock ifNotNil: [ indexUpdateBlock value: anObject value: tally ].
- self updateObjectIndex: tally.
self upHeap: tally.
^anObject!
Item was changed:
----- Method: Heap>>at: (in category 'accessing') -----
at: index
"Return the element at the given position within the receiver"
+
+ index > tally ifTrue: [ ^self errorSubscriptBounds: index ].
- (index < 1 or:[index > tally]) ifTrue:[^self errorSubscriptBounds: index].
^array at: index!
Item was added:
+ ----- Method: Heap>>capacity (in category 'accessing') -----
+ capacity
+ "Answer the current capacity of the receiver."
+
+ ^array size!
Item was changed:
----- Method: Heap>>collect: (in category 'enumerating') -----
collect: aBlock
+
+ ^(array first: tally) replace: aBlock!
- ^self collect: aBlock as: Array!
Item was added:
+ ----- Method: Heap>>compact (in category 'growing') -----
+ compact
+ "Remove any empty slots in the receiver."
+
+ self growTo: self size.!
Item was changed:
----- Method: Heap>>downHeap: (in category 'private-heap') -----
downHeap: anIndex
"Check the heap downwards for correctness starting at anIndex.
Everything above (i.e. left of) anIndex is ok."
+
+ | childIndex childValue index value |
+ index := anIndex.
- | value k n j |
- anIndex = 0 ifTrue:[^self].
- n := tally bitShift: -1.
- k := anIndex.
value := array at: anIndex.
+ [ (childIndex := 2 * index) >= tally or: [
+ "Select the child with the larger value. We know there are two children."
+ childValue := array at: childIndex.
+ (sortBlock
+ ifNil: [ (array at: childIndex + 1) <= childValue ]
+ ifNotNil: [ sortBlock value: (array at: childIndex + 1) value: childValue ])
+ ifTrue: [
+ childValue := array at: (childIndex := childIndex + 1) ].
+ "Check if the value at index is at the right position."
+ sortBlock
+ ifNil: [ value <= childValue ]
+ ifNotNil: [ sortBlock value: value value: childValue ] ] ]
+ whileFalse: [
+ "Move value downwards the tree."
+ array at: index put: childValue.
+ indexUpdateBlock ifNotNil: [ indexUpdateBlock value: childValue value: index ].
+ "Contine from childIndex"
+ index := childIndex ].
+ childIndex = tally ifTrue: [ "Special case: there's only one child."
+ "Check if the value at index is at the right position."
+ childValue := array at: childIndex.
+ (sortBlock
+ ifNil: [ value <= childValue ]
+ ifNotNil: [ sortBlock value: value value: childValue ])
+ ifFalse: [
+ "Move value downwards the tree."
+ array at: index put: childValue.
+ indexUpdateBlock ifNotNil: [ indexUpdateBlock value: childValue value: index ].
+ "Contine from childIndex"
+ index := childIndex ] ].
+ array at: index put: value.
+ indexUpdateBlock ifNotNil: [ indexUpdateBlock value: value value: index ]!
- [k <= n] whileTrue:[
- j := k + k.
- "use max(j,j+1)"
- (j < tally and:[self sorts: (array at: j+1) before: (array at: j)])
- ifTrue:[ j := j + 1].
- "check if position k is ok"
- (self sorts: value before: (array at: j))
- ifTrue:[ "yes -> break loop"
- n := k - 1]
- ifFalse:[ "no -> make room at j by moving j-th element to k-th position"
- array at: k put: (array at: j).
- self updateObjectIndex: k.
- "and try again with j"
- k := j]].
- array at: k put: value.
- self updateObjectIndex: k.!
Item was changed:
----- Method: Heap>>downHeapSingle: (in category 'private-heap') -----
downHeapSingle: anIndex
"This version is optimized for the case when only one element in the receiver can be at a wrong position. It avoids one comparison at each node when travelling down the heap and checks the heap upwards after the element is at a bottom position. Since the probability for being at the bottom of the heap is much larger than for being somewhere in the middle this version should be faster."
+
+ | childIndex index value |
+ index := anIndex.
- | value k n j |
- anIndex = 0 ifTrue:[^self].
- n := tally bitShift: -1.
- k := anIndex.
value := array at: anIndex.
+ [ (childIndex := 2 * index) < tally ] whileTrue:[
+ "Select the child with the larger value. We know there are two children."
+ (sortBlock
+ ifNil: [ (array at: childIndex + 1) <= (array at: childIndex) ]
+ ifNotNil: [ sortBlock value: (array at: childIndex + 1) value: (array at: childIndex) ])
+ ifTrue: [ childIndex := childIndex + 1 ].
+ array at: index put: (array at: childIndex).
+ indexUpdateBlock ifNotNil: [ indexUpdateBlock value: (array at: index) value: index ].
+ "and repeat at the next level"
+ index := childIndex ].
+ childIndex = tally ifTrue: [ "Child with no sibling"
+ array at: index put: (array at: childIndex).
+ indexUpdateBlock ifNotNil: [ indexUpdateBlock value: (array at: index) value: index ].
+ index := childIndex ].
+ array at: index put: value.
+ indexUpdateBlock ifNotNil: [ indexUpdateBlock value: value value: index ].
+ self upHeap: index!
- [k <= n] whileTrue:[
- j := k + k.
- "use max(j,j+1)"
- (j < tally and:[self sorts: (array at: j+1) before: (array at: j)])
- ifTrue:[ j := j + 1].
- array at: k put: (array at: j).
- self updateObjectIndex: k.
- "and try again with j"
- k := j].
- array at: k put: value.
- self updateObjectIndex: k.
- self upHeap: k!
Item was changed:
----- Method: Heap>>growTo: (in category 'growing') -----
growTo: newSize
"Grow to the requested size."
+
| newArray |
newArray := Array new: (newSize max: tally).
+ newArray replaceFrom: 1 to: tally with: array startingAt: 1.
- newArray replaceFrom: 1 to: array size with: array startingAt: 1.
array := newArray!
Item was changed:
----- Method: Heap>>indexUpdateBlock: (in category 'accessing') -----
indexUpdateBlock: aBlockOrNil
+ "aBlockOrNil is either nil or a two argument block. The first argument is the object whose index has changed in the heap, the second is the new index. The block will be evaluated whenever an element is moved in the heap's internal array. If you don't plan to remove elements by index (see #removeAt:), then you should not set this block."
indexUpdateBlock := aBlockOrNil.
!
Item was added:
+ ----- Method: Heap>>isValidHeap (in category 'testing') -----
+ isValidHeap
+
+ "Check the size first."
+ (tally between: 0 and: array size) ifFalse: [ ^false ].
+ "Check the sort order between parent and child nodes."
+ 1 to: (tally bitShift: -1) do: [ :index |
+ | childIndex |
+ childIndex := 2 * index.
+ sortBlock
+ ifNil: [ (array at: index) <= (array at: childIndex) ifFalse: [ ^false ] ]
+ ifNotNil: [ (sortBlock value: (array at: index) value: (array at: childIndex)) ifFalse: [ ^false ] ].
+ childIndex < tally ifTrue: [
+ childIndex := childIndex + 1.
+ sortBlock
+ ifNil: [ (array at: index) <= (array at: childIndex) ifFalse: [ ^false ] ]
+ ifNotNil: [ (sortBlock value: (array at: index) value: (array at: childIndex)) ifFalse: [ ^false ] ] ] ].
+ "Check for elements left in array after tally."
+ tally + 1 to: array size do: [ :index |
+ (array at: index) ifNotNil: [ ^false ] ].
+ ^true!
Item was changed:
----- Method: Heap>>privateRemoveAt: (in category 'private') -----
privateRemoveAt: index
+ "Remove the element at the given index and make sure the sorting order is okay. The value of index must not be larger than tally."
+
- "Remove the element at the given index and make sure the sorting order is okay"
| removed |
removed := array at: index.
+ index = tally ifTrue: [
+ array at: index put: nil.
+ tally := tally - 1.
+ ^removed ].
+ array
+ at: index put: (array at: tally);
+ at: tally put: nil.
- array at: index put: (array at: tally).
- array at: tally put: nil.
tally := tally - 1.
+ 2 * index <= tally "The node at index has at least one child."
+ ifTrue: [ self downHeapSingle: index ]
+ ifFalse: [ self upHeap: index ].
- index > tally ifFalse:[
- "Use #downHeapSingle: since only one element has been removed"
- self downHeapSingle: index].
^removed!
Item was changed:
----- Method: Heap>>privateReverseSort (in category 'private') -----
privateReverseSort
"Arrange to have the array sorted in reverse order.
WARNING: this method breaks the heap invariants. It's up to the sender to restore them afterwards."
+
| oldTally |
+ self deprecated: 'Use #sort if you want to sort.'.
oldTally := tally.
[tally > 1] whileTrue:
[array swap: 1 with: tally.
tally := tally - 1.
self downHeapSingle: 1].
tally := oldTally!
Item was changed:
----- Method: Heap>>removeAt: (in category 'removing') -----
removeAt: index
+ "Remove the element at the given index and make sure the sorting order is okay."
+
+ index > tally ifTrue: [ self errorSubscriptBounds: index ].
- "Remove the element at given position"
- (index < 1 or:[index > tally]) ifTrue:[^self errorSubscriptBounds: index].
^self privateRemoveAt: index!
Item was changed:
----- Method: Heap>>select: (in category 'enumerating') -----
select: aBlock
"Evaluate aBlock with each of my elements as the argument. Collect into
a new collection like the receiver, only those elements for which aBlock
evaluates to true."
| newCollection |
newCollection := self copyEmpty.
+ 1 to: tally do: [ :index |
+ | element |
+ (aBlock value: (element := array at: index)) ifTrue: [
+ newCollection add: element ] ].
- self do:
- [:each |
- (aBlock value: each)
- ifTrue: [newCollection add: each]].
^ newCollection!
Item was added:
+ ----- Method: Heap>>sort (in category 'sorting') -----
+ sort
+ "Fully sort the heap. This method preserves the heap invariants and can thus be sent safely"
+
+ | start end element originalIndexUpdateBlock |
+ end := tally.
+ "Temporarly remove indexUpdateBlock to speed up sorting."
+ originalIndexUpdateBlock := indexUpdateBlock.
+ indexUpdateBlock := nil.
+ [ tally > 1 ] whileTrue: [
+ element := array at: tally.
+ array
+ at: tally put: (array at: 1);
+ at: 1 put: element.
+ tally := tally - 1.
+ self downHeapSingle: 1 ].
+ tally := end.
+ start := 1.
+ originalIndexUpdateBlock ifNil: [
+ "The was no indexUpdateBlock; just reverse the elements"
+ [ start < end ] whileTrue: [
+ element := array at: start.
+ array
+ at: start put: (array at: end);
+ at: end put: element.
+ start := start + 1.
+ end := end - 1 ].
+ ^self ].
+ "Restore indexUpdateBlock, reverse the elements and update the indices."
+ indexUpdateBlock := originalIndexUpdateBlock.
+ start := 1.
+ [ start < end ] whileTrue: [
+ | endValue |
+ element := array at: start.
+ endValue := array at: end.
+ array
+ at: start put: endValue;
+ at: end put: element.
+ indexUpdateBlock
+ value: endValue value: start;
+ value: element value: end.
+ start := start + 1.
+ end := end - 1 ].
+ start = end ifTrue: [ indexUpdateBlock value: (array at: start) value: start ]!
Item was changed:
----- Method: Heap>>sortBlock: (in category 'accessing') -----
sortBlock: aBlock
+
+ | oldIndexUpdateBlock |
sortBlock := aBlock.
+ "Restore the heap invariant."
+ tally <= 1 ifTrue: [ ^self ].
+ oldIndexUpdateBlock := indexUpdateBlock.
+ indexUpdateBlock := nil.
+ (tally bitShift: -1) to: 1 by: -1 do: [ :index | self downHeap: index ].
+ indexUpdateBlock := oldIndexUpdateBlock ifNil: [ ^self ].
+ 1 to: tally do: [ :index |
+ indexUpdateBlock value: (array at: index) value: index ]
+
+ !
- self reSort.!
Item was changed:
----- Method: Heap>>upHeap: (in category 'private-heap') -----
upHeap: anIndex
"Check the heap upwards for correctness starting at anIndex.
Everything below anIndex is ok."
+
+ | index parentValue parentIndex value |
+ anIndex = 1 ifTrue: [ ^self ].
+ value := array at: (index := anIndex).
+ [ index > 1 and: [
+ parentValue := array at: (parentIndex := index bitShift: -1).
+ sortBlock
+ ifNil: [ value <= parentValue ]
+ ifNotNil: [ sortBlock value: value value: parentValue ] ] ]
+ whileTrue: [
+ array at: index put: parentValue.
+ indexUpdateBlock ifNotNil: [ indexUpdateBlock value: parentValue value: index ].
+ index := parentIndex ].
+ array at: index put: value.
+ indexUpdateBlock ifNotNil: [ indexUpdateBlock value: value value: index ]!
- | value k kDiv2 tmp |
- anIndex = 0 ifTrue:[^self].
- k := anIndex.
- value := array at: anIndex.
- [ (k > 1) and:[self sorts: value before: (tmp := array at: (kDiv2 := k bitShift: -1))] ]
- whileTrue:[
- array at: k put: tmp.
- self updateObjectIndex: k.
- k := kDiv2].
- array at: k put: value.
- self updateObjectIndex: k.!
Tobias Pape uploaded a new version of Graphics to project The Trunk:
http://source.squeak.org/trunk/Graphics-topa.341.mcz
==================== Summary ====================
Name: Graphics-topa.341
Author: topa
Time: 1 June 2016, 11:41:14.5378 pm
UUID: 6b532963-62f7-4713-8668-99d5d3c7fc5f
Ancestors: Graphics-topa.340
Let text styels present themselves
=============== Diff against Graphics-topa.340 ===============
Item was added:
+ ----- Method: TextStyle>>asStringOrText (in category 'accessing') -----
+ asStringOrText
+ "be fancy"
+ ^ self defaultFont familyName asText
+ addAttribute: (TextFontReference toFont: self defaultFont);
+ yourself!
Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.1156.mcz
==================== Summary ====================
Name: Morphic-mt.1156
Author: mt
Time: 1 June 2016, 4:09:34.015287 pm
UUID: 522ade56-9b2e-f749-bb5c-cb117aa97c56
Ancestors: Morphic-topa.1155
If #mouseOverForKeyboardFocus is disabled, do not highlight (a.k.a. "look focused") background windows on mouse-enter, even if they are active due to the preference "Windows' Contents Are Always Active".
Note that there is still a bug, which I intend to fix if the event filters make it into the trunk. Namely, if you "debug it" and expression via the context menu, the appearing debugger will not be the top window. An additional click is required. Sorry for this inconvenience.
=============== Diff against Morphic-topa.1155 ===============
Item was changed:
MorphicModel subclass: #SystemWindow
+ instanceVariableNames: 'labelString stripes label closeBox collapseBox paneMorphs paneRects collapsedFrame fullFrame isCollapsed isActive isLookingFocused menuBox mustNotClose labelWidgetAllowance updatablePanes allowReframeHandles labelArea expandBox'
- instanceVariableNames: 'labelString stripes label closeBox collapseBox paneMorphs paneRects collapsedFrame fullFrame isCollapsed isActive menuBox mustNotClose labelWidgetAllowance updatablePanes allowReframeHandles labelArea expandBox'
classVariableNames: 'ClickOnLabelToEdit CloseBoxFrame CloseBoxImageFlat CloseBoxImageGradient CollapseBoxImageFlat CollapseBoxImageGradient DoubleClickOnLabelToExpand ExpandBoxFrame ExpandBoxImageFlat ExpandBoxImageGradient FocusFollowsMouse GradientWindow HideExpandButton MenuBoxFrame MenuBoxImageFlat MenuBoxImageGradient ResizeAlongEdges ReuseWindows TopWindow WindowTitleActiveOnFirstClick WindowsRaiseOnClick'
poolDictionaries: ''
category: 'Morphic-Windows'!
!SystemWindow commentStamp: '<historical>' prior: 0!
SystemWindow is the Morphic equivalent of StandardSystemView -- a labelled container for rectangular views, with iconic facilities for close, collapse/expand, and resizing.
The attribute onlyActiveOnTop, if set to true (and any call to activate will set this), determines that only the top member of a collection of such windows on the screen shall be active. To be not active means that a mouse click in any region will only result in bringing the window to the top and then making it active.!
Item was added:
+ ----- Method: SystemWindow>>activateIfNeeded: (in category 'focus') -----
+ activateIfNeeded: evt
+ "Make me the new key window if needed. Ensure that the focus look matches the keyboard focus."
+
+ (self isKeyWindow not
+ and: [self class windowsRaiseOnClick
+ or: [self windowDecorations anySatisfy: [:morph | morph bounds containsPoint: evt position]] ])
+ ifTrue: [self beKeyWindow]
+ ifFalse: [self updateFocusLookForKeyboardFocus].!
Item was changed:
----- Method: SystemWindow>>handleMouseDown: (in category 'events') -----
handleMouseDown: evt
-
- "If my submorphs handled the events, we still need to use this hook to raise."
- (self isKeyWindow not
- and: [self class windowsRaiseOnClick
- or: [self windowDecorations anySatisfy: [:morph | morph bounds containsPoint: evt position]] ])
- ifTrue: [self beKeyWindow].
+ self activateIfNeeded: evt.
^ super handleMouseDown: evt!
Item was added:
+ ----- Method: SystemWindow>>handleMouseUp: (in category 'events') -----
+ handleMouseUp: evt
+
+ self activateIfNeeded: evt.
+ ^ super handleMouseUp: evt!
Item was added:
+ ----- Method: SystemWindow>>isLookingFocused (in category 'focus') -----
+ isLookingFocused
+
+ ^ isLookingFocused ifNil: [false]!
Item was added:
+ ----- Method: SystemWindow>>isLookingFocused: (in category 'focus') -----
+ isLookingFocused: aBoolean
+
+ isLookingFocused := aBoolean.!
Item was changed:
----- Method: SystemWindow>>lookFocused (in category 'focus') -----
lookFocused
+
+ "Optimize performance."
+ self isLookingFocused ifTrue: [^ self].
+ self isLookingFocused: true.
+
label ifNotNil: [ label color: Color black ].
(self isKeyWindow or: [self class windowTitleActiveOnFirstClick])
ifTrue: [self undimWindowButtons].
self paneColorToUse in: [ : col |
self
setStripeColorsFrom: col ;
adoptPaneColor: col].!
Item was changed:
----- Method: SystemWindow>>lookUnfocused (in category 'focus') -----
lookUnfocused
+
+ "Optimize performance."
+ self isLookingFocused ifFalse: [^ self].
+ self isLookingFocused: false.
+
label ifNotNil: [ label color: Color darkGray ].
self dimWindowButtons.
self paneColorToUseWhenNotActive in: [ : col |
self
setStripeColorsFrom: col ;
adoptPaneColor: col ]!
Item was changed:
----- Method: SystemWindow>>mouseEnter: (in category 'events') -----
mouseEnter: anEvent
"Handle a mouseEnter event, meaning the mouse just entered my bounds with no button pressed. The default response is to let my eventHandler, if any, handle it."
super mouseEnter: anEvent.
+ (self isActive and: [Preferences mouseOverForKeyboardFocus])
+ ifTrue: [self lookFocused].!
- self isActive ifTrue: [self lookFocused].!
Item was changed:
----- Method: SystemWindow>>mouseLeave: (in category 'events') -----
mouseLeave: anEvent
"Handle a mouseEnter event, meaning the mouse just entered my bounds with no button pressed. The default response is to let my eventHandler, if any, handle it."
super mouseLeave: anEvent.
+ (model windowActiveOnFirstClick and: [Preferences mouseOverForKeyboardFocus
+ or: [anEvent hand keyboardFocus notNil and: [anEvent hand keyboardFocus containingWindow ~= self]]])
+ ifTrue: [self lookUnfocused].!
- model windowActiveOnFirstClick ifTrue: [self lookUnfocused].!
Item was changed:
----- Method: SystemWindow>>mouseLeaveDragging: (in category 'events') -----
mouseLeaveDragging: evt
+ "Passivate after drop operations if needed. Unfortunately, we get a leave-dragging event for the system window we want to drag. Watch out for it."
- "Passivate after drop operations if needed."
+ ((model windowActiveOnFirstClick and: [(evt hand submorphs includes: self) not])
+ or: [self isKeyWindow not])
+ ifTrue: [self lookUnfocused].
+
- model windowActiveOnFirstClick ifTrue: [self lookUnfocused].
-
(self isKeyWindow not and: [evt hand hasSubmorphs]) ifTrue:[
self passivateIfNeeded.
evt hand removeMouseListener: self. "no more drop completion possible on submorph"
].!
Item was changed:
----- Method: SystemWindow>>openAsIsIn: (in category 'open/close') -----
openAsIsIn: aWorld
"This msg and its callees result in the window being activeOnlyOnTop"
aWorld addMorph: self.
self beKeyWindow.
+ aWorld startSteppingSubmorphsOf: self.!
- aWorld startSteppingSubmorphsOf: self.
- self activeHand
- releaseKeyboardFocus;
- releaseMouseFocus.!
Item was changed:
----- Method: SystemWindow>>openInWorld: (in category 'open/close') -----
openInWorld: aWorld
"This msg and its callees result in the window being activeOnlyOnTop"
+ ^ self anyOpenWindowLikeMe
- [^ self anyOpenWindowLikeMe
ifEmpty:
[ self
bounds: (RealEstateAgent initialFrameFor: self world: aWorld) ;
openAsIsIn: aWorld ]
ifNotEmptyDo:
[ : windows |
windows anyOne
expand ;
beKeyWindow ;
+ postAcceptBrowseFor: self ].!
- postAcceptBrowseFor: self ].
- ] ensure: [
- self activeHand
- releaseKeyboardFocus;
- releaseMouseFocus. ]!
Item was changed:
----- Method: SystemWindow>>openInWorld:extent: (in category 'open/close') -----
openInWorld: aWorld extent: extent
"This msg and its callees result in the window being activeOnlyOnTop"
+ ^ self anyOpenWindowLikeMe
- [^ self anyOpenWindowLikeMe
ifEmpty:
[ self
position: (RealEstateAgent initialFrameFor: self initialExtent: extent world: aWorld) topLeft ;
extent: extent.
self openAsIsIn: aWorld ]
ifNotEmptyDo:
[ : windows |
windows anyOne
expand ;
beKeyWindow ;
+ postAcceptBrowseFor: self ].!
- postAcceptBrowseFor: self ].
- ] ensure: [
- self activeHand
- releaseKeyboardFocus;
- releaseMouseFocus. ]!
Item was changed:
----- Method: SystemWindow>>passivate (in category 'focus') -----
passivate
"Reconfigure my focus according to preferences."
self isActive ifFalse: [^ self].
self isActive: false.
self isCollapsed ifFalse: [model modelSleep].
self submorphsDo: [:each | each lock].
+ self activeHand keyboardFocus ifNotNil: [:morph |
+ morph containingWindow == self
+ ifTrue: [self activeHand releaseKeyboardFocus]].
+
self lookUnfocused.!
Item was changed:
----- Method: SystemWindow>>updateFocusLookAtHand (in category 'focus') -----
updateFocusLookAtHand
"If there is more than one active window, look for the mouse cursor and update the window focus look accordingly. This method is not on the class-side because we need our world and some active hand."
+ (model windowActiveOnFirstClick and: [Preferences mouseOverForKeyboardFocus])
+ ifFalse: [self updateFocusLookForKeyboardFocus]
+ ifTrue: [
+ ((self class windowsIn: self world)
+ do: [:window | window lookUnfocused];
+ select: [:window | window bounds containsPoint: self activeHand position])
+ ifNotEmpty: [:windowsPointed | windowsPointed first lookFocused "only to foremost window"]].!
- model windowActiveOnFirstClick ifFalse: [^ self].
-
- ((self class windowsIn: self world)
- do: [:window | window lookUnfocused];
- select: [:window | window bounds containsPoint: self activeHand position])
- ifNotEmpty: [:windowsPointed | windowsPointed first lookFocused "only to foremost window"].!
Item was added:
+ ----- Method: SystemWindow>>updateFocusLookForKeyboardFocus (in category 'focus') -----
+ updateFocusLookForKeyboardFocus
+
+ | f w |
+ (((f := self activeHand keyboardFocus) notNil and: [(w := f containingWindow) notNil])
+ and: [w isActive])
+ ifTrue: [
+ (self class windowsIn: self world) do: [:window | window lookUnfocused].
+ w lookFocused]!