Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.1783.mcz
==================== Summary ====================
Name: Morphic-mt.1783
Author: mt
Time: 7 October 2021, 3:16:58.720277 pm
UUID: ccc05305-cb74-6841-8a74-ed5a772f7b4b
Ancestors: Morphic-mt.1782
Revises Morphic-mt.1781. Only be a renderer if you have a single submorph. Now you can open a halo on the items in a tree morph again.
Also fixes meta-click+drag bug on morphs that have a flex-shell.
Also fixes change-hierarchy bug on morphs that have a flex-shell.
=============== Diff against Morphic-mt.1782 ===============
Item was changed:
----- Method: MorphicHaloDispatcher>>dispatchHalo:createFor: (in category 'dispatching') -----
dispatchHalo: anEvent createFor: aContainer
"Invoke a halo on any aContainer's submorph that wants it. Dispatch uses anEvent's #position. The dispatch only ends in that container if no other morph wants it. Note that the event's #shiftPressed state determines whether the dispatch goes innermost-to-outermost (if pressed) or the other way around (if not pressed).
If there already is a halo, check whether the event still points into the same hierarchy. If it does, do nothing here but rely on the halo itself to process the event (see implementors of #transferHalo:from:). If, however, the event points to a different hierarchy in the container, invoke a new halo and discard the current one. We do this here because the current halo should not bother with its container but only its #target."
| stack innermost haloTarget |
"The stack is the frontmost (i.e. innermost) to backmost (i.e. outermost) morph."
stack := (aContainer morphsAt: anEvent position unlocked: true) select:
+ [ : each | each wantsHaloFromClick or: [ each isRenderer ] ].
- [ : each | each wantsHaloFromClick ].
"self assert: [ stack last == aContainer ]."
innermost := anEvent hand halo
ifNil: [ stack first ]
ifNotNil:
[ : existingHalo |
"self assert: [ existingHalo wantsHaloFromClick not ]. "
stack
detect: [ : each | each owner == aContainer ]
ifFound:
[ : topInContainer | "Is existingHalo's target part of the same topInContainer as the morph clicked?"
(existingHalo target withAllOwners includes: topInContainer)
ifTrue: [ "same hierarchy, let #transferHalo: continue to handle it for now." ^ false ]
ifFalse:
[ "different hierarchy, remove + add."
anEvent hand removeHalo.
anEvent shiftPressed
ifTrue: [ stack first ]
ifFalse: [ topInContainer ] ] ]
ifNone: [ "existingHalo is on the World, defer to #transferHalo: for now." ^ false ] ].
"If modifier key is pressed, start at innermost (the target), otherwise the outermost (direct child of the world (self))."
haloTarget := (innermost == aContainer or: [ anEvent shiftPressed ])
ifTrue: [ innermost ]
ifFalse:
[ "Find the outermost owner that wants it. Ignore containment above aContainer."
stack := innermost withAllOwners.
(stack first: (stack findFirst: [ : each | each owner == aContainer ])) reversed
+ detect: [ : each | each wantsHaloFromClick or: [ each isRenderer ] ]
- detect: [ : each | each wantsHaloFromClick ]
ifNone: [ "haloTarget has its own mouseDown handler, don't halo." ^ false ] ].
"Now that we have the haloTarget, show the halo."
self invokeHaloOrMove: anEvent on: haloTarget.
^ true!
Item was changed:
----- Method: MorphicHaloDispatcher>>invokeHaloOrMove:on: (in category 'invoking') -----
invokeHaloOrMove: anEvent on: aMorph
"Special gestures (cmd-mouse on the Macintosh; Alt-mouse on Windows and Unix) allow a mouse-sensitive morph to be moved or bring up a halo for the morph."
+ | h doNotDrag |
- | h tfm doNotDrag |
anEvent hand newMouseFocus: aMorph event: anEvent.
h := anEvent hand halo.
"Prevent wrap around halo transfers originating from throwing the event back in"
doNotDrag := false.
h ifNotNil:[
(h innerTarget == aMorph) ifTrue:[doNotDrag := true].
(h innerTarget hasOwner: aMorph) ifTrue:[doNotDrag := true].
(aMorph hasOwner: h target) ifTrue:[doNotDrag := true]].
+ h := aMorph addHalo: anEvent.
- tfm := (aMorph transformedFrom: nil) inverseTransformation.
-
- "cmd-drag on flexed morphs works better this way"
- h := aMorph addHalo: (anEvent transformedBy: tfm).
h setProperty: #lastHaloDispatcher toValue: self.
doNotDrag ifTrue:[^ true].
"Initiate drag transition if requested"
anEvent hand
waitForClicksOrDrag: h
+ event: anEvent
- event: (anEvent transformedBy: tfm)
selectors: { nil. nil. nil. #startDragTarget:. }
threshold: HandMorph dragThreshold.
"Pass focus explicitly here"
anEvent hand newMouseFocus: h.
"Reset temporary cursors to make available halo interaction visible."
anEvent hand showTemporaryCursor: nil.
^ true!
Item was changed:
----- Method: TransformMorph>>isRenderer (in category 'classification') -----
isRenderer
+ ^ submorphs size = 1
- ^ true
!
Item was changed:
----- Method: TransformMorph>>morphicLayerNumber (in category 'submorphs - layers') -----
morphicLayerNumber
+ ^ self isRenderer
+ ifTrue: [self renderedMorph morphicLayerNumber]
- ^ self hasSubmorphs
ifFalse: [super morphicLayerNumber]
+ !
- ifTrue: [self firstSubmorph morphicLayerNumber]!
Item was changed:
----- Method: TransformMorph>>renderedMorph (in category 'classification') -----
renderedMorph
"We are a renderer. Answer appropriately."
+ ^ self isRenderer
- ^ self hasSubmorphs
ifTrue: [self firstSubmorph renderedMorph]
+ ifFalse: [super renderedMorph]!
- ifFalse: [self]!
Item was changed:
----- Method: TransformMorph>>wantsHaloFromClick (in category 'halos and balloon help') -----
wantsHaloFromClick
+ ^ self hasSubmorphs not!
- ^ self renderedMorph == self!
Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.1782.mcz
==================== Summary ====================
Name: Morphic-mt.1782
Author: mt
Time: 6 October 2021, 11:00:59.501367 am
UUID: 917d7198-f778-8d40-94ef-8a0d6a48186c
Ancestors: Morphic-mt.1781
Fixes regression in grip resizing.
=============== Diff against Morphic-mt.1781 ===============
Item was changed:
----- Method: BottomLeftGripMorph>>apply: (in category 'target resize') -----
apply: delta
| oldBounds |
oldBounds := self target bounds.
self target
bounds: (oldBounds origin + (delta x @ 0) corner: oldBounds corner + (0 @ delta y)).
self flag: #workaround. "mt: Due to a layout-specific 'let us start in the top-left corner of a layout cell'-behavior, we have to go up the owner chain and propagate the delta. See Morph >> #layoutInBounds:positioning: and there section 1.2."
self target allOwnersDo:
[:anOwner |
(anOwner layoutPolicy notNil and: [anOwner ~~ Project current world])
+ ifTrue: [anOwner left: anOwner left + delta x]].!
- ifTrue: [anOwner left: owner left + delta x]].!
Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.1781.mcz
==================== Summary ====================
Name: Morphic-mt.1781
Author: mt
Time: 6 October 2021, 10:15:44.239651 am
UUID: 9fef6ccb-8df4-8047-8b0b-f8292ad3c397
Ancestors: Morphic-ul.1780
Fixes infinite-loop bug regarding #topRendererOrSelf by promoting TransformMorph to be an #isRenderer too, which makes sense because it clips and translates its contents already and usually has only a single submorph. The #transform could also scale and rotate. In the long term, the few extra features of TransformationMorph could be merged into TransformMorph. This would make it easier for clients to pick the right one. :-)
See http://lists.squeakfoundation.org/pipermail/squeak-dev/2021-October/216637.…
=============== Diff against Morphic-ul.1780 ===============
Item was changed:
----- Method: MorphicHaloDispatcher>>dispatchHalo:transferInwardsFrom: (in category 'dispatching') -----
dispatchHalo: event transferInwardsFrom: currentTarget
| localEvent world |
"Note that a halo usually attaches to the outermost (or top) renderer in a composition around the rendered morph. Thus, we have to lookup that inner (or rendered) morph first when transferring the halo inwards in the hierarchy of submorphs."
currentTarget renderedMorph submorphsDo: [:nextTarget |
localEvent := event transformedBy: (nextTarget transformedFrom: currentTarget).
(nextTarget fullContainsPoint: localEvent position) ifTrue: [
+ ^ nextTarget renderedMorph wantsHaloFromClick
- ^ nextTarget wantsHaloFromClick
ifTrue: [self invokeHalo: localEvent on: nextTarget]
ifFalse: [self dispatchHalo: localEvent transferInwardsFrom: nextTarget]]].
"We're at the bottom most level; throw the event back up to the root to find recipient"
event hand removeHalo.
Preferences maintainHalos ifFalse: [
(world := currentTarget world) ifNil: [ ^ false ].
localEvent := event transformedBy: (currentTarget transformedFrom: world) inverseTransformation.
world processEvent: localEvent resetHandlerFields].
^ false!
Item was added:
+ ----- Method: TransformMorph>>innocuousName (in category 'naming') -----
+ innocuousName
+
+ | r |
+ ^ (r := self renderedMorph) == self
+ ifTrue: [super innocuousName]
+ ifFalse: [r innocuousName]!
Item was added:
+ ----- Method: TransformMorph>>isRenderer (in category 'classification') -----
+ isRenderer
+
+ ^ true
+ !
Item was added:
+ ----- Method: TransformMorph>>renderedMorph (in category 'classification') -----
+ renderedMorph
+ "We are a renderer. Answer appropriately."
+
+ ^ self hasSubmorphs
+ ifTrue: [self firstSubmorph renderedMorph]
+ ifFalse: [self]!
Item was changed:
----- Method: TransformMorph>>wantsHaloFromClick (in category 'halos and balloon help') -----
wantsHaloFromClick
+
+ ^ self renderedMorph == self!
- ^ false!
Item was removed:
- ----- Method: TransformationMorph>>innocuousName (in category 'naming') -----
- innocuousName
- | r |
- ^ (r := self renderedMorph) == self
- ifTrue: [super innocuousName] ifFalse: [r innocuousName]!
Item was removed:
- ----- Method: TransformationMorph>>isRenderer (in category 'classification') -----
- isRenderer
-
- ^ true
- !
Item was removed:
- ----- Method: TransformationMorph>>renderedMorph (in category 'classification') -----
- renderedMorph
- "We are a renderer. Answer appropriately."
-
- submorphs isEmpty ifTrue: [^self].
- ^self firstSubmorph renderedMorph!
Item was removed:
- ----- Method: TransformationMorph>>wantsHaloFromClick (in category 'halos and balloon help') -----
- wantsHaloFromClick
-
- ^ self renderedMorph == self!
Levente Uzonyi uploaded a new version of Sound to project The Trunk:
http://source.squeak.org/trunk/Sound-ct.82.mcz
==================== Summary ====================
Name: Sound-ct.82
Author: ct
Time: 3 October 2021, 3:21:00.283874 pm
UUID: 61a3c1d0-1c49-d542-8624-096b1b67e309
Ancestors: Sound-eem.81
Fixes SoundRecorder accesses to CanRecordWhilePlaying by always using the preference getter. As the class variable is nil in current Trunk images, you could not even open the Multimedia category in the parts bin before.
Removes the initialization of CanRecordWhilePlaying to support lazy default values from the preference getter. Also, this initialize method apparently has never been called in the current Trunk image.
=============== Diff against Sound-eem.81 ===============
Item was removed:
- ----- Method: SoundRecorder class>>initialize (in category 'class initialization') -----
- initialize
- "SoundRecorder initialize"
- "Details: Some computers cannot record and playback sound at the same time. If CanRecordWhilePlaying is false, then the SoundRecorder alternates between recording and playing. If it is true, sounds can be playing during recording."
-
- CanRecordWhilePlaying := false.
- !
Item was changed:
----- Method: SoundRecorder>>pause (in category 'recording controls') -----
pause
"Go into pause mode. The record level continues to be updated, but no sound is recorded."
paused := true.
((currentBuffer ~~ nil) and: [nextIndex > 1])
ifTrue: [self emitPartialBuffer.
self allocateBuffer].
soundPlaying ifNotNil: [
soundPlaying pause.
soundPlaying := nil].
"Note: there can be problems if canRecordWhilePlaying is true. Recorders which only pause will inhibit other recorders from recording. I chose to make #stopPlaying unconditional in a subclass. The same might be appropriate here at the expense of making recorders resumable"
+ self class canRecordWhilePlaying ifFalse: [self stopRecording].!
- CanRecordWhilePlaying ifFalse: [self stopRecording].
- !
Item was changed:
----- Method: SoundRecorder>>resumeRecording (in category 'recording controls') -----
resumeRecording
"Continue recording from the point at which it was last paused."
self flag: #bob.
"Note: If canRecordWhilePlaying is true, then recordings may never get started (at least by this method). One possibility, used in a subclass, is to make the #startPlaying unconditional. Another would be to use #startPlaying instead of #resumePlaying in appropriate cases"
+ self class canRecordWhilePlaying ifFalse: [self startRecording].
- CanRecordWhilePlaying ifFalse: [self startRecording].
paused := false.
!
Item was changed:
----- Method: SoundRecorder>>startRecording (in category 'recording controls') -----
startRecording
"Turn on the sound input driver and start the recording process. Initially, recording is paused.
If the primStartRecordingDesiredSampleRate:... fails it almost certainly means we have no usable
sound input device. Rather than having the prim raise a failure error we let it quietly do nothing
(since I hate trying to debug errors inside a critical block) and check the actual sampling rate later.
If the sampling rate is 0 we know the startup failed and raise an application level Signal to let any
user code know about the problem.
You might think we should also use the stopRecording message to close things down cleanly but
that simply results in astorm of attempts to start recording so it is simpler to let it be deluded. An
attempts to start recording will repeat the test and thereby handle any plug-in hardware etc."
recordLevel ifNil: [recordLevel := 0.5]. "lazy initialization"
+ self class canRecordWhilePlaying ifFalse: [SoundPlayer shutDown: true].
- CanRecordWhilePlaying ifFalse: [SoundPlayer shutDown: true].
recordProcess ifNotNil: [self stopRecording].
paused := true.
meteringBuffer := SoundBuffer newMonoSampleCount: 1024.
meterLevel := 0.
self allocateBuffer.
Smalltalk newExternalSemaphoreDo: [ :semaphore :index |
bufferAvailableSema := semaphore.
self primStartRecordingDesiredSampleRate: samplingRate asInteger
stereo: stereo
semaIndex: index ].
RecorderActive := true.
samplingRate := self primGetActualRecordingSampleRate.
samplingRate = 0 ifTrue: [ Warning signal: 'SoundRecorder: unable to connect to sound input device'].
self primSetRecordLevel: (1000.0 * recordLevel) asInteger.
recordProcess := [self recordLoop] newProcess.
recordProcess priority: Processor userInterruptPriority.
recordProcess resume!
Eliot Miranda uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-eem.1416.mcz
==================== Summary ====================
Name: Kernel-eem.1416
Author: eem
Time: 1 October 2021, 2:37:05.661504 pm
UUID: 2b78c119-0d77-4333-a40c-efd59f951f13
Ancestors: Kernel-ul.1415
No point wasting time with the isFinite check in fromIEEE64Bit:; multipying nan or infinity by 1.0 yields teh same result. So save time by always multiplying by 1.0
=============== Diff against Kernel-ul.1415 ===============
Item was changed:
----- Method: Float class>>fromIEEE64Bit: (in category 'instance creation') -----
fromIEEE64Bit: anInteger
"Convert the given 64 bit word (which is supposed to be a positive 64-bit value) from
a 64 bit IEEE floating point representation into an actual Squeak float object (being
64 bits wide). Should only be used for conversion in FloatArrays or likewise objects."
| value |
value := self basicNew: 2.
value
basicAt: 1 put: (anInteger bitShift: -32);
basicAt: 2 put: (anInteger bitAnd: 16rFFFFFFFF).
+ ^value * 1.0 "reduce to SmallFloat64 if possible"!
- ^value isFinite
- ifTrue: [value * 1.0] "reduce to SmallFloat64 if possible"
- ifFalse: [value]!