The Trunk: Morphic-mt.760.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.760.mcz

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