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

commits at source.squeak.org commits at source.squeak.org
Thu Feb 26 17:19:46 UTC 2015


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

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

Name: Morphic-mt.760
Author: mt
Time: 26 February 2015, 6:19:14.906 pm
UUID: fb8f4f20-e595-d444-a291-58885547c05f
Ancestors: Morphic-topa.759

Corner rounding refactored. Does not rely on (spooky) CornerRounder implementation anymore. Many hacks for that CornerRounder could be removed from Morphic.

A preference can be used to choose the preferred corner radius for rounded morphs. (Preferences > Morphic > Preferred Corner Radius) Subclasses may override the drawing of corners as needed. See draw* methods.

=============== Diff against Morphic-topa.759 ===============

Item was removed:
- ----- Method: Canvas>>roundCornersOf:during: (in category 'drawing-general') -----
- roundCornersOf: aMorph during: aBlock
- 	^self roundCornersOf: aMorph in: aMorph bounds during: aBlock!

Item was removed:
- ----- Method: Canvas>>roundCornersOf:in:during: (in category 'drawing-general') -----
- roundCornersOf: aMorph in: bounds during: aBlock
- 	^aBlock value!

Item was removed:
- ----- Method: FormCanvas>>roundCornersOf:in:during: (in category 'drawing-general') -----
- roundCornersOf: aMorph in: bounds during: aBlock
- 	aMorph wantsRoundedCorners ifFalse:[^aBlock value].
- 	(self seesNothingOutside: (CornerRounder rectWithinCornersOf: bounds))
- 		ifTrue: ["Don't bother with corner logic if the region is inside them"
- 				^ aBlock value].
- 	CornerRounder roundCornersOf: aMorph on: self in: bounds
- 		displayBlock: aBlock
- 		borderWidth: aMorph borderWidthForRounding
- 		corners: aMorph roundedCorners!

Item was changed:
  ----- Method: HandMorph>>fullDrawOn: (in category 'drawing') -----
  fullDrawOn: aCanvas 
  	"A HandMorph has unusual drawing requirements:
  		1. the hand itself (i.e., the cursor) appears in front of its submorphs
  		2. morphs being held by the hand cast a shadow on the world/morphs below
  	The illusion is that the hand plucks up morphs and carries them above the world."
  
  	"Note: This version caches an image of the morphs being held by the hand for
  	 better performance. This cache is invalidated if one of those morphs changes."
  
