The Trunk: Morphic-mt.1728.mcz

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

The Trunk: Morphic-mt.1728.mcz

commits-2
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!