Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.1683.mcz
==================== Summary ====================
Name: Morphic-mt.1683
Author: mt
Time: 17 September 2020, 3:38:41.086573 pm
UUID: 146f304e-7d94-624b-9d19-d193c3522b86
Ancestors: Morphic-mt.1682
Fixes a bug in the definition of height-for-width and width-for-height layout behavior.
=============== Diff against Morphic-mt.1682 ===============
Item was changed:
----- Method: Morph>>changesHeightForWidth (in category 'layout-menu') -----
changesHeightForWidth
+ "When both axes are on #spaceFill, the receiver (morph) usually adapts any inner height-for-width layout unless there is more space to fill. Since we cannot know in advance, we assume that an extra layout run might be necessary."
+ ^ (self hResizing == #spaceFill and: [self vResizing == #spaceFill])
+ or: [(self hResizing ~= #shrinkWrap
+ and: [self vResizing = #shrinkWrap])
+ and: [self wrapDirection ~= #none]]!
- ^ (self hResizing ~= #shrinkWrap
- and: [self vResizing = #shrinkWrap])
- and: [self wrapDirection ~= #none]!
Item was changed:
----- Method: Morph>>changesWidthForHeight (in category 'layout-menu') -----
changesWidthForHeight
+ "When both axes are on #spaceFill, the receiver (morph) usually adapts any inner height-for-width layout unless there is more space to fill. Since we cannot know in advance, we assume that an extra layout run might be necessary."
+
+ ^ (self hResizing == #spaceFill and: [self vResizing == #spaceFill])
+ or: [(self hResizing = #shrinkWrap
+ and: [self vResizing ~= #shrinkWrap])
+ and: [self wrapDirection ~= #none]]!
-
- ^ (self hResizing = #shrinkWrap
- and: [self vResizing ~= #shrinkWrap])
- and: [self wrapDirection ~= #none]!
Marcel Taeumel uploaded a new version of ST80 to project The Trunk:
http://source.squeak.org/trunk/ST80-mt.259.mcz
==================== Summary ====================
Name: ST80-mt.259
Author: mt
Time: 17 September 2020, 1:33:37.991573 pm
UUID: 8717279a-d050-7a42-9989-bb849160b60d
Ancestors: ST80-mt.258
Let there be only one queue of deferred actions for all MVC projects to mirror the behavior of Morphic projects.
=============== Diff against ST80-mt.258 ===============
Item was changed:
Object subclass: #ControlManager
instanceVariableNames: 'scheduledControllers activeController activeControllerProcess screenController newTopClicked'
+ classVariableNames: 'DeferredActionQueue'
- classVariableNames: ''
poolDictionaries: ''
category: 'ST80-Controllers'!
!ControlManager commentStamp: '<historical>' prior: 0!
I represent the top level control over scheduling which controller of a view on the screen the user is actively using. ScheduledControllers is the global reference to an instance of me, the one attached to the Project currently being used.!
Item was added:
+ ----- Method: ControlManager class>>addDeferredUIMessage: (in category 'class initialization') -----
+ addDeferredUIMessage: valuableObject
+ "Arrange for valuableObject to be evaluated the next time the controlActivity in any controller becomes active."
+
+ self deferredActionQueue nextPut: valuableObject.!
Item was added:
+ ----- Method: ControlManager class>>deferredActionQueue (in category 'class initialization') -----
+ deferredActionQueue
+
+ ^DeferredActionQueue ifNil: [DeferredActionQueue := SharedQueue new]!
Item was added:
+ ----- Method: ControlManager>>processDeferredActions (in category 'scheduling') -----
+ processDeferredActions
+
+ [self class deferredActionQueue isEmpty]
+ whileFalse: [self class deferredActionQueue next value].!
Item was removed:
- ----- Method: Controller>>addDeferredUIMessage: (in category 'basic control sequence') -----
- addDeferredUIMessage: valuableObject
- "Arrange for valuableObject to be evaluated the next time the
- controlActivity for this controller becomes active."
-
- self deferredActionQueue nextPut: valuableObject!
Item was changed:
----- Method: Controller>>controlActivity (in category 'control defaults') -----
controlActivity
"Pass control to the next control level (that is, to the Controller of a
subView of the receiver's view) if possible. It is sent by
Controller|controlLoop each time through the main control loop. It should
be redefined in a subclass if some other action is needed."
self processDeferredActions.
- Project current world activeController processDeferredActions.
self controlToNextLevel!
Item was changed:
----- Method: Controller>>processDeferredActions (in category 'control defaults') -----
processDeferredActions
+
+ Project current isMVC ifFalse: [^ self].
+ Project current world processDeferredActions.!
-
- [self deferredActionQueue isEmpty]
- whileFalse: [deferredActionQueue next value].!
Item was changed:
----- Method: MVCProject>>addDeferredUIMessage: (in category 'scheduling & debugging') -----
addDeferredUIMessage: valuableObject
"Arrange for valuableObject to be evaluated at a time when the user interface
is in a coherent state."
+ self flag: #discuss. "mt: Why are deferred UI messages shared among all MVC projects?"
+ ControlManager addDeferredUIMessage: valuableObject.!
- world activeController
- ifNotNil: [:controller | controller addDeferredUIMessage: valuableObject]!
Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.1682.mcz
==================== Summary ====================
Name: Morphic-mt.1682
Author: mt
Time: 17 September 2020, 1:11:51.011573 pm
UUID: af1dbefd-44de-e849-b99d-a8d62204a9fc
Ancestors: Morphic-dtl.1681
Fixes come-to-front bug in dialog windows. No behaves like system windows do.
=============== Diff against Morphic-dtl.1681 ===============
Item was added:
+ ----- Method: DialogWindow>>handleMouseDown: (in category 'events') -----
+ handleMouseDown: event
+ "Always bring me to the front since I am modal"
+
+ self comeToFront.
+ ^ super handleMouseDown: event!
Item was changed:
----- Method: DialogWindow>>mouseDown: (in category 'events') -----
mouseDown: event
self stopAutoTrigger.
-
- "Always bring me to the front since I am modal"
- self comeToFront.
(self containsPoint: event position) ifFalse: [
^ self autoCancel
ifTrue: [self cancelDialog]
ifFalse: [self flash]].
event hand
waitForClicksOrDrag: self
event: event
selectors: { nil. nil. nil. #startDrag: }
threshold: HandMorph dragThreshold.!
Marcel Taeumel uploaded a new version of ST80 to project The Trunk:
http://source.squeak.org/trunk/ST80-mt.258.mcz
==================== Summary ====================
Name: ST80-mt.258
Author: mt
Time: 17 September 2020, 9:15:53.534726 am
UUID: c7ff9de0-a71a-4646-a639-211d94848498
Ancestors: ST80-mt.257
Fixes processing of deferred actions in MVC.
Note that windows in MVC delegate control to their sub-controllers, however, remaining the active controller from the project's world perspective (i.e. the controller manager). Thus, we have to process two deferred-action queues in for most cases. For example, the text field in a workspace involves a PluggableTextController, embedded in a StandardSystemController. Any do-it like "Project current addDeferredUIMessage: [...]" will add the message to the StandardSystemController's queue.
=============== Diff against ST80-mt.257 ===============
Item was changed:
----- Method: Controller>>controlActivity (in category 'control defaults') -----
controlActivity
"Pass control to the next control level (that is, to the Controller of a
subView of the receiver's view) if possible. It is sent by
Controller|controlLoop each time through the main control loop. It should
be redefined in a subclass if some other action is needed."
+ self processDeferredActions.
+ Project current world activeController processDeferredActions.
- [self deferredActionQueue isEmpty]
- whileFalse: [deferredActionQueue next value].
self controlToNextLevel!
Item was added:
+ ----- Method: Controller>>processDeferredActions (in category 'control defaults') -----
+ processDeferredActions
+
+ [self deferredActionQueue isEmpty]
+ whileFalse: [deferredActionQueue next value].!
Item was changed:
----- Method: ParagraphEditor>>normalActivity (in category 'controlling') -----
normalActivity
self processKeyboard.
+ self processMouseButtons.
+ super normalActivity.
+ !
- self processMouseButtons!
Marcel Taeumel uploaded a new version of PreferenceBrowser to project The Trunk:
http://source.squeak.org/trunk/PreferenceBrowser-mt.106.mcz
==================== Summary ====================
Name: PreferenceBrowser-mt.106
Author: mt
Time: 17 September 2020, 8:51:08.314726 am
UUID: b9d92cdc-bbf8-6441-bd0a-e3b2a287e934
Ancestors: PreferenceBrowser-mt.105
Let the wizard install FFI through Metacello again to manage different Squeak versions.
Note that the Metacello script was fixed so that it should work for Squeak 5.3, too.
=============== Diff against PreferenceBrowser-mt.105 ===============
Item was changed:
----- Method: PreferenceWizardMorph>>installFFI (in category 'actions - packages') -----
installFFI
+ Metacello new
- " Metacello new
configuration: 'FFI';
+ load.
+ "
- load."
(Installer squeak)
project: 'FFI';
install: 'FFI-Pools';
install: 'FFI-Kernel';
install: 'FFI-Tools';
install: 'FFI-Tests';
+ install: 'FFI-PoolsTests'.
+ "!
- install: 'FFI-PoolsTests'.!
David T. Lewis uploaded a new version of Kernel to project The Trunk:
http://source.squeak.org/trunk/Kernel-dtl.1340.mcz
==================== Summary ====================
Name: Kernel-dtl.1340
Author: dtl
Time: 15 September 2020, 10:28:36.703545 pm
UUID: d155f790-f808-4f68-ae73-3d98434f66d0
Ancestors: Kernel-ul.1339
Implement Sensor eventTimeNow for support of synthesized events. Eliminates the sometimes incorrect assumption that event time stamps must match the obsolete VM millisecond clock, and allows the Windows VM to consistently use native Windows event time stamps in the event queue.
=============== Diff against Kernel-ul.1339 ===============
Item was changed:
Object subclass: #EventSensor
+ instanceVariableNames: 'mouseButtons mousePosition mouseWheelDelta keyboardBuffer interruptKey interruptSemaphore eventQueue inputSemaphore lastEventPoll hasInputSemaphore lastEventTime'
- instanceVariableNames: 'mouseButtons mousePosition mouseWheelDelta keyboardBuffer interruptKey interruptSemaphore eventQueue inputSemaphore lastEventPoll hasInputSemaphore'
classVariableNames: 'ButtonDecodeTable EventPollPeriod EventTicklerProcess InterruptWatcherProcess KeyDecodeTable'
poolDictionaries: 'EventSensorConstants'
category: 'Kernel-Processes'!
!EventSensor commentStamp: 'mt 12/13/2019 14:38' prior: 0!
An EventSensor is an interface to the user input devices.
There is at least one instance of EventSensor named Sensor in the system.
EventSensor is a replacement for the earlier InputSensor implementation based on a set of (optional) event primitives. An EventSensor updates its state when events are received so that all state based users of Sensor (e.g., Sensor keyboard, Sensor leftShiftDown, Sensor mouseButtons) will work exactly as before, by moving the current VM mechanisms into EventSensor itself. An optional input semaphore is part of the new design.
For platforms that support true asynchronous event notification, the semaphore will be signaled to indicate pending events.
On platforms that do not support asynchronous notifications about events, the UI will have to poll EventSensor periodically to read events from the VM.
Instance variables:
mouseButtons <Integer> - mouse button state as replacement for primMouseButtons
mousePosition <Point> - mouse position as replacement for primMousePt
keyboardBuffer <SharedQueue> - keyboard input buffer
interruptKey <Integer> - currently defined interrupt key
interruptSemaphore <Semaphore> - the semaphore signaled when the interruptKey is detected
eventQueue <SharedQueue> - an optional event queue for event driven applications
inputSemaphore <Semaphore>- the semaphore signaled by the VM if asynchronous event notification is supported
lastEventPoll <Integer> - the last millisecondClockValue at which we called fetchMoreEvents
hasInputSemaphore <Boolean> - true if my inputSemaphore has actually been signaled at least once.
Class variables:
ButtonDecodeTable <ByteArray> - maps mouse buttons as reported by the VM to ones reported in the events.
KeyDecodeTable <Dictionary<SmallInteger->SmallInteger>> - maps some keys and their modifiers to other keys (used for instance to map Ctrl-X to Alt-X)
InterruptSemaphore <Semaphore> - signalled by the the VM and/or the event loop upon receiving an interrupt keystroke.
InterruptWatcherProcess <Process> - waits on the InterruptSemaphore and then responds as appropriate.
EventPollPeriod <Integer> - the number of milliseconds to wait between polling for more events in the userInterruptHandler.
EventTicklerProcess <Process> - the process that makes sure that events are polled for often enough (at least every EventPollPeriod milliseconds).
Event format:
The current event format is very simple. Each event is recorded into an 8 element array. All events must provide some SmallInteger ID (the first field in the event buffer) and a time stamp (the second field in the event buffer), so that the difference between the time stamp of an event and the current time can be reported.
Currently, the following events are defined:
Null event
=============
The Null event is returned when the ST side asks for more events but no more events are available.
Structure:
[1] - event type 0
[2-8] - unused
Mouse event structure
==========================
Mouse events are generated when mouse input is detected.
[1] - event type 1
[2] - time stamp
[3] - mouse x position
[4] - mouse y position
[5] - button state; bitfield with the following entries:
1 - 2r001 yellow (e.g., right) button
2 - 2r010 blue (e.g., middle) button
4 - 2r100 red (e.g., left) button
[all other bits are currently undefined]
[6] - modifier keys; bitfield with the following entries:
1 - shift key
2 - ctrl key
4 - (Mac specific) option key
8 - Cmd/Alt key
[all other bits are currently undefined]
[7] - reserved.
[8] - host window id.
Keyboard events
====================
Keyboard events are generated when keyboard input is detected.
[1] - event type 2
[2] - time stamp
[3] - character code (Ascii)
For now the character code is in Mac Roman encoding. See #macToSqueak.
For key press/release (see [4]), character codes are normalized.
[4] - press state; integer with the following meaning
0 - character (aka. key stroke or key still pressed)
1 - key press (aka. key down)
2 - key release (aka. key up)
[5] - modifier keys (same as in mouse events)
For key press/release (see [4]), modifier keys are still accessible.
[6] - character code (Unicode UTF32)
Manual decoding via KeyboardInputInterpreter possible.
For key press/release (see [4]), character codes are normalized.
[7] - reserved.
[8] - host window id.
Mouse-wheel event structure
==========================
Mouse-wheel events are generated when mouse-wheel input is detected.
[1] - event type 7
[2] - time stamp
[3] - horizontal scroll delta
[4] - vertical scroll delta
[5] - button state (same as in mouse events)
[6] - modifier keys (same as in mouse events)
[7] - reserved.
[8] - host window id.
!
Item was changed:
----- Method: EventSensor>>createMouseEvent (in category 'mouse') -----
createMouseEvent
"create and return a new mouse event from the current mouse
position; this is useful for restarting normal event queue
processing after manual polling"
| buttons modifiers pos mapped eventBuffer |
eventBuffer := Array new: 8.
buttons := self peekButtons.
pos := self peekPosition.
modifiers := buttons bitShift: -3.
buttons := buttons bitAnd: 7.
mapped := self mapButtons: buttons modifiers: modifiers.
eventBuffer
at: 1
put: EventTypeMouse;
+ at: 2 put: self eventTimeNow;
- at: 2 put: Time eventMillisecondClock;
at: 3 put: pos x;
at: 4 put: pos y;
at: 5 put: mapped;
at: 6 put: modifiers.
^ eventBuffer!
Item was added:
+ ----- Method: EventSensor>>eventTimeNow (in category 'private') -----
+ eventTimeNow
+ "Answer an event timeStamp that is slightly more recent than that of
+ the most recently processed event. Intended for synthesized events to
+ be processed in line with those from the real event queue."
+
+ ^ lastEventTime + 1.
+ !
Item was changed:
----- Method: EventSensor>>peekEventSynthesized (in category 'private') -----
peekEventSynthesized
"Return a synthesized event. This method is called if an event driven client wants to receive events but the primary user interface is not event-driven (e.g., the receiver does not have an event queue but only updates its state). This can, for instance, happen if a Morphic World is run in an MVC window. To simplify the clients work this method will always return all available keyboard events first, and then (repeatedly) the mouse events. Since mouse events come last, the client can assume that after one mouse event has been received there are no more to come. Note that it is impossible for EventSensor to determine if a mouse event has been issued before so the client must be aware of the possible problem of getting repeatedly the same mouse events. See HandMorph>>processEvents for an example on how to deal with this."
| kbd array buttons pos modifiers mapped |
"First check for keyboard"
array := Array new: 8.
keyboardBuffer isEmpty ifFalse:
["simulate keyboard event"
array at: 1 put: EventTypeKeyboard. "evt type"
+ array at: 2 put: self eventTimeNow. "time stamp"
- array at: 2 put: Time eventMillisecondClock. "time stamp"
array at: 3 put: ((kbd := keyboardBuffer peek) bitAnd: 255). "char code"
array at: 4 put: EventKeyChar. "key press/release"
array at: 5 put: (kbd bitShift: -8). "modifier keys"
^ array].
"Then check for mouse"
pos := mousePosition.
buttons := mouseButtons.
modifiers := buttons bitShift: -3.
buttons := buttons bitAnd: 7.
mapped := self mapButtons: buttons modifiers: modifiers.
array
at: 1 put: EventTypeMouse;
+ at: 2 put: self eventTimeNow;
- at: 2 put: Time eventMillisecondClock;
at: 3 put: pos x;
at: 4 put: pos y;
at: 5 put: mapped;
at: 6 put: modifiers.
^ array
!
Item was changed:
----- Method: EventSensor>>primGetNextEvent: (in category 'private-I/O') -----
primGetNextEvent: array
"Store the next OS event available into the provided array.
Essential. If the VM is not event driven the ST code will fall
back to the old-style mechanism and use the state based
primitives instead."
| kbd buttons modifiers pos mapped |
<primitive: 94>
"Simulate the events"
array at: 1 put: EventTypeNone. "assume no more events"
"First check for keyboard"
kbd := self oldPrimKbdNext.
kbd = nil ifFalse:[
"simulate keyboard event"
array at: 1 put: EventTypeKeyboard. "evt type"
+ array at: 2 put: self eventTimeNow. "time stamp"
- array at: 2 put: Time eventMillisecondClock. "time stamp"
array at: 3 put: (kbd bitAnd: 255). "char code"
array at: 4 put: EventKeyChar. "key press/release"
array at: 5 put: (kbd bitShift: -8). "modifier keys"
^self].
"Then check for mouse"
buttons := self oldPrimMouseButtons.
pos := self oldPrimMousePt.
modifiers := buttons bitShift: -3.
buttons := buttons bitAnd: 7.
mapped := self mapButtons: buttons modifiers: modifiers.
(pos = mousePosition and:[(mapped bitOr: (modifiers bitShift: 3)) = mouseButtons])
ifTrue:[^self].
array
at: 1 put: EventTypeMouse;
+ at: 2 put: self eventTimeNow;
- at: 2 put: Time eventMillisecondClock;
at: 3 put: pos x;
at: 4 put: pos y;
at: 5 put: mapped;
at: 6 put: modifiers.
!
Item was changed:
----- Method: EventSensor>>processEvent: (in category 'private-I/O') -----
processEvent: evt
"Process a single event. This method is run at high priority."
| type buttons window |
type := evt at: 1.
+ lastEventTime := evt at: 2.
"Only process main window events, forward others to host window proxies"
window := evt at: 8.
(window isNil or: [window isZero]) ifTrue:
[window := 1.
evt at: 8 put: window].
window = 1 ifFalse: [
^Smalltalk at: #HostWindowProxy ifPresent: [:w | w processEvent: evt]].
"Tackle mouse events and mouse wheel events first"
(type = EventTypeMouse or: [type = EventTypeMouseWheel])
ifTrue: [buttons := (ButtonDecodeTable at: (evt at: 5) + 1).
evt at: 5 put: (Smalltalk platformName = 'Mac OS'
ifTrue: [ buttons ]
ifFalse: [ self mapButtons: buttons modifiers: (evt at: 6) ]).
self queueEvent: evt.
type = EventTypeMouseWheel
ifTrue: [^ self processMouseWheelEvent: evt].
type = EventTypeMouse
ifTrue: [^ self processMouseEvent: evt]].
"Store the event in the queue if there's any"
type = EventTypeKeyboard
ifTrue: [ "Check if the event is a user interrupt"
((evt at: 4) = EventKeyChar
and: [((evt at: 3)
bitOr: (((evt at: 5)
bitAnd: 8)
bitShift: 8))
= interruptKey])
ifTrue: ["interrupt key is meta - not reported as event"
^ interruptSemaphore signal].
"Decode keys for characters (i.e., duplicate or swap, ctrl <-> alt/cmd)."
(evt at: 4) = EventKeyChar
ifTrue: [ | unicode ascii |
"Copy lookup key first in case of key swap."
unicode := {evt at: 6. evt at: 5}.
ascii := {evt at: 3. evt at: 5}.
KeyDecodeTable "Unicode character first"
at: unicode
ifPresent: [:a | evt at: 6 put: a first;
at: 5 put: a second].
KeyDecodeTable "ASCII character second"
at: ascii
ifPresent: [:a | evt at: 3 put: a first;
at: 5 put: a second]].
self queueEvent: evt.
self processKeyboardEvent: evt .
^self ].
"Handle all events other than Keyboard or Mouse."
self queueEvent: evt.
!
David T. Lewis uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-dtl.1680.mcz
==================== Summary ====================
Name: Morphic-dtl.1680
Author: dtl
Time: 15 September 2020, 4:04:29.45022 pm
UUID: ecb7a7fd-061d-44e0-802f-b08ac8ae9778
Ancestors: Morphic-mt.1679
For MouseEvent>>asMouseMove retain the original event timeStamp. Removes an unnecessary dependency on eventMillisecondClock.
=============== Diff against Morphic-mt.1679 ===============
Item was changed:
----- Method: MouseEvent>>asMouseMove (in category 'converting') -----
asMouseMove
"Convert the receiver into a mouse move"
+ ^MouseMoveEvent new setType: #mouseMove startPoint: position endPoint: position trail: {position. position} buttons: buttons hand: source stamp: timeStamp!
- ^MouseMoveEvent new setType: #mouseMove startPoint: position endPoint: position trail: {position. position} buttons: buttons hand: source stamp: Time eventMillisecondClock!
David T. Lewis uploaded a new version of System to project The Trunk:
http://source.squeak.org/trunk/System-dtl.1172.mcz
==================== Summary ====================
Name: System-dtl.1172
Author: dtl
Time: 15 September 2020, 11:51:49.283423 am
UUID: ff268fb9-4fff-4981-bc66-1b0f2a5e2589
Ancestors: System-mt.1170
Fix Etoys project loading. Update ImageSegment>>reshapeClasses:refStream: to accomodate the elementsForwardIdentityTo: changes from Collections-eem.885.
Also update other methods in ImageSegment and NativeImageSegment similarly on the (untested) assumption that the behavior should remain consistent for image segments. Note that Binding class>>convertInstances in package Environments may require similar attention.
Replaces System-dtl.1171 from inbox (moved to treated)
=============== Diff against System-mt.1170 ===============
Item was changed:
----- Method: ImageSegment>>install (in category 'read/write segment') -----
install
"This operation retrieves the segment if necessary from file storage, installs it in memory, and replaces (using become:) all the root stubs with the reconstructed roots of the segment."
| allObjectsInSegment newRoots |
state = #onFile ifTrue: [self readFromFile].
state = #onFileWithSymbols ifTrue:
[self readFromFileWithSymbols].
(state = #active) | (state = #imported) ifFalse: [self errorWrongState].
allObjectsInSegment := self loadSegmentFrom: segment outPointers: outPointers.
newRoots := allObjectsInSegment first.
self checkAndReportLoadError.
(state = #imported "just came in from exported file" or: [arrayOfRoots isNil "testing..."])
ifTrue: [arrayOfRoots := newRoots]
+ ifFalse: [arrayOfRoots elementsForwardIdentityAndHashTo: newRoots].
- ifFalse: [arrayOfRoots elementsForwardIdentityTo: newRoots].
state := #inactive.
Beeper beepPrimitive!
Item was changed:
----- Method: ImageSegment>>reshapeClasses:refStream: (in category 'fileIn') -----
reshapeClasses: mapFakeClassesToReal refStream: smartRefStream
| bads allVarMaps partials in out perfect |
self flag: #bobconv.
partials := OrderedCollection new.
bads := OrderedCollection new.
allVarMaps := IdentityDictionary new.
mapFakeClassesToReal keysAndValuesDo: [ :aFakeClass :theRealClass |
aFakeClass allInstances do: [ :misShapen |
perfect := smartRefStream convert1: misShapen to: theRealClass allVarMaps: allVarMaps.
bads
detect: [ :x | x == misShapen]
ifNone: [
bads add: misShapen.
partials add: perfect
].
].
].
bads isEmpty ifFalse: [
+ bads asArray elementsForwardIdentityAndHashTo: partials asArray
- bads asArray elementsForwardIdentityTo: partials asArray
].
in := OrderedCollection new.
out := OrderedCollection new.
partials do: [ :each |
perfect := smartRefStream convert2: each allVarMaps: allVarMaps.
in
detect: [ :x | x == each]
ifNone: [
in add: each.
out add: perfect
]
].
in isEmpty ifFalse: [
+ in asArray elementsForwardIdentityAndHashTo: out asArray
- in asArray elementsForwardIdentityTo: out asArray
].
!
Item was changed:
----- Method: NativeImageSegment>>extract (in category 'read/write segment') -----
extract
"This operation replaces (using become:) all the original roots of a segment with segmentRootStubs. Thus the original objects will be reclaimed, and the root stubs will remain to bring the segment back in if it is needed."
Cursor write showWhile: [
state = #inactive ifTrue: [self copyFromRoots: arrayOfRoots sizeHint: 0].
state = #activeCopy ifFalse: [self errorWrongState].
+ arrayOfRoots elementsForwardIdentityAndHashTo:
- arrayOfRoots elementsForwardIdentityTo:
(arrayOfRoots collect: [:r | r rootStubInImageSegment: self]).
state := #active].!
Item was changed:
----- Method: NativeImageSegment>>extractThenInstall (in category 'read/write segment') -----
extractThenInstall
"For testing only"
| allObjectsInSegment newRoots |
state = #activeCopy ifFalse: [self errorWrongState].
+ arrayOfRoots elementsForwardIdentityAndHashTo:
- arrayOfRoots elementsForwardIdentityTo:
(arrayOfRoots collect: [:r | r rootStubInImageSegment: self]).
state := #active.
allObjectsInSegment := self loadSegmentFrom: segment outPointers: outPointers.
newRoots := allObjectsInSegment first.
state := #inactive.
+ arrayOfRoots elementsForwardIdentityAndHashTo: newRoots.!
- arrayOfRoots elementsForwardIdentityTo: newRoots.!
Item was changed:
----- Method: NativeImageSegment>>revert (in category 'read/write segment') -----
revert
"Pretend this segment was never brought in. Check that it has a fileName. Replace (using become:) all the original roots of a segment with segmentRootStubs. Thus the original objects will be reclaimed, and the root stubs will remain to bring the segment back in if it is needed.
How to use revert: In the project, choose 'save for reverting'.
ReEnter the project. Make changes.
Either exit normally, and change will be kept, or
Choose 'Revert to saved version'."
fileName ifNil: [^ self].
(state = #inactive) | (state = #onFile) ifFalse: [^ self].
Cursor write showWhile: [
+ arrayOfRoots elementsForwardIdentityAndHashTo:
- arrayOfRoots elementsForwardIdentityTo:
(arrayOfRoots collect: [:r | r rootStubInImageSegment: self]).
state := #onFile.
segment := nil]
"Old version:
How to use revert: In the project, execute
(Project current projectParameters at: #frozen put: true)
Leave the project. Check that the project went out to disk (it is gray in the Jump to Project list).
ReEnter the project. Hear a plink as it comes in from disk. Make a change.
Exit the project. Choose 'Revert to previous version' in the dialog box.
Check that the project went out to disk (it is gray in the Jump to Project list).
ReEnter the project and see that it is in the original state."!