+ 	| disableCaching subBnds |
- 	| disableCaching subBnds roundCorners rounded |
  	self visible ifFalse: [^self].
  	(aCanvas isVisible: self fullBounds) ifFalse: [^self].
  	(self hasProperty: #errorOnDraw) ifTrue:[^self drawErrorOn: aCanvas].
  	disableCaching := false.
  	disableCaching 
  		ifTrue: 
  			[self nonCachingFullDrawOn: aCanvas.
  			^self].
  	submorphs isEmpty 
  		ifTrue: 
  			[cacheCanvas := nil.
  			^self drawOn: aCanvas].	"just draw the hand itself"
  	subBnds := Rectangle merging: (submorphs collect: [:m | m fullBounds]).
  	self updateCacheCanvas: aCanvas.
  	(cacheCanvas isNil 
  		or: [cachedCanvasHasHoles and: [cacheCanvas depth = 1]]) 
  			ifTrue: 
  				["could not use caching due to translucency; do full draw"
  
  				self nonCachingFullDrawOn: aCanvas.
  				^self].
  
- 	"--> begin rounded corners hack <---"
- 	roundCorners := cachedCanvasHasHoles == false 
- 				and: [submorphs size = 1 and: [submorphs first wantsRoundedCorners]].
- 	roundCorners 
- 		ifTrue: 
- 			[rounded := submorphs first.
- 			aCanvas asShadowDrawingCanvas translateBy: self shadowOffset
- 				during: 
- 					[:shadowCanvas | 
- 					shadowCanvas roundCornersOf: rounded
- 						during: 
- 							[(subBnds areasOutside: (rounded boundsWithinCorners 
- 										translateBy: self shadowOffset negated)) 
- 								do: [:r | shadowCanvas fillRectangle: r color: Color black]]].
- 			aCanvas roundCornersOf: rounded
- 				during: 
- 					[aCanvas 
- 						drawImage: cacheCanvas form
- 						at: subBnds origin
- 						sourceRect: cacheCanvas form boundingBox].
- 			^self drawOn: aCanvas	"draw the hand itself in front of morphs"].
- 	"--> end rounded corners hack <---"
- 
  	"draw the shadow"
  	aCanvas asShadowDrawingCanvas translateBy: self shadowOffset
  		during: 
  			[:shadowCanvas | 
  			cachedCanvasHasHoles 
  				ifTrue: 
  					["Have to draw the real shadow of the form"
  
  					shadowCanvas paintImage: cacheCanvas form at: subBnds origin]
  				ifFalse: 
  					["Much faster if only have to shade the edge of a solid rectangle"
  
  					(subBnds areasOutside: (subBnds translateBy: self shadowOffset negated)) 
  						do: [:r | shadowCanvas fillRectangle: r color: Color black]]].
  
  	"draw morphs in front of the shadow using the cached Form"
  	cachedCanvasHasHoles 
  		ifTrue: [aCanvas paintImage: cacheCanvas form at: subBnds origin]
  		ifFalse: 
  			[aCanvas 
  				drawImage: cacheCanvas form
  				at: subBnds origin
  				sourceRect: cacheCanvas form boundingBox].
  	self drawOn: aCanvas	"draw the hand itself in front of morphs"!

Item was changed:
  Object subclass: #Morph
  	instanceVariableNames: 'bounds owner submorphs fullBounds color extension'
+ 	classVariableNames: 'PreferredCornerRadius'
- 	classVariableNames: ''
  	poolDictionaries: ''
  	category: 'Morphic-Kernel'!
  
  !Morph commentStamp: 'efc 2/26/2003 20:01' prior: 0!
  A Morph (from the Greek "shape" or "form") is an interactive graphical object. General information on the Morphic system can be found at http://minnow.cc.gatech.edu/squeak/30. 
  
  Morphs exist in a tree, rooted at a World (generally a PasteUpMorph). The morphs owned by a morph are its submorphs. Morphs are drawn recursively; if a Morph has no owner it never gets drawn. To hide a Morph and its submorphs, set its #visible property to false using the #visible: method. 
  
  The World (screen) coordinate system is used for most coordinates, but can be changed if there is a TransformMorph somewhere in the owner chain. 
  
  My instance variables have accessor methods (e.g., #bounds, #bounds:). Most users should use the accessor methods instead of using the instance variables directly.
  
  Structure:
  instance var 	Type 			Description 
  bounds 			Rectangle 		A Rectangle indicating my position and a size that will enclose 									me. 
  owner 			Morph		 	My parent Morph, or nil for the top-level Morph, which is a
   				or nil			world, typically a PasteUpMorph.
  submorphs 		Array 			My child Morphs. 
  fullBounds 		Rectangle 		A Rectangle minimally enclosing me and my submorphs. 
  color 			Color 			My primary color. Subclasses can use this in different ways. 
  extension 		MorphExtension Allows extra properties to be stored without adding a
  				or nil  				storage burden to all morphs. 
  
  By default, Morphs do not position their submorphs. Morphs may position their submorphs directly or use a LayoutPolicy to automatically control their submorph positioning.
  
  Although Morph has some support for BorderStyle, most users should use BorderedMorph if they want borders.!

Item was added:
+ ----- Method: Morph class>>preferredCornerRadius (in category 'preferences') -----
+ preferredCornerRadius
+ 
+ 	<preference: 'Preferred Corner Radius'
+ 		category: 'Morphic'
+ 		description: 'If a morph wants rounded corners, use this radius. May be overwritten in subclasses.'
+ 		type: #Number>
+ 	^ PreferredCornerRadius ifNil: [6]!

Item was added:
+ ----- Method: Morph class>>preferredCornerRadius: (in category 'preferences') -----
+ preferredCornerRadius: anInteger
+ 
+ 	PreferredCornerRadius := anInteger.!

Item was changed:
  ----- Method: Morph>>boundsWithinCorners (in category 'drawing') -----
  boundsWithinCorners
+ 	"Return a single sub-rectangle that lies entirely inside corners
+ 	that are made by me.
+ 	Used to identify large regions of window that do not need to be redrawn."
  
+ 	^ self wantsRoundedCorners
+ 		ifTrue: [self bounds insetBy: 0 at self class preferredCornerRadius]
+ 		ifFalse: [self bounds]
+ !
- 	^ CornerRounder rectWithinCornersOf: self bounds!

Item was changed:
  ----- Method: Morph>>drawDropHighlightOn: (in category 'drawing') -----
  drawDropHighlightOn: aCanvas
+ 
  	self highlightedForDrop ifTrue: [
+ 		self wantsRoundedCorners
+ 			ifTrue: [aCanvas frameRoundRect: self fullBounds radius: self class preferredCornerRadius width: 1 color: self dropHighlightColor]
+ 			ifFalse: [aCanvas frameRectangle: self fullBounds color: self dropHighlightColor]].!
- 		aCanvas frameRectangle: self fullBounds color: self dropHighlightColor].!

Item was changed:
  ----- Method: Morph>>drawDropShadowOn: (in category 'drawing') -----
  drawDropShadowOn: aCanvas
  
  	aCanvas 
  		translateBy: self shadowOffset 
  		during: [ :shadowCanvas |
+ 			(shadowCanvas isVisible: self bounds) ifTrue: [
+ 				self wantsRoundedCorners
+ 					ifTrue: [shadowCanvas fillRoundRect: self bounds radius: self class preferredCornerRadius fillStyle: self shadowColor]
+ 					ifFalse: [shadowCanvas fillRectangle: self bounds fillStyle: self shadowColor]]].
- 			shadowCanvas shadowColor: self shadowColor.
- 			shadowCanvas roundCornersOf: self during: [ 
- 				(shadowCanvas isVisible: self bounds) ifTrue:
- 					[shadowCanvas fillRectangle: self bounds fillStyle: self fillStyle]]
- 		].
  !

