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

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

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

Name: Morphic-mt.825
Author: mt
Time: 6 April 2015, 2:23:39.657 pm
UUID: 689afaee-4732-ab48-8ab8-f950131ccb24
Ancestors: Morphic-mt.824

Soft drop shadows introduced and *disabled* by default. Cache added to shadow drawing (including regular/sharp shadows), which will be updated on extent updates.

This commit also cleans-up some shadow-related code.

Note: This does not change the way hand morphs compute their drop shadows when dragging morphs around! There always have been two seprate concepts for drop shadows.

=============== Diff against Morphic-mt.824 ===============

Item was changed:
  ----- Method: FillInTheBlankMorph>>setDefaultParameters (in category 'initialization') -----
  setDefaultParameters
  "change the receiver's appareance parameters"
 
  | colorFromMenu worldColor menuColor |
 
  colorFromMenu := Preferences menuColorFromWorld
  and: [Display depth > 4
  and: [(worldColor := self currentWorld color) isColor]].
 
  menuColor := colorFromMenu
  ifTrue: [worldColor luminance > 0.7
  ifTrue: [worldColor mixed: 0.85 with: Color black]
  ifFalse: [worldColor mixed: 0.4 with: Color white]]
  ifFalse: [Preferences menuColor].
 
  self color: menuColor.
  self borderWidth: Preferences menuBorderWidth.
 
  Preferences menuAppearance3d ifTrue: [
  self borderStyle: BorderStyle thinGray.
+ self hasDropShadow: true.
+
+ self useSoftDropShadow
+ ifFalse: [
+ self
+ shadowColor: (TranslucentColor r: 0.0 g: 0.0 b: 0.0 alpha: 0.666);
+ shadowOffset: 1 @ 1]
+ ifTrue: [
+ self
+ shadowColor: (TranslucentColor r: 0.0 g: 0.0 b: 0.0 alpha: 0.01);
+ shadowOffset: (10@8 corner: 10@12) ]
- self
- addDropShadow;
- shadowColor: (TranslucentColor r: 0.0 g: 0.0 b: 0.0 alpha: 0.666);
- shadowOffset: 1 @ 1
  ]
  ifFalse: [
  | menuBorderColor |
  menuBorderColor := colorFromMenu
  ifTrue: [worldColor muchDarker]
  ifFalse: [Preferences menuBorderColor].
  self borderColor: menuBorderColor.
  ].
 
 
  self layoutInset: 3.
  !

Item was changed:
  ----- Method: MenuMorph>>setDefaultParameters (in category 'initialization') -----
  setDefaultParameters
  "change the receiver's appareance parameters"
 
  | colorFromMenu worldColor menuColor |
 
  colorFromMenu := Preferences menuColorFromWorld
  and: [Display depth > 4
  and: [(worldColor := self currentWorld color) isColor]].
 
  menuColor := colorFromMenu
  ifTrue: [worldColor luminance > 0.7
  ifTrue: [worldColor mixed: 0.85 with: Color black]
  ifFalse: [worldColor mixed: 0.4 with: Color white]]
  ifFalse: [Preferences menuColor].
 
  self color: menuColor.
  self borderWidth: Preferences menuBorderWidth.
 
  Preferences menuAppearance3d ifTrue: [
  self borderStyle: BorderStyle thinGray.
+ self hasDropShadow: true.
+
+ self useSoftDropShadow
+ ifFalse: [
+ self
+ shadowColor: (TranslucentColor r: 0.0 g: 0.0 b: 0.0 alpha: 0.666);
+ shadowOffset: 1 @ 1]
+ ifTrue: [
+ self
+ shadowColor: (TranslucentColor r: 0.0 g: 0.0 b: 0.0 alpha: 0.01);
+ shadowOffset: (10@8 corner: 10@12) ]
- self
- addDropShadow;
- shadowColor: (TranslucentColor r: 0.0 g: 0.0 b: 0.0 alpha: 0.666);
- shadowOffset: 1 @ 1
  ]
  ifFalse: [
  | menuBorderColor |
  menuBorderColor := colorFromMenu
  ifTrue: [worldColor muchDarker]
  ifFalse: [Preferences menuBorderColor].
  self borderColor: menuBorderColor.
  ].
 
 
  self layoutInset: 3.
  !

