Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.1731.mcz
==================== Summary ====================
Name: Morphic-mt.1731
Author: mt
Time: 2 March 2021, 11:44:21.476687 am
UUID: d06129c7-0def-1645-9066-c8a5720bf5d2
Ancestors: Morphic-mt.1730
Adds the possibility to handle #ownerChanged through composition (instead of subclassing/overwriting). Note that #cull: also works with symbols and message sends, not just blocks. :-) Got inspired by #eventHandler and how #mouseDown: (etc.) is implemented in Morph.
Use it to extract Etoys-specific background morph and grid.
=============== Diff against Morphic-mt.1730 ===============
Item was changed:
+ ----- Method: Morph>>ownerChanged (in category 'layout') -----
- ----- Method: Morph>>ownerChanged (in category 'change reporting') -----
ownerChanged
"This morph's owner has changed its geometry and is about to update its layout. This is a simple layout hook to update this morph's geometry according to its owner.
For more advanced strategies, use a LayoutPolicy with some LayoutProperties. See #layoutPolicy: and maybe also #doLayoutIn:."
+ self snapToEdgeIfAppropriate.
+
+ self ownerChangedHandler
+ ifNotNil: [:handler | handler cull: self].!
- self snapToEdgeIfAppropriate.!
Item was added:
+ ----- Method: Morph>>ownerChangedHandler (in category 'layout') -----
+ ownerChangedHandler
+
+ ^ self valueOfProperty: #ownerChangedHandler!
Item was added:
+ ----- Method: Morph>>ownerChangedHandler: (in category 'layout') -----
+ ownerChangedHandler: aHandler
+
+ self
+ setProperty: #ownerChangedHandler
+ toValue: aHandler.
+
+ self layoutChanged.!
Item was changed:
----- Method: MorphicProject class>>applyUserInterfaceTheme (in category 'preferences') -----
applyUserInterfaceTheme
self current addDeferredUIMessage: [
"After all immediate changes where applied, we can reset to values that match the current world configuration:"
self worldGridOrigin: nil.
self worldGridModulus: nil.
+ self worldGridEnabled
- self current world griddingOn
ifTrue: [self current world firstHand turnOnGridding]].!
Item was changed:
----- Method: MorphicProject class>>worldGridEnabled (in category 'preferences') -----
worldGridEnabled
<preference: 'Snap Morphs to World Grid'
categoryList: #('Morphic' 'Tools')
description: 'When true, morphs placed in the world will align with a regular grid. This includes tool windows.'
type: #Boolean>
+
+ | world |
+ world := self current world.
+ ^ self current isMorphic and: [world layoutPolicy notNil and: [world layoutPolicy isGridLayout]]!
- ^ self current isMorphic and: [self current world griddingOn]!
Item was changed:
----- Method: MorphicProject class>>worldGridEnabled: (in category 'preferences') -----
worldGridEnabled: aBooleanOrNil
+ (aBooleanOrNil ifNil: [false])
+ ifTrue: [self current world layoutPolicy: GridLayout new]
+ ifFalse: [self current world layoutPolicy: nil].
- (aBooleanOrNil ifNil: [false]) = self current world griddingOn
- ifFalse: [self current world griddingOnOff].
"Auto-configure origin and modulus to match world properties."
self worldGridOrigin: nil.
self worldGridModulus: nil.
"Snap to grid when dragging something."
+ self worldGridEnabled
- self current world griddingOn
ifTrue: [self current world firstHand turnOnGridding]
ifFalse: [self current world firstHand turnOffGridding].!
Item was changed:
BorderedMorph subclass: #PasteUpMorph
+ instanceVariableNames: 'presenter model cursor padding turtleTrailsForm turtlePen lastTurtlePositions isPartsBin indicateCursor wantsMouseOverHalos worldState'
- instanceVariableNames: 'presenter model cursor padding backgroundMorph turtleTrailsForm turtlePen lastTurtlePositions isPartsBin indicateCursor wantsMouseOverHalos worldState'
classVariableNames: 'GlobalCommandKeysEnabled WindowEventHandler'
poolDictionaries: ''
category: 'Morphic-Worlds'!
!PasteUpMorph commentStamp: '<historical>' prior: 0!
A morph whose submorphs comprise a paste-up of rectangular subparts which "show through". Anything called a 'Playfield' is a PasteUpMorph.
Facilities commonly needed on pages of graphical presentations and on simulation playfields, such as the painting of new objects, turtle trails, gradient fills, background paintings, parts-bin behavior, collision-detection, etc., are (or will be) provided.
A World, the entire Smalltalk screen, is a PasteUpMorph. A World responds true to isWorld. Morph subclasses that have specialized menus (BookMorph) build them in the message addBookMenuItemsTo:hand:. A PasteUpMorph that is a world, builds its menu in HandMorph buildWorldMenu.
presenter A Presenter in charge of stopButton stepButton and goButton,
mouseOverHalosEnabled soundsEnabled fenceEnabled coloredTilesEnabled.
model <not used>
cursor ??
padding ??
backgroundMorph A Form that covers the background.
turtleTrailsForm Moving submorphs may leave trails on this form.
turtlePen Draws the trails.
lastTurtlePositions A Dictionary of (aPlayer -> aPoint) so turtle trails can be drawn
only once each step cycle. The point is the start of the current stroke.
isPartsBin If true, every object dragged out is copied.
autoLineLayout ??
indicateCursor ??
resizeToFit ??
wantsMouseOverHalos If true, simply moving the cursor over a submorph brings up its halo.
worldState If I am also a World, keeps the hands, damageRecorder, stepList etc.
griddingOn If true, submorphs are on a grid
!
Item was changed:
----- Method: PasteUpMorph>>drawOn: (in category 'drawing') -----
drawOn: aCanvas
"Draw in order:
- background color
- - grid, if any
- - background sketch, if any
- Update and draw the turtleTrails form. See the comment in updateTrailsForm.
- cursor box if any
Later (in drawSubmorphsOn:) I will skip drawing the background sketch."
"draw background fill"
super drawOn: aCanvas.
- "draw grid"
- (self griddingOn and: [self gridVisible])
- ifTrue:
- [aCanvas fillRectangle: self bounds
- fillStyle: (self
- gridFormOrigin: self gridOrigin
- grid: self gridModulus
- background: nil
- line: Color lightGray)].
-
- "draw background sketch."
- backgroundMorph ifNotNil: [
- self clipSubmorphs ifTrue: [
- aCanvas clipBy: self clippingBounds
- during: [ :canvas | canvas fullDrawMorph: backgroundMorph ]]
- ifFalse: [ aCanvas fullDrawMorph: backgroundMorph ]].
-
"draw turtle trails"
(lastTurtlePositions isNil or: [lastTurtlePositions isEmpty]) ifFalse:[
self updateTrailsForm.
].
turtleTrailsForm
ifNotNil: [aCanvas paintImage: turtleTrailsForm at: self position].
"draw cursor"
(submorphs notEmpty and: [self indicateCursor])
ifTrue:
[aCanvas
frameRectangle: self selectedRect
width: 2
color: Color black]!
Item was removed:
- ----- Method: PasteUpMorph>>drawSubmorphsOn: (in category 'painting') -----
- drawSubmorphsOn: aCanvas
- "Display submorphs back to front, but skip my background sketch."
-
- | drawBlock |
- submorphs isEmpty ifTrue: [^self].
- drawBlock := [:canvas | submorphs reverseDo: [:m | m ~~ backgroundMorph ifTrue: [ canvas fullDrawMorph: m ]]].
- self clipSubmorphs
- ifTrue: [aCanvas clipBy: self clippingBounds during: drawBlock]
- ifFalse: [drawBlock value: aCanvas]!
Item was removed:
- ----- Method: PasteUpMorph>>gridVisible (in category 'gridding') -----
- gridVisible
-
- ^ self hasProperty: #gridVisible!
Item was removed:
- ----- Method: PasteUpMorph>>gridVisibleOnOff (in category 'gridding') -----
- gridVisibleOnOff
-
- self setProperty: #gridVisible toValue: self gridVisible not.
- self changed!
Item was removed:
- ----- Method: PasteUpMorph>>gridVisibleString (in category 'gridding') -----
- gridVisibleString
- "Answer a string to be used in a menu offering the opportunity
- to show or hide the grid"
- ^ (self gridVisible
- ifTrue: ['<yes>']
- ifFalse: ['<no>'])
- , 'grid visible when gridding' translated!
Item was removed:
- ----- Method: PasteUpMorph>>griddingOn (in category 'gridding') -----
- griddingOn
-
- ^ self layoutPolicy notNil and: [self layoutPolicy isGridLayout]!
Item was removed:
- ----- Method: PasteUpMorph>>griddingOnOff (in category 'gridding') -----
- griddingOnOff
- "Change grid layout. Consider the #clearArea to ignore docking bars and other adhereing morphs."
-
- self layoutPolicy: (self griddingOn ifFalse: [GridLayout new]).!
Item was removed:
- ----- Method: PasteUpMorph>>griddingString (in category 'gridding') -----
- griddingString
- "Answer a string to use in a menu offering the user the
- opportunity to start or stop using gridding"
- ^ (self griddingOn
- ifTrue: ['<yes>']
- ifFalse: ['<no>'])
- , 'use gridding' translated!
Item was removed:
- ----- Method: PasteUpMorph>>privateRemoveMorph: (in category 'private') -----
- privateRemoveMorph: aMorph
- backgroundMorph == aMorph ifTrue: [ backgroundMorph := nil ].
- ^super privateRemoveMorph: aMorph.
- !
Item was removed:
- ----- Method: PasteUpMorph>>setGridSpec (in category 'gridding') -----
- setGridSpec
- "Gridding rectangle provides origin and modulus"
- | response result |
- response := UIManager default
- request: 'New grid origin (usually 0@0):' translated
- initialAnswer: self gridOrigin printString.
- response isEmpty ifTrue: [^ self].
- result := [Compiler evaluate: response] ifError: [^ self].
- (result isPoint and: [(result >= (0@0))])
- ifTrue: [self gridOrigin: result]
- ifFalse: [self inform: ('Must be a Point with coordinates (for example 10@10)' translated )].
-
- response := UIManager default
- request: 'New grid spacing:' translated
- initialAnswer: self gridModulus printString.
- response isEmpty ifTrue: [^ self].
- result := [Compiler evaluate: response] ifError: [^ self].
- (result isPoint and: [(result > (0@0)) ])
- ifTrue: [self gridModulus: result]
- ifFalse: [self inform: ('Must be a Point with coordinates (for example 10@10)' translated )].
-
- !
Marcel Taeumel uploaded a new version of MorphicTests to project The Trunk:
http://source.squeak.org/trunk/MorphicTests-mt.72.mcz
==================== Summary ====================
Name: MorphicTests-mt.72
Author: mt
Time: 2 March 2021, 11:03:22.265687 am
UUID: b86bc3c1-fdde-7343-9628-073d9dd73d70
Ancestors: MorphicTests-mt.71
More tests for the new grid layout.
=============== Diff against MorphicTests-mt.71 ===============
Item was changed:
----- Method: GridLayoutTest>>test01Position (in category 'tests') -----
test01Position
+ | m o |
- | m |
m := self addMorph.
+ o := container position.
{
0@0 . 0@0 .
9@9 . 0@0 .
10@10 . 20@20 .
25@25 . 20@20
} pairsDo: [:newPosition :expectedGrid |
+ m position: newPosition + o.
- m position: newPosition.
container fullBounds.
+ self assert: expectedGrid + o equals: m position].!
- self assert: expectedGrid equals: m position].!
Item was added:
+ ----- Method: GridLayoutTest>>test05SnapToEdge (in category 'tests') -----
+ test05SnapToEdge
+ "The grid should be ignored for morphs that snap to their owner's edges."
+
+ | m |
+ m := Morph new color: Color random; extent: 10@10; yourself.
+ container addMorph: m.
+
+ "1) Manual snap-to-edge will not work."
+ m position: 0@(100 - 10).
+ container fullBounds.
+ self assert: 0@100 equals: m position.
+
+ "2) Use snap-to-edge property."
+ m setToAdhereToEdge: #bottom.
+ container fullBounds.
+ self assert: 0@(100 - 10) equals: m position.!
Item was added:
+ ----- Method: GridLayoutTest>>test06Origin (in category 'tests') -----
+ test06Origin
+ "The grid's origin should be relative to its morph's position so that the morph can be moved around without the grid changing."
+
+ container position: 0@0.
+ container removeAllMorphs.
+ self test01Position.
+
+ container position: 10@10.
+ container removeAllMorphs.
+ self test01Position.!
Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.1730.mcz
==================== Summary ====================
Name: Morphic-mt.1730
Author: mt
Time: 2 March 2021, 11:01:40.072687 am
UUID: 5fa729ff-1ebb-3a4e-8283-f88485971bd6
Ancestors: Morphic-mt.1729
A fix and a tweak.
(Note that it is interesting that damage-recording-based drawing via #changed and deferred layout computation via #layoutChanged are in conflict with each other. Also see #privateInvalidateMorph: and its senders.)
=============== Diff against Morphic-mt.1729 ===============
Item was changed:
----- Method: Morph>>position: (in category 'geometry') -----
position: aPoint
"Change the position of this morph, which is the top left corner of its bounds."
| delta box |
delta := (aPoint - self bounds topLeft) rounded.
"Skip drawing and layout updates for null changes."
(delta x = 0 and: [delta y = 0])
ifTrue: [^ self].
"Optimize drawing. Record one damage rectangle for short distance and two damage rectangles for large distances."
+ box := fullBounds ifNil: [self outerBounds]. "Avoid premature layout computation. Like in #extent: and #changed."
- box := self fullBounds.
(delta dotProduct: delta) > 100 "More than 10 pixels?"
ifTrue: [self
invalidRect: box;
invalidRect: (box translateBy: delta)]
ifFalse: [self
invalidRect: (box merge: (box translateBy: delta))].
"Move this morph and *all* of its submorphs."
self privateFullMoveBy: delta.
"For all known layout policies, my layout and the layout of my children is fine. Only the layout of my owner might be affected. So, tell about it."
self owner ifNotNil: [:o |
self flag: #todo. "mt: Maybe we can save a lot of effort and troubles by only calling #layoutChanged if the owner has a layout policy installed? Take the thumbs of scroll-bars as an example..."
o layoutChanged].!
Item was changed:
----- Method: Morph>>setToAdhereToEdge: (in category 'menus') -----
setToAdhereToEdge: anEdge
anEdge ifNil: [^ self].
anEdge == #none ifTrue: [^ self removeProperty: #edgeToAdhereTo].
self setProperty: #edgeToAdhereTo toValue: anEdge.
+ self layoutChanged.
!
Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.1728.mcz
==================== Summary ====================
Name: Morphic-mt.1728
Author: mt
Time: 1 March 2021, 12:21:45.616905 pm
UUID: 9034e981-d83b-c344-a079-e9eb55c8115f
Ancestors: Morphic-mt.1727
Increases robustness during layout computation. Similar to WorldState >> #displayWorldSafely:. Here, faulty layout policies will be disabled to keep the environment responsive.
Note that you can try breaking #doLayoutIn: and then take a look at all those #fullBounds sends. (After reverting the last change via the emergency evaluator, of course.)
=============== Diff against Morphic-mt.1727 ===============
Item was changed:
----- Method: Morph>>adjustLayoutBounds (in category 'layout') -----
adjustLayoutBounds
"Adjust the receivers bounds depending on the resizing strategy imposed"
| hFit vFit box sbox myExtent myOrigin myBox |
hFit := self hResizing.
vFit := self vResizing.
(hFit == #shrinkWrap or:[vFit == #shrinkWrap]) ifFalse:[^self]. "not needed"
(self cellSpacing == #none and: [self listSpacing == #none]) ifFalse: [
self flag: #todo. "mt: Find a way to make cell sizes accessible from here."
+ self cellSpacing: #none; listSpacing: #none.
self notify: 'It is not possible to shrink-wrap around submorphs when the layout policy reserves extra cell space. At this point, we have no access to that extra cell space and we do not know whether the submorph did make use of that extra space. So, shrink-wrapping could make the bounds very unstable.\\Please either reset #cellSpacing and #listSpacing - or change the resizing strategy to #rigid or #spaceFill.' withCRs.
^ self].
box := self layoutBounds.
sbox := self submorphBoundsForShrinkWrap outsetBy: self cellInset.
myExtent := box extent.
myOrigin := box origin.
hFit == #shrinkWrap ifTrue:[
myExtent := sbox extent x @ myExtent y.
myOrigin := sbox origin x @ myOrigin y].
vFit == #shrinkWrap ifTrue:[
myExtent := myExtent x @ sbox extent y.
myOrigin := myOrigin x @ sbox origin y].
"Make sure we don't get smaller than minWidth/minHeight"
myExtent x < self minWidth ifTrue:[
myExtent := (myExtent x max:
(self minWidth - self bounds width + self layoutBounds width)) @ myExtent y].
myExtent y < self minHeight ifTrue:[
myExtent := myExtent x @ (myExtent y max:
(self minHeight - self bounds height + self layoutBounds height))].
myBox := myOrigin extent: myExtent.
self setLayoutBoundsFromLayout: myBox.!
Item was changed:
----- Method: Morph>>buildDebugMenu: (in category 'debug and other') -----
buildDebugMenu: aHand
"Answer a debugging menu for the receiver. The hand argument is seemingly historical and plays no role presently"
| aMenu aPlayer |
aMenu := MenuMorph new defaultTarget: self.
aMenu addStayUpItem.
(self hasProperty: #errorOnDraw) ifTrue:
[aMenu add: 'start drawing again' translated action: #resumeAfterDrawError.
aMenu addLine].
(self hasProperty: #errorOnStep) ifTrue:
[aMenu add: 'start stepping again' translated action: #resumeAfterStepError.
aMenu addLine].
+ (self hasProperty: #errorOnLayout) ifTrue:
+ [aMenu add: 'start layouting again' translated action: #resumeAfterLayoutError.
+ aMenu addLine].
aMenu add: 'inspect morph' translated action: #inspectInMorphic:.
aMenu add: 'inspect owner chain' translated action: #inspectOwnerChain.
Smalltalk isMorphic ifFalse:
[aMenu add: 'inspect morph (in MVC)' translated action: #inspect].
self isMorphicModel ifTrue:
[aMenu add: 'inspect model' translated target: self model action: #inspect;
add: 'explore model' translated target: self model action: #explore].
(aPlayer := self player) ifNotNil:
[aMenu add: 'inspect player' translated target: aPlayer action: #inspect].
aMenu add: 'explore morph' translated target: self selector: #exploreInMorphic:.
aMenu addLine.
aPlayer ifNotNil:
[ aMenu add: 'viewer for Player' translated target: self player action: #beViewed.
aMenu balloonTextForLastItem: 'Opens a viewer on my Player -- this is the same thing you get if you click on the cyan "View" halo handle' translated ].
aMenu add: 'viewer for Morph' translated target: self action: #viewMorphDirectly.
aMenu balloonTextForLastItem: 'Opens a Viewer on this Morph, rather than on its Player' translated.
aMenu addLine.
aPlayer ifNotNil:
[aPlayer class isUniClass ifTrue: [
aMenu add: 'browse player class' translated target: aPlayer selector: #haveFullProtocolBrowsedShowingSelector: argumentList: #(nil)]].
aMenu add: 'browse morph class' translated target: self selector: #browseHierarchy.
(self isMorphicModel)
ifTrue: [aMenu
add: 'browse model class'
target: self model
selector: #browseHierarchy].
aMenu addLine.
self addViewingItemsTo: aMenu.
aMenu
add: 'make own subclass' translated action: #subclassMorph;
add: 'save morph in file' translated action: #saveOnFile;
addLine;
add: 'call #tempCommand' translated action: #tempCommand;
add: 'define #tempCommand' translated action: #defineTempCommand;
addLine;
add: 'control-menu...' translated target: self selector: #invokeMetaMenu:;
add: 'edit balloon help' translated action: #editBalloonHelpText.
^ aMenu!
Item was added:
+ ----- Method: Morph>>doLayout (in category 'layout') -----
+ doLayout
+
+ self doLayoutIn: self layoutBounds.!
Item was added:
+ ----- Method: Morph>>doLayoutSafely (in category 'layout') -----
+ doLayoutSafely
+ "Also see #resumeAfterLayoutError."
+
+ [fullBounds] whileNil: [
+ [self doLayout] on: Error, Halt, Warning do: [:error |
+
+ | errorMorph |
+ (error signalerContext
+ findContextSuchThat: [:context |
+ context receiver isMorph and: [context receiver layoutPolicy notNil]])
+ ifNil: [^ Project current primitiveError: error description]
+ ifNotNil: [:errorContext | errorMorph := errorContext receiver].
+ errorMorph
+ instVarNamed: #fullBounds
+ put: (errorMorph instVarNamed: #bounds).
+ (Warning handles: error) ifFalse: [
+ "Disable the policy unless it is a warning, which should be secured where signaled to ease debugging."
+ errorMorph
+ setProperty: #errorOnLayout toValue: errorMorph layoutPolicy;
+ setProperty: #layoutPolicy toValue: nil. "Avoid #layoutChanged!!"].
+
+ ToolSet debugException: error]].!
Item was changed:
----- Method: Morph>>fullBounds (in category 'layout') -----
fullBounds
+ "Return the bounding box of the receiver and all its children. Recompute the layout if necessary. See #layoutChanged."
+
+ ^ fullBounds ifNil: [self doLayoutSafely. fullBounds]!
- "Return the bounding box of the receiver and all its children. Recompute the layout if necessary."
- fullBounds ifNotNil:[^fullBounds].
- "Errors at this point can be critical so make sure we catch 'em all right"
- [self doLayoutIn: self layoutBounds] on: Error, Warning, Halt do:[:ex|
- "This should do it unless you don't screw up the bounds"
- fullBounds := bounds.
- ex pass].
- ^fullBounds!
Item was added:
+ ----- Method: Morph>>resumeAfterLayoutError (in category 'debug and other') -----
+ resumeAfterLayoutError
+ "Resume layouting after an error has occured."
+
+ self layoutPolicy: (self valueOfProperty: #errorOnLayout ifAbsent: [^ self]).
+ self removeProperty:#errorOnLayout.!
Item was changed:
----- Method: MorphicDebugger class>>openOn:context:label:contents:fullView: (in category 'opening') -----
openOn: processToDebug context: context label: title contents: contentsStringOrNil fullView: full
| debugger uiBlock |
debugger := self new
process: processToDebug context: context;
errorWasInUIProcess: (Project current spawnNewProcessIfThisIsUI: processToDebug).
uiBlock := [
full
ifTrue: [debugger openFullNoSuspendLabel: title]
ifFalse: [debugger openNotifierNoSuspendContents: contentsStringOrNil label: title].
+ "Try layouting the debugger tool at least once to avoid freeze."
+ debugger topView ifNotNil: [:window |
+ "There are way too many #fullBounds sends. Layout errors might already have happened."
+ window allMorphsDo: [:m | (m hasProperty: #errorOnLayout) ifTrue: [self error: 'Layout error']].
+ window world doLayout. "Not safely!!"].
"Try drawing the debugger tool at least once to avoid freeze."
debugger topView ifNotNil: [:window | window world displayWorld. "Not safely!!"].
].
"Schedule debugging in a deferred UI message if necessary. Note that only the ui process should execute ui code."
(Project current uiProcess isActiveProcess not or: [processToDebug isActiveProcess])
ifTrue: [Project current addDeferredUIMessage: uiBlock]
ifFalse: uiBlock.
processToDebug suspend.
"Get here only if active process is not the process-to-debug. So in tests, use a helper process if you want to access this return value."
^ debugger!
Marcel Taeumel uploaded a new version of Tools to project The Trunk:
http://source.squeak.org/trunk/Tools-mt.1027.mcz
==================== Summary ====================
Name: Tools-mt.1027
Author: mt
Time: 1 March 2021, 11:19:25.66938 am
UUID: 4a78193f-b0aa-1b42-9f4a-d588b979d0b6
Ancestors: Tools-mt.1026
Let warnings appear as "normal" as possible via #debugException:.
Note that the "normal" contents are prepared only in ToolSet >> #handleWarning: for unhandled warnings, which is transparent to the signaler. This interface, however, is for exception handlers that want to allow for post-exception debugging, which can also catch warnings.
=============== Diff against Tools-mt.1026 ===============
Item was changed:
----- Method: StandardToolSet class>>debugException: (in category 'debugging') -----
debugException: anException
"For convenience. Construct a helper process to debug an exception that occurred in the active process later on so that the active process can (try to) resume. Uses a temporary variable to access and copy the signaler context now before it gets GC'ed."
| helperProcess |
helperProcess := (Process
forContext: anException signalerContext copyStack
priority: Processor activeProcess priority)
shouldResumeFromDebugger: false;
yourself.
Project current addDeferredUIMessage: [
helperProcess
debugWithTitle: anException description
+ full: false
+ contents: ((anException isKindOf: Warning)
+ ifTrue: [anException messageText])].!
- full: false].!