[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
|