Item was changed:
  Object subclass: #Morph
  instanceVariableNames: 'bounds owner submorphs fullBounds color extension'
+ classVariableNames: 'PreferredCornerRadius UseSoftDropShadow'
- classVariableNames: 'PreferredCornerRadius'
  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>>useSoftDropShadow (in category 'preferences') -----
+ useSoftDropShadow
+
+ <preference: 'Use Soft Drop Shadow'
+ categoryList: #(Morphic windows menus performance)
+ description: 'If drop shadows are enabled, this preference will switch between hard and soft shadows. Soft shadows are more expensive.'
+ type: #Boolean>
+ ^ UseSoftDropShadow ifNil: [ false ]!

Item was added:
+ ----- Method: Morph class>>useSoftDropShadow: (in category 'preferences') -----
+ useSoftDropShadow: aBoolean
+
+ UseSoftDropShadow = aBoolean ifTrue: [^ self].
+ UseSoftDropShadow := aBoolean.
+
+ SystemWindow refreshAllWindows.
+ SystemProgressMorph reset.
+ TheWorldMainDockingBar updateInstances.!

Item was changed:
  ----- Method: Morph>>addDropShadow (in category 'drop shadows') -----
  addDropShadow
 
- self hasDropShadow ifTrue:[^self].
- self changed.
  self hasDropShadow: true.
+
+ self useSoftDropShadow
+ ifFalse: [
+ self
+ shadowOffset: 3@3;
+ shadowColor: (Color black alpha: 0.5)]
+ ifTrue: [
+ self
+ shadowOffset: (10@8 corner: 10@12);
+ shadowColor: (Color black alpha: 0.01)].!
- self shadowOffset: 3@3.
- self layoutChanged.
- self changed.!

Item was changed:
  ----- Method: Morph>>drawDropShadowOn: (in category 'drawing') -----
  drawDropShadowOn: aCanvas
+ "Rectangular shadow with support for rounded corners."
+
+ | shadowBounds |
+ shadowBounds := self shadowOffset isRectangle
+ ifTrue: [self bounds outsetBy: self shadowOffset]
+ ifFalse: [self bounds translateBy: (self shadowOffset negated max: 0@0)].
+
+ "Only redraw the shadow if the shadow area is affected."
+ ((aCanvas clipRect intersects: shadowBounds) and: [((self bounds insetBy: (self wantsRoundedCorners ifFalse: [0] ifTrue: [self class preferredCornerRadius])) containsRect: aCanvas clipRect) not])
+ ifTrue: [
+ (self hasProperty: #dropShadow)
+ ifFalse: [self updateDropShadowCache].
+ aCanvas
+ translucentImage: (self valueOfProperty: #dropShadow)
+ at: shadowBounds topLeft].!
-
- 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]]].
- !

Item was changed:
  ----- Method: Morph>>expandFullBoundsForDropShadow: (in category 'drawing') -----
  expandFullBoundsForDropShadow: aRectangle
  "Return an expanded rectangle for an eventual drop shadow"
  | delta box |
 
+ self shadowOffset isRectangle
+ ifTrue: [^ aRectangle outsetBy: self shadowOffset].
+
  box := aRectangle.
  delta := self shadowOffset.
  box := delta x >= 0
  ifTrue:[box right: aRectangle right + delta x]
  ifFalse:[box left: aRectangle left + delta x].
  box := delta y >= 0
  ifTrue:[box bottom: aRectangle bottom + delta y]
  ifFalse:[box top: aRectangle top + delta y].
  ^box!

Item was changed:
  ----- Method: Morph>>extent: (in category 'geometry') -----
  extent: aPoint
 
  (bounds extent closeTo: aPoint) ifTrue: [^ self].
  self changed.
  bounds := (bounds topLeft extent: aPoint) rounded.
+ self removeProperty: #dropShadow.
  self layoutChanged.
  self changed.
  !

Item was changed:
  ----- Method: Morph>>hasDropShadow: (in category 'drop shadows') -----
  hasDropShadow: aBool