Item was changed:
  ----- Method: Morph>>drawMouseDownHighlightOn: (in category 'drawing') -----
  drawMouseDownHighlightOn: aCanvas
+ 
  	self highlightedForMouseDown ifTrue: [
+ 		self wantsRoundedCorners
+ 			ifTrue: [aCanvas frameRoundRect: self fullBounds radius: self class preferredCornerRadius width: 1 color: self color darker darker]
+ 			ifFalse: [aCanvas frameRectangle: self fullBounds color: self color darker darker]].!
- 		aCanvas frameRectangle: self fullBounds color: self color darker darker].!

Item was changed:
  ----- Method: Morph>>drawOn: (in category 'drawing') -----
  drawOn: aCanvas
  
+ 	self wantsRoundedCorners
+ 		ifTrue: [aCanvas frameAndFillRoundRect: self bounds radius: self class preferredCornerRadius fillStyle: self fillStyle borderWidth: self borderStyle width borderColor: self borderStyle color]
+ 		ifFalse: [aCanvas fillRectangle: self bounds fillStyle: self fillStyle borderStyle: self borderStyle].
+ 	
- 	aCanvas fillRectangle: self bounds fillStyle: self fillStyle borderStyle: self borderStyle.
  !

Item was changed:
  ----- Method: Morph>>fullDrawOn: (in category 'drawing') -----
  fullDrawOn: aCanvas
  	"Draw the full Morphic structure on the given Canvas"
  
  	self visible ifFalse: [^ self].
  	(aCanvas isVisible: self fullBounds) ifFalse:[^self].
  	(self hasProperty: #errorOnDraw) ifTrue:[^self drawErrorOn: aCanvas].
  	"Note: At some point we should generalize this into some sort of 
  	multi-canvas so that we can cross-optimize some drawing operations."
+ 
  	"Pass 1: Draw eventual drop-shadow"
  	self hasDropShadow ifTrue: [self drawDropShadowOn: aCanvas].
  	(self hasRolloverBorder and: [(aCanvas seesNothingOutside: self bounds) not])
  		ifTrue: [self drawRolloverBorderOn: aCanvas].
  
  	"Pass 2: Draw receiver itself"
+ 	(aCanvas isVisible: self bounds) ifTrue:[aCanvas drawMorph: self].
+ 	self drawSubmorphsOn: aCanvas.
+ 	self drawDropHighlightOn: aCanvas.
+ 	self drawMouseDownHighlightOn: aCanvas.!
- 	aCanvas roundCornersOf: self during:[
- 		(aCanvas isVisible: self bounds) ifTrue:[aCanvas drawMorph: self].
- 		self drawSubmorphsOn: aCanvas.
- 		self drawDropHighlightOn: aCanvas.
- 		self drawMouseDownHighlightOn: aCanvas].!

Item was removed:
- ----- Method: PluggableCanvas>>roundCornersOf:in:during: (in category 'drawing-general') -----
- roundCornersOf: aMorph in: bounds during: aBlock
- 	aMorph wantsRoundedCorners ifFalse:[^aBlock value].
- 	(self seesNothingOutside: (CornerRounder rectWithinCornersOf: bounds))
- 		ifTrue: ["Don't bother with corner logic if the region is inside them"
- 				^ aBlock value].
- 	CornerRounder roundCornersOf: aMorph on: self in: bounds
- 		displayBlock: aBlock
- 		borderWidth: aMorph borderWidthForRounding
- 		corners: aMorph roundedCorners!

Item was changed:
  ----- Method: WorldState>>displayWorld:submorphs: (in category 'update cycle') -----
  displayWorld: aWorld submorphs: submorphs
  	"Update this world's display."
  
+ 	| deferredUpdateMode handsToDraw allDamage handDamageRects worldDamageRects |
- 	| deferredUpdateMode handsToDraw allDamage |
  
  	submorphs do: [:m | m fullBounds].  "force re-layout if needed"
  	self checkIfUpdateNeeded ifFalse: [^ self].  "display is already up-to-date"
  
  	deferredUpdateMode := self doDeferredUpdatingFor: aWorld.
  	deferredUpdateMode ifFalse: [self assuredCanvas].
- 	canvas roundCornersOf: aWorld during:[ | handDamageRects worldDamageRects |
- 		worldDamageRects := self drawWorld: aWorld submorphs: submorphs invalidAreasOn: canvas.  "repair world's damage on canvas"
- 		"self handsDo:[:h| h noticeDamageRects: worldDamageRects]."
- 		handsToDraw := self selectHandsToDrawForDamage: worldDamageRects.
- 		handDamageRects := handsToDraw collect: [:h | h savePatchFrom: canvas].
- 		allDamage := worldDamageRects, handDamageRects.
  
+ 	worldDamageRects := self drawWorld: aWorld submorphs: submorphs invalidAreasOn: canvas.  "repair world's damage on canvas"
+ 	"self handsDo:[:h| h noticeDamageRects: worldDamageRects]."
+ 	handsToDraw := self selectHandsToDrawForDamage: worldDamageRects.
+ 	handDamageRects := handsToDraw collect: [:h | h savePatchFrom: canvas].
+ 	allDamage := worldDamageRects, handDamageRects.
+ 
+ 	handsToDraw reverseDo: [:h | canvas fullDrawMorph: h].  "draw hands onto world canvas"
+ 
- 		handsToDraw reverseDo: [:h | canvas fullDrawMorph: h].  "draw hands onto world canvas"
- 	].
  	"*make this true to flash damaged areas for testing*"
  	Preferences debugShowDamage ifTrue: [aWorld flashRects: allDamage color: Color black].
  
  	canvas finish: allDamage.
  
  	"quickly copy altered rects of canvas to Display:"
  	deferredUpdateMode
  		ifTrue: [self forceDamageToScreen: allDamage]
  		ifFalse: [canvas showAt: aWorld viewBox origin invalidRects: allDamage].
  	handsToDraw do: [:h | h restoreSavedPatchOn: canvas].  "restore world canvas under hands"
  	Display deferUpdates: false; forceDisplayUpdate.
  !



More information about the Squeak-dev mailing list