[squeak-dev] The Trunk: Morphic-mt.1610.mcz

commits at source.squeak.org commits at source.squeak.org
Wed Dec 18 15:31:55 UTC 2019


Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.1610.mcz

==================== Summary ====================

Name: Morphic-mt.1610
Author: mt
Time: 18 December 2019, 4:31:47.223146 pm
UUID: 569aa27b-a8eb-0247-a758-b9ef6f53fa97
Ancestors: Morphic-mt.1609

Fixes a serious regression in text widgets and all other scroll panes.

- There were too many layout invalidations when scrolling through a pane's scroll bars. See #moveSliderTo: for the fix.
- There was a control-flow contract violation in ScrollPane >> #scrollToShow:.
- The text field discarderd mark-and-point information when replacing its editor. See, for example, #scrollSelectionIntoView:.
- All transform morphs triggered redraw requests on offset updates even if the new offset was not different. That made code in ScrollPanes unnecessarily complex.

I documented all the other quirks to be tackled after the 5.3 release. :-)

=============== Diff against Morphic-mt.1609 ===============

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 := 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].!
- 	self owner ifNotNil: [:o | o layoutChanged].!

Item was changed:
  ----- Method: PluggableTextMorph>>mouseLeave: (in category 'event handling') -----
  mouseLeave: event
  	"Save the selection interval for later."
  
+ 	self flag: #fixIntervalCache. "mt: We should find a better design for discarding unused text editors in text morphs and restoring them on demand."
+ 	selectionInterval := textMorph editor markIndex to: textMorph editor pointIndex -1.
- 	selectionInterval := textMorph editor selectionInterval.
  
  	super mouseLeave: event.
  
  	Preferences mouseOverForKeyboardFocus
  		ifTrue: [event hand releaseKeyboardFocus: self]!

Item was changed:
  ----- Method: PluggableTextMorph>>printIt (in category 'menu commands') -----
  printIt
  	| oldEditor |
  	textMorph editor selectFrom: selectionInterval first to: selectionInterval last;
  						model: model.  "For, eg, evaluateSelection"
  	textMorph handleEdit: [(oldEditor := textMorph editor) evaluateSelectionAndDo:
  		[:result |
+ 		self flag: #fixIntervalCache. "mt: We should find a better design for discarding unused text editors in text morphs and restoring them on demand."
+ 		selectionInterval := oldEditor markIndex to: oldEditor pointIndex -1.
- 		selectionInterval := oldEditor selectionInterval.
  		textMorph installEditorToReplace: oldEditor.
  		textMorph handleEdit: [oldEditor afterSelectionInsertAndSelect: result printString].
+ 		selectionInterval := oldEditor markIndex to: oldEditor pointIndex -1.
- 		selectionInterval := oldEditor selectionInterval.
  	
  		textMorph editor selectFrom: selectionInterval first to: selectionInterval last.
  		self scrollSelectionIntoView]]!

Item was changed:
  ----- Method: PluggableTextMorph>>scrollSelectionIntoView: (in category 'editor access') -----
  scrollSelectionIntoView: event 
  	"Scroll my text into view. Due to line composition mechanism, we must never use the right of a character block because the lines last character block right value always comes from a global container and is *not* line specific."
+ 
+ 	self flag: #fixIntervalCache. "mt: We should find a better design for discarding unused text editors in text morphs and restoring them on demand."
+ 	selectionInterval := textMorph editor markIndex to: textMorph editor pointIndex - 1.
  	
- 	selectionInterval := textMorph editor selectionInterval.
- 	
  	textMorph editor hasSelection
  		ifFalse: [self scrollToShow: (textMorph editor startBlock withWidth: 1)]
  		ifTrue: [
  			self scrollToShow: (textMorph editor startBlock topLeft corner: textMorph editor stopBlock bottomLeft).
  			self scrollToShow: (textMorph editor pointBlock withWidth: 1). "Ensure text cursor visibility."].
  		
  	^ true!

Item was changed:
  ----- Method: ScrollPane>>scrollToShow: (in category 'scrolling') -----
  scrollToShow: aRectangle
  
  	| newOffset |
  	newOffset := self offsetToShow: aRectangle.
+ 	self hScrollBar setValue: newOffset x.
+ 	self vScrollBar setValue: newOffset y.!
- 	scroller offset = newOffset ifTrue: [^ self].
- 	scroller offset: newOffset.
- 	self layoutChanged.!

Item was changed:
  ----- Method: Slider>>computeSlider (in category 'geometry') -----
  computeSlider
  	| r v |
  	r := self roomToMove.
  	v := self maximumValue = self minimumValue
  		ifTrue: [0]
  		ifFalse: [(value - self minimumValue) / (self maximumValue - self minimumValue)].
  	self descending
  		ifFalse:
+ 			[self moveSliderTo: (self orientation == #horizontal
- 			[slider position: (self orientation == #horizontal
  				ifTrue: [r topLeft + ((r width * v) asInteger @ 0)]
  				ifFalse: [r topLeft + (0 @ (r height * v)  asInteger)])]
  		ifTrue:
+ 			[self moveSliderTo: (self orientation == #horizontal
- 			[slider position: (self orientation == #horizontal
  				ifTrue:	[r bottomRight - ((r width * v) asInteger @ 0)]
  				ifFalse:	[r bottomRight - ((0 @ (r height * v) asInteger))])].
+ 	self resizeSliderTo: self sliderExtent.!
- 	slider extent: self sliderExtent!

Item was added:
+ ----- Method: Slider>>moveSliderTo: (in category 'geometry') -----
+ moveSliderTo: newPosition
+ 	"Sliently move the slider (or thumb) to not trigger any #layoutChanged events."
+ 	
+ 	| delta |
+ 	self flag: #codeDuplication. "mt: We need a better way to silently do position changes. See Morph >> #position:."
+ 	
+ 	delta := (newPosition - slider position) rounded.
+ 	delta = (0 at 0) ifTrue: [^ self].
+ 	
+ 	slider privateFullMoveBy: delta.
+ 	self changed.
+ 	!

Item was added:
+ ----- Method: Slider>>resizeSliderTo: (in category 'geometry') -----
+ resizeSliderTo: newExtent
+ 	
+ 	slider extent: newExtent.!

Item was changed:
  ----- Method: Slider>>showSliderShadow (in category 'other events') -----
  showSliderShadow
  
  	sliderShadow color: self sliderShadowColor.
  	sliderShadow cornerStyle: slider cornerStyle.
+ 	sliderShadow privateBounds: slider bounds. "mt: Avoid #layoutChanged. See #moveSliderTo:."
- 	sliderShadow bounds: slider bounds.
  	sliderShadow show.!

Item was changed:
  ----- Method: TextEditor>>stateArray (in category 'initialize-release') -----
  stateArray
  	^ {ChangeText.
  		FindText.
  		history ifNil: [TextEditorCommandHistory new]. "Convert old instances"
+ 		self markIndex to: self pointIndex - 1.
- 		self selectionInterval.
  		self startOfTyping.
  		emphasisHere}!

Item was changed:
  ----- Method: TransformMorph>>offset: (in category 'accessing') -----
  offset: newOffset
  
+ 	self offset = newOffset ifTrue: [^ self].
  	transform := transform withOffset: newOffset - self innerBounds topLeft.
+ 	self changed.!
- 	self changed!



More information about the Squeak-dev mailing list