+
+ self hasDropShadow = aBool ifTrue: [^ self].
+ self changed.
  aBool
  ifTrue:[self setProperty: #hasDropShadow toValue: true]
+ ifFalse:[self removeProperty: #hasDropShadow].
+
+ self layoutChanged.
+ self changed.!
- ifFalse:[self removeProperty: #hasDropShadow]!

Item was changed:
  ----- Method: Morph>>shadowColor: (in category 'drop shadows') -----
  shadowColor: aColor
+ self shadowColor = aColor ifTrue: [^ self].
+ self setProperty: #shadowColor toValue: aColor.
+ self removeProperty: #dropShadow.
+ self changed.!
- self shadowColor = aColor ifFalse:[self changed].
- self setProperty: #shadowColor toValue: aColor.!

Item was changed:
  ----- Method: Morph>>shadowOffset: (in category 'drop shadows') -----
  shadowOffset: aPoint
  "Set the current shadow offset"
 
+ self shadowOffset = aPoint ifTrue: [^ self].
+ self changed.
+
  (aPoint isNil or: [ aPoint isZero ])
  ifTrue:[self removeProperty: #shadowOffset]
+ ifFalse:[self setProperty: #shadowOffset toValue: aPoint].
+
+ self layoutChanged.
+ self changed.!
- ifFalse:[self setProperty: #shadowOffset toValue: aPoint].!

Item was added:
+ ----- Method: Morph>>updateDropShadowCache (in category 'drawing') -----
+ updateDropShadowCache
+
+ | shadowBounds offset form canvas drawBlock localBounds mask maskCanvas |
+ shadowBounds := self shadowOffset isRectangle
+ ifTrue: [0@0 corner: (self bounds outsetBy: self shadowOffset) extent]
+ ifFalse: [0@0 corner: self extent + self shadowOffset abs].
+ offset := self shadowOffset isRectangle
+ ifTrue: [0@0]
+ ifFalse: [self shadowOffset max: 0@0].
+ localBounds := self shadowOffset isRectangle
+ ifTrue: [self shadowOffset topLeft extent: self extent]
+ ifFalse: [(self shadowOffset negated max: 0@0) extent: self extent].
+
+ form := Form extent: shadowBounds extent depth: Display depth.
+ canvas := form getCanvas.
+
+ drawBlock := self useSoftDropShadow
+ ifFalse: [
+ [:c | self wantsRoundedCorners
+ ifTrue: [c fillRoundRect: localBounds radius: self class preferredCornerRadius fillStyle: self shadowColor]
+ ifFalse: [c fillRectangle: localBounds fillStyle: self shadowColor]]]
+ ifTrue: [
+ [:c | self wantsRoundedCorners
+ ifTrue: [0 to: 9 do: [:i |
+ c
+ fillRoundRect: (shadowBounds insetBy: i)
+ radius: (self class preferredCornerRadius max: 20) -i
+ fillStyle: (self shadowColor alpha: self shadowColor alpha * (i+1))]]
+ ifFalse: [0 to: 9 do: [:i |
+ c
+ fillRoundRect: (shadowBounds insetBy: i) radius: 20-i
+ fillStyle: (self shadowColor alpha: self shadowColor alpha * (i+1))]]]].
+
+ canvas
+ translateBy: offset
+ during: [ :shadowCanvas | drawBlock value: shadowCanvas].
+
+ "Support transparent morph colors without having the shadow to shine through.."
+ mask := Form extent: shadowBounds extent depth: Display depth.
+ maskCanvas := mask getCanvas.
+ self wantsRoundedCorners
+ ifTrue: [maskCanvas fillRoundRect: (localBounds insetBy: self borderWidth) radius: self class preferredCornerRadius fillStyle: Color black]
+ ifFalse: [maskCanvas fillRectangle: (localBounds insetBy: self borderWidth) fillStyle: Color black].
+ mask
+ displayOn: form
+ at: 0@0
+ rule: Form erase.
+
+ self setProperty: #dropShadow toValue: form.!

Item was added:
+ ----- Method: Morph>>useSoftDropShadow (in category 'drop shadows') -----
+ useSoftDropShadow
+
+ ^ self
+ valueOfProperty: #useSoftDropShadow
+ ifAbsent: [self class useSoftDropShadow]!

Item was added:
+ ----- Method: Morph>>useSoftDropShadow: (in category 'drop shadows') -----
+ useSoftDropShadow: aBooleanOrNil
+
+ aBooleanOrNil
+ ifNil: [self removeProperty: #useSoftDropShadow]
+ ifNotNil: [self setProperty: #useSoftDropShadow toValue: aBooleanOrNil].!

Item was changed:
  ----- Method: SystemProgressMorph>>setDefaultParameters (in category 'initialization') -----
  setDefaultParameters
  "change the receiver's appareance parameters"
 
  | colorFromMenu worldColor menuColor |
 
  colorFromMenu := Preferences menuColorFromWorld
  and: [Display depth > 4
  and: [(worldColor := self currentWorld color) isColor]].
 
  menuColor := colorFromMenu
  ifTrue: [worldColor luminance > 0.7
  ifTrue: [worldColor mixed: 0.85 with: Color black]
  ifFalse: [worldColor mixed: 0.4 with: Color white]]
  ifFalse: [Preferences menuColor].
 
  self color: menuColor.
 
  MenuMorph roundedMenuCorners
  ifTrue: [self useRoundedCorners].
  self borderWidth: Preferences menuBorderWidth.
 
  Preferences menuAppearance3d ifTrue: [
  self borderStyle: BorderStyle thinGray.
+ self hasDropShadow: true.
+
+ self useSoftDropShadow
+ ifFalse: [
+ self
+ shadowColor: (TranslucentColor r: 0.0 g: 0.0 b: 0.0 alpha: 0.666);
+ shadowOffset: 1 @ 1]
+ ifTrue: [
+ self
+ shadowColor: (TranslucentColor r: 0.0 g: 0.0 b: 0.0 alpha: 0.01);
+ shadowOffset: (10@8 corner: 10@12) ]
- self
- addDropShadow;
- shadowColor: (TranslucentColor r: 0.0 g: 0.0 b: 0.0 alpha: 0.666);
- shadowOffset: 1 @ 1
  ]
  ifFalse: [
  | menuBorderColor |
  menuBorderColor := colorFromMenu
  ifTrue: [worldColor muchDarker]
  ifFalse: [Preferences menuBorderColor].
  self borderColor: menuBorderColor.
  ].
 
  self
  updateColor: self
  color: self color
  intensity: 1.!

Item was changed:
  ----- Method: SystemWindow class>>refreshAllWindows (in category 'initializing') -----
  refreshAllWindows
  "If there is some prominent UI change, use this method to update all open windows."
 
+ SystemWindow allSubInstances do: [:w |
+ w
+ setDefaultParameters;
+ refreshWindowColor].!
- SystemWindow allSubInstances do: [:w | w refreshWindowColor].!

Item was changed:
  ----- Method: SystemWindow class>>updatePreferences (in category 'initializing') -----
  updatePreferences
  "Temporary method to update system-wide preferences"
+ Preferences installNormalWindowColors.
- Preferences setPreference: #defaultWindowColor toValue: (Color veryVeryLightGray muchLighter).
- (Preferences preferenceAt: #defaultWindowColor) defaultValue: (Color veryVeryLightGray muchLighter).
 
  Preferences setPreference: #menuAppearance3d toValue: true.
  (Preferences preferenceAt: #menuAppearance3d) defaultValue: true.
 
  Preferences setPreference: #menuColorFromWorld toValue: false.
  (Preferences preferenceAt: #menuColorFromWorld) defaultValue: false.
 
  MenuMorph roundedMenuCorners: false.
 
  Preferences setParameter: #menuColor to: (Color gray: 0.9).
  Preferences setParameter: #menuTitleColor to: (Color transparent).
  Preferences setParameter: #menuTitleBorderWidth to: 0.
  Preferences setParameter: #defaultWorldColor to: (Color gray: 0.25).
 
  Preferences setPreference: #showSplitterHandles toValue: false.
  (Preferences preferenceAt: #showSplitterHandles) defaultValue: true.
 
  Preferences setPreference: #showSharedFlaps toValue: false.
  (Preferences preferenceAt: #showSharedFlaps) defaultValue: false.
 
- Preferences installBrightWindowColors.
-
  CornerGripMorph drawCornerResizeHandles: false.
  FillInTheBlankMorph roundedDialogCorners: true.
 
  LazyListMorph
  listSelectionColor: LazyListMorph listSelectionColor;
  listSelectionTextColor: Color black.
  PluggableButtonMorph roundedButtonCorners: true.
  SystemWindow
  clickOnLabelToEdit: false;
  doubleClickOnLabelToExpand: true;
  moveMenuButtonRight: true;
+ hideExpandButton: false.!
- hideExpandButton: false.
- !

Item was changed:
  ----- Method: SystemWindow>>activateWindow (in category 'top window') -----
  activateWindow
  "Bring me to the front and make me able to respond to mouse and keyboard.
  Was #activate (sw 5/18/2001 23:20)"
 
  | oldTop outerMorph sketchEditor pal |
+ self hasDropShadow: Preferences menuAppearance3d.
+
  outerMorph := self topRendererOrSelf.
  outerMorph owner ifNil: [^ self "avoid spurious activate when drop in trash"].
  oldTop := TopWindow.
  oldTop = self ifTrue: [^self].
  TopWindow := self.
  oldTop ifNotNil: [oldTop passivate].
  outerMorph owner firstSubmorph == outerMorph
  ifFalse: ["Bring me (with any flex) to the top if not already"
  outerMorph owner addMorphFront: outerMorph].
  self submorphsDo: [:m | m unlock].
 
  label ifNotNil: [label color: Color black].
 
  self undimWindowButtons.
  labelArea ifNotNil: [labelArea submorphsDo: [:m | m unlock; show]].
  self
  setStripeColorsFrom: self paneColorToUse;
  adoptPaneColor: self paneColorToUse.
 
  self isCollapsed ifFalse:
  [model modelWakeUpIn: self.
  self positionSubmorphs.
  labelArea ifNil: [self adjustBorderUponActivationWhenLabeless]].
 
  (sketchEditor := self extantSketchEditor) ifNotNil:
  [sketchEditor comeToFront.
  (pal := self world findA: PaintBoxMorph) ifNotNil:
  [pal comeToFront]].
 
  self updatePaneColors.!

Item was changed:
  ----- Method: SystemWindow>>initialize (in category 'initialization') -----
  initialize
  "Initialize a system window. Add label, stripes, etc., if desired"
 
  super initialize.
 
  self layoutPolicy: ProportionalLayout new.
 
  self initializeLabelArea.
  self addCornerGrips.
+ self setDefaultParameters.
 
- Preferences menuAppearance3d ifTrue: [
- self
- addDropShadow;
- shadowColor: (TranslucentColor r: 0.0 g: 0.0 b: 0.0 alpha: 0.333);
- shadowOffset: 1@1].
-
  allowReframeHandles := true.
  isCollapsed := false.
  activeOnlyOnTop := true.
  paneMorphs := Array new.
  mustNotClose := false.
  updatablePanes := Array new.!

Item was changed:
  ----- Method: SystemWindow>>justDroppedInto:event: (in category 'geometry') -----
  justDroppedInto: aMorph event: anEvent
+
+ self hasDropShadow: (self isActive and: [Preferences menuAppearance3d]).
+
  isCollapsed
  ifTrue: [self position: ((self position max: 0@0) grid: 8@8).
  collapsedFrame := self bounds]
  ifFalse: [fullFrame := self bounds.
  TopWindow ~~ self ifTrue: [self activate]].
  ^super justDroppedInto: aMorph event: anEvent!

Item was changed:
  ----- Method: SystemWindow>>passivate (in category 'top window') -----
  passivate
  "Make me unable to respond to mouse and keyboard"
 
  label ifNotNil: [label color: Color darkGray].
 
+ self hasDropShadow: false.
  self paneColorToUseWhenNotActive in: [:c |
  self
  setStripeColorsFrom: c;
  adoptPaneColor: c].
 
  model modelSleep.
 
  self lockInactivePortions
  !

Item was added:
+ ----- Method: SystemWindow>>setDefaultParameters (in category 'initialization') -----
+ setDefaultParameters
+
+ Preferences menuAppearance3d ifTrue: [
+ self hasDropShadow: self isActive.
+
+ self useSoftDropShadow
+ ifTrue: [
+ self
+ shadowColor: (TranslucentColor r: 0.0 g: 0.0 b: 0.0 alpha: 0.01);
+ shadowOffset: (10@8 corner: 10@12)]
+ ifFalse: [
+ self
+ shadowColor: (TranslucentColor r: 0.0 g: 0.0 b: 0.0 alpha: 0.333);
+ shadowOffset: 1@1] ].
+ self changed.!

Item was changed:
  ----- Method: SystemWindow>>setWindowColor: (in category 'colors handling') -----
  setWindowColor: incomingColor
  | existingColor aColor |
  incomingColor ifNil: [^ self].  "it happens"
+ aColor := incomingColor.
- aColor := incomingColor asNontranslucentColor.
  (aColor = ColorPickerMorph perniciousBorderColor
  or: [aColor = Color black]) ifTrue: [^ self].
  existingColor := self paneColorToUse.
  existingColor ifNil: [^ Beeper beep].
  self paneColor: aColor.
  self setStripeColorsFrom: aColor.
  self changed.!

Item was changed:
  ----- Method: SystemWindow>>startDragFromLabel: (in category 'events') -----
  startDragFromLabel: evt
  "When label events are active, we need to pass dragging to the window explicitely
  The window only recognizes a drag with an offset of more than 3 pixels"
 
  self isSticky ifTrue: [^ self].
  self fastFramingOn
  ifTrue: [self doFastFrameDrag: evt cursorPoint]
+ ifFalse: [
+ self hasDropShadow: false.
+ evt hand grabMorph: self topRendererOrSelf]
- ifFalse: [evt hand grabMorph: self topRendererOrSelf]
  !

Item was changed:
  ----- Method: UserDialogBoxMorph>>initialize (in category 'initialization') -----
  initialize
 
  | titleRow cc |
  super initialize.
  self color: Color white.
  self listDirection: #topToBottom; wrapCentering: #center;
  hResizing: #shrinkWrap; vResizing: #shrinkWrap.
  self layoutInset: -1 @ -1; cellInset: 5@5.
  self borderStyle: BorderStyle thinGray.
+ self useRoundedCorners.
+ self hasDropShadow: true.
+ self useSoftDropShadow
+ ifFalse: [
+ self
+ shadowColor: (TranslucentColor r: 0.0 g: 0.0 b: 0.0 alpha: 0.666);
+ shadowOffset: 1 @ 1]
+ ifTrue: [
+ self
+ shadowColor: (TranslucentColor r: 0.0 g: 0.0 b: 0.0 alpha: 0.01);
+ shadowOffset: (10@8 corner: 10@12)].
- self
- useRoundedCorners;
- addDropShadow;
- shadowColor: (TranslucentColor r: 0.0 g: 0.0 b: 0.0 alpha: 0.666);
- shadowOffset: 1 @ 1.
 
  cc := Color gray: 0.8.
  titleRow := AlignmentMorph newRow.
  titleRow hResizing: #spaceFill; vResizing: #shrinkWrap.
  titleRow useRoundedCorners.
  titleRow borderStyle: BorderStyle thinGray.
  titleRow layoutInset: (2@5 corner: (2@ (5 + Morph preferredCornerRadius))).
  titleRow color: cc.
  titleRow fillStyle: self titleGradient.
 
  titleMorph := StringMorph new.
  titleMorph emphasis: 1.
  titleRow addMorph: titleMorph.
  labelMorph := TextMorph new.
  labelMorph margins: 5@5.
  labelMorph lock.
  buttonRow := AlignmentMorph newRow vResizing: #shrinkWrap.
  buttonRow hResizing: #shrinkWrap; layoutInset: 5@5; cellInset: 5@5.
  buttonRow color: Color transparent.
  self
  addMorphBack: titleRow ;
  addMorphBack: labelMorph ;
+ addMorphBack: buttonRow.
- addMorphBack: buttonRow ;
- addDropShadow.
  keyMap := Dictionary new!