'From Cuis 1.0 of 19 April 2009 [latest update: #187] on 14 May 2009 at 5:52:58 pm'!
!classDefinition: #Morph category: #'Morphic-OldKernel'!
Object subclass: #Morph
	instanceVariableNames: 'bounds owner submorphs fullBounds color extension vResizing hResizing layoutInset '
	classVariableNames: 'EmptyArray '
	poolDictionaries: ''
	category: 'Morphic-OldKernel'!
!classDefinition: #FillInTheBlankMorph category: #'Morphic-OldWindows'!
AlignmentMorph subclass: #FillInTheBlankMorph
	instanceVariableNames: 'response done textPane responseUponCancel '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Morphic-OldWindows'!
!classDefinition: #MenuMorph category: #'Morphic-OldMenus'!
BorderedMorph subclass: #MenuMorph
	instanceVariableNames: 'defaultTarget selectedItem stayUp popUpOwner activeSubMenu titleMorph '
	classVariableNames: 'CloseBoxImage PushPinImage '
	poolDictionaries: ''
	category: 'Morphic-OldMenus'!

!MenuMorph commentStamp: '<historical>' prior: 0!
Instance variables:
	defaultTarget 		<Object>				The default target for creating menu items
	selectedItem		<MenuItemMorph> 	The currently selected item in the receiver
	stayUp 			<Boolean>				True if the receiver should stay up after clicks
	popUpOwner 		<MenuItemMorph>		The menu item that automatically invoked the receiver, if any.
	activeSubMenu 	<MenuMorph>			The currently active submenu.!

!classDefinition: #PluggableButtonMorph category: #'Morphic-OldWindows'!
AlignmentMorph subclass: #PluggableButtonMorph
	instanceVariableNames: 'model label getStateSelector actionSelector getLabelSelector getMenuSelector shortcutCharacter askBeforeChanging triggerOnMouseDown offColor onColor feedbackColor showSelectionFeedback allButtons arguments argumentsProvider argumentsSelector font '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Morphic-OldWindows'!
!classDefinition: #SimpleButtonMorph category: #'Morphic-OldWidgets'!
RectangleMorph subclass: #SimpleButtonMorph
	instanceVariableNames: 'target actionSelector arguments actWhen oldColor label font '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Morphic-OldWidgets'!
!classDefinition: #ColorPickerMorph category: #'Morphic-OldWidgets'!
SketchMorph subclass: #ColorPickerMorph
	instanceVariableNames: 'selectedColor sourceHand deleteOnMouseUp updateContinuously target selector argument originalColor theSelectorDisplayMorph command isModal clickedTranslucency '
	classVariableNames: 'ColorChart DragBox FeedbackBox RevertBox TransText TransparentBox '
	poolDictionaries: ''
	category: 'Morphic-OldWidgets'!

!MenuItemMorph commentStamp: 'jmv 5/6/2009 22:52' prior: 0!
I represent an item in a menu.

Instance variables:
	isEnabled 	<Boolean>			True if the menu item can be executed.
	subMenu 	<MenuMorph | nil>	The submenu to activate automatically when the user mouses over the item.
	isSelected 	<Boolean>			True if the item is currently selected.
	target 		<Object>			The target of the associated action.
	selector 	<Symbol>			The associated action.
	arguments 	<Array>			The arguments for the associated action.
	icon		<Form | nil>		An optional icon form to be displayed to my left.

If I have a dynamic marker, created by strings like <yes> or <no> in my contents, it will be installed as a submorph.!

!classDefinition: #SystemWindow category: #'Morphic-OldWindows'!
MorphWithModel subclass: #SystemWindow
	instanceVariableNames: 'labelString stripes label closeBox collapseBox paneMorphs paneRects collapsedFrame fullFrame isCollapsed menuBox mustNotClose labelWidgetAllowance updatablePanes allowReframeHandles labelArea expandBox '
	classVariableNames: 'CloseBoxImage CollapseBoxImage TopWindow '
	poolDictionaries: ''
	category: 'Morphic-OldWindows'!

!DisplayText methodsFor: 'displaying' stamp: 'jmv 5/14/2009 17:51'!
displayOn: aDisplayMedium at: aDisplayPoint clippingBox: clipRectangle rule: ruleInteger fillColor: aForm
	"Refer to the comment in 
	DisplayObject|displayOn:at:clippingBox:rule:mask:."

	| form1 rule |
	form1 _ self form.
	rule _ (ruleInteger = Form over and: [backColor isTransparent])
				ifTrue: [(form1 depth = 32 and: [foreColor = Color black]) ifTrue: [rule _ 28] ifFalse: [Form paint]]
				ifFalse: [ruleInteger].
	form1
		displayOn: aDisplayMedium
		at: aDisplayPoint + offset
		clippingBox: clipRectangle
		rule: rule
		fillColor: aForm! !


!Form class methodsFor: 'fileIn/Out' stamp: 'jmv 5/5/2009 16:37'!
services

	^ Array
		with: self serviceImageAsBackground ! !


!LayoutFrame class methodsFor: 'as yet unclassified' stamp: 'jmv 5/4/2009 23:23'!
fractions: fractionsOrNil offsets: offsetsOrNil

	| fractions offsets leftOffset rightOffset topOffset bottomOffset |

	fractions _ fractionsOrNil ifNil: [0@0 extent: 0@0].
	offsets _ offsetsOrNil ifNil: [0].
	offsets isNumber
		ifTrue: [
			leftOffset _ topOffset _ offsets.
			rightOffset _ bottomOffset _ offsets negated ]
		ifFalse: [
			offsets isPoint
				ifTrue: [
					leftOffset _ offsets x.
					rightOffset _ offsets x negated.
					topOffset _ offsets y.
					bottomOffset _ offsets y negated  ]
				ifFalse: [
					leftOffset _ offsets left.
					rightOffset _ offsets right.
					topOffset _ offsets top.
					bottomOffset _ offsets bottom ]].
					
	^self new
		topFraction: fractions top offset: topOffset;
		leftFraction: fractions left offset: leftOffset;
		bottomFraction: fractions bottom offset: bottomOffset;
		rightFraction: fractions right offset: rightOffset
! !


!LightWidget methodsFor: 'halos and balloon help' stamp: 'jmv 5/5/2009 16:44'!
balloonHelpTextForHandle: aHandle
	"Answer a string providing balloon help for the given halo handle"

	|  itsSelector |
	itsSelector _ aHandle eventHandler firstMouseSelector.
	#(	(addFullHandles						'More halo handles')
		(addSimpleHandles						'Fewer halo handles')
		(chooseEmphasisOrAlignment			'Emphasis & alignment')
		(chooseFont							'Change font')
		(chooseStyle							'Change style')
		(dismiss								'Remove')
		(doDebug:with:							'Debug')
		(doDirection:with:						'Choose forward direction')
		(doDup:with:							'Duplicate')
		(doMenu:with:							'Menu')
		(doGrab:with:							'Pick up')
		(doRecolor:with:						'Change color')
		(maybeDoDup:with:						'Duplicate')
		(mouseDownInCollapseHandle:with:	'Collapse')
		(mouseDownOnHelpHandle:			'Help')
		(startDrag:with:						'Move')
		(startGrow:with:						'Change size') 
		(startRot:with:							'Rotate')) 


	do:
		[:pair | itsSelector == pair first ifTrue: [^ pair last]].

	(itsSelector == #mouseDownInDimissHandle:with:) ifTrue:
				['Remove from screen'].

	^ 'unknown halo handle'! !

!LightWidget methodsFor: 'meta actions' stamp: 'jmv 5/11/2009 23:38'!
blueButtonDown: anEvent
	"Special gestures (cmd-mouse on the Macintosh; Alt-mouse on Windows and Unix) allow a mouse-sensitive morph to be moved or bring up a halo for the morph."
	| h tfm doNotDrag |
	h _ anEvent hand halo.
	"Prevent wrap around halo transfers originating from throwing the event back in"
	doNotDrag _ false.
	h ifNotNil:[
		(h innerTarget == self) ifTrue:[doNotDrag _ true].
		(h innerTarget hasOwner: self) ifTrue:[doNotDrag _ true].
		(self hasOwner: h target) ifTrue:[doNotDrag _ true]].

	tfm _ (self transformedFrom: nil) inverseTransformation.

	"cmd-drag on flexed morphs works better this way"
	h _ self addHalo: (anEvent transformedBy: tfm).
	doNotDrag ifTrue:[^self].
	"Initiate drag transition if requested"
	anEvent hand 
		waitForClicksOrDrag: h
		event: (anEvent transformedBy: tfm)
		clkSel: nil
		dblClkSel: nil
		dblClkTimeoutSel: nil
		dragSel: #dragTarget:.
	"Pass focus explicitly here"
	anEvent hand newMouseFocus: h.! !


!Morph methodsFor: 'copying' stamp: 'jmv 5/7/2009 21:25'!
veryDeepInner: deepCopier 
	"The inner loop, so it can be overridden when a field should not  
	be traced."
	"super veryDeepInner: deepCopier.	know Object has no inst vars"
	bounds _ bounds clone.
	"Points are shared with original"
	"owner _ owner.	special, see veryDeepFixupWith:"
	submorphs _ submorphs veryDeepCopyWith: deepCopier.
	"each submorph's fixup will install me as the owner"
	"fullBounds _ fullBounds.	fullBounds is shared with original!!"
	color _ color veryDeepCopyWith: deepCopier.
	"color, if simple, will return self. may be complex"
	self
		privateExtension: (self extension veryDeepCopyWith: deepCopier).
		vResizing _ vResizing! !

!Morph methodsFor: 'e-toy support' stamp: 'jmv 5/13/2009 15:37'!
embeddedInMorphicWindowLabeled: labelString 
	| window |
	window := (SystemWindow labelled: labelString) model: nil.
	window setWindowColor: nil class windowColor.
	window addMorph: self frame: (0 @ 0 extent: 1 @ 1).
	^window! !

!Morph methodsFor: 'halos and balloon help' stamp: 'jmv 5/5/2009 16:44'!
balloonHelpTextForHandle: aHandle
	"Answer a string providing balloon help for the given halo handle"

	|  itsSelector |
	itsSelector _ aHandle eventHandler firstMouseSelector.
	#(	(addFullHandles						'More halo handles')
		(addSimpleHandles						'Fewer halo handles')
		(chooseEmphasisOrAlignment			'Emphasis & alignment')
		(chooseFont							'Change font')
		(chooseStyle							'Change style')
		(dismiss								'Remove')
		(doDebug:with:							'Debug')
		(doDirection:with:						'Choose forward direction')
		(doDup:with:							'Duplicate')
		(doMenu:with:							'Menu')
		(doGrab:with:							'Pick up')
		(doRecolor:with:						'Change color')
		(maybeDoDup:with:						'Duplicate')
		(mouseDownInCollapseHandle:with:	'Collapse')
		(mouseDownOnHelpHandle:			'Help')
		(startDrag:with:						'Move')
		(startGrow:with:						'Change size') 
		(startRot:with:							'Rotate')) 


	do:
		[:pair | itsSelector == pair first ifTrue: [^ pair last]].

	(itsSelector == #mouseDownInDimissHandle:with:) ifTrue:
				['Remove from screen'].

	^ 'unknown halo handle'! !

!Morph methodsFor: 'layout' stamp: 'jmv 5/10/2009 21:53'!
acceptDroppingMorph: aMorph event: evt
	"This message is sent when a morph is dropped onto a morph that has agreed to accept the dropped morph by responding 'true' to the wantsDroppedMorph:Event: message. This default implementation just adds the given morph to the receiver."
	
	self addMorph: aMorph! !

!Morph methodsFor: 'layout' stamp: 'jmv 5/10/2009 10:37'!
doLayoutIn: layoutBounds 
	"Compute a new layout based on the given layout bounds."

	"Note: Testing for #bounds or #layoutBounds would be sufficient to
	figure out if we need an invalidation afterwards but #bounds
	is what we need for all leaf nodes so we use that."

	| layout box priorBounds |
	priorBounds := self bounds.
	submorphs isEmpty ifTrue: [^fullBounds := priorBounds].
	"Send #ownerChanged to our children"
	submorphs do: [:m | m ownerChanged].
	layout := self layoutPolicy.
	layout ifNotNil: [layout layout: self in: layoutBounds].

	fullBounds := self privateFullBounds.
	box := self bounds.
	box = priorBounds 
		ifFalse: [self invalidRect: (priorBounds quickMerge: box)]! !

!Morph methodsFor: 'layout' stamp: 'jmv 5/11/2009 22:53'!
layoutInBounds: cellBounds
	"Layout specific. Apply the given bounds to the receiver after being layed out in its owner."
	| box aSymbol delta |
	fullBounds ifNil:["We are getting new bounds here but we haven't computed the receiver's layout yet. Although the receiver has reported its minimal size before the actual size it has may differ from what would be after the layout. Normally, this isn't a real problem, but if we have #shrinkWrap constraints then the receiver's bounds may be larger than the cellBounds. THAT is a problem because the centering may not work correctly if the receiver shrinks after the owner layout has been computed. To avoid this problem, we compute the receiver's layout now. Note that the layout computation is based on the new cell bounds rather than the receiver's current bounds."
		
		self flag: #jmvRemove.
		"Leer el comentario. Entender. Simplificar!! (no hay mas shrinkWrap!!)"
		
		cellBounds origin = self bounds origin ifFalse:[
			box _ self bounds.
			delta _ cellBounds origin - self bounds origin.
			self invalidRect: (box merge: (box translateBy: delta)).
			self privateFullMoveBy: delta]. "sigh..."
		box _ cellBounds origin extent: "adjust for #rigid receiver"
			(self hResizing == #rigid ifTrue:[self bounds extent x] ifFalse:[cellBounds extent x]) @
			(self vResizing == #rigid ifTrue:[self bounds extent y] ifFalse:[cellBounds extent y]).
		"Compute inset of layout bounds"
		box _ box origin - (self bounds origin - self layoutBounds origin) corner:
					box corner - (self bounds corner - self layoutBounds corner).
		"And do the layout within the new bounds"
		self layoutBounds: box.
		self doLayoutIn: box].
	cellBounds = self fullBounds ifTrue:[^self]. "already up to date"
	cellBounds extent = self fullBounds extent "nice fit"
		ifTrue:[^self position: cellBounds origin].
	box _ bounds.
	"match #spaceFill constraints"
	self hResizing == #spaceFill 
		ifTrue:[box _ box origin extent: cellBounds width @ box height].
	self vResizing == #spaceFill
		ifTrue:[box _ box origin extent: box width @ cellBounds height].
	"align accordingly"
	aSymbol _ #center.
	box _ box align: (box perform: aSymbol) with: (cellBounds perform: aSymbol).
	"and install new bounds"
	self bounds: box.! !

!Morph methodsFor: 'layout-properties' stamp: 'jmv 5/11/2009 22:52'!
hResizing
	"Layout specific. This property describes how the receiver should be resized with respect to its owner and its children. Possible values are:
		#rigid			-	do not resize the receiver
		#spaceFill		-	resize to fill owner's available space
	"
	^hResizing ifNil:[#rigid]! !

!Morph methodsFor: 'layout-properties' stamp: 'jmv 5/11/2009 22:52'!
hResizing: aSymbol
	"Layout specific. This property describes how the receiver should be resized with respect to its owner and its children. Possible values are:
		#rigid			-	do not resize the receiver
		#spaceFill		-	resize to fill owner's available space
	"	self flag: #jmvRemove.
	hResizing _ aSymbol.
	self layoutChanged.
! !

!Morph methodsFor: 'layout-properties' stamp: 'jmv 5/7/2009 21:33'!
layoutInset
	"Return the extra inset for layouts"
	^layoutInset ifNil: [0]! !

!Morph methodsFor: 'layout-properties' stamp: 'jmv 5/7/2009 21:33'!
layoutInset: aNumber
	"Return the extra inset for layouts"
	self flag: #jmvRemove.
	layoutInset _ aNumber.
	self layoutChanged.! !

!Morph methodsFor: 'layout-properties' stamp: 'jmv 5/4/2009 15:46'!
layoutPolicy
	"Layout specific. Return the layout policy describing how children 
	of the receiver should appear."	self flag: #jmvRemove.
	^ self hasExtension
		ifTrue: [ self extension layoutPolicy]! !

!Morph methodsFor: 'layout-properties' stamp: 'jmv 5/4/2009 15:46'!
layoutPolicy: aLayoutPolicy
	"Layout specific. Return the layout policy describing how children of the receiver should appear."	self flag: #jmvRemove.
	self layoutPolicy == aLayoutPolicy ifTrue:[^self].
	self assureExtension layoutPolicy: aLayoutPolicy.
	self layoutChanged.! !

!Morph methodsFor: 'layout-properties' stamp: 'jmv 5/11/2009 22:54'!
vResizing
	"Layout specific. This property describes how the receiver should be resized with respect to its owner and its children. Possible values are:
		#rigid			-	do not resize the receiver
		#spaceFill		-	resize to fill owner's available space
	"
	^vResizing ifNil:[#rigid]! !

!Morph methodsFor: 'layout-properties' stamp: 'jmv 5/11/2009 22:54'!
vResizing: aSymbol
	"Layout specific. This property describes how the receiver should be resized with respect to its owner and its children. Possible values are:
		#rigid			-	do not resize the receiver
		#spaceFill		-	resize to fill owner's available space
	"	self flag: #jmvRemove.
	vResizing _ aSymbol.
	self layoutChanged.
! !

!Morph methodsFor: 'menus' stamp: 'jmv 5/11/2009 23:53'!
addStandardHaloMenuItemsTo: aMenu hand: aHandMorph
	"Add standard halo items to the menu"

	| unlockables |

	self isWorldMorph ifTrue:
		[^ self addWorldHaloMenuItemsTo: aMenu hand: aHandMorph].

	aMenu add: 'send to back' translated action: #goBehind.
	aMenu add: 'bring to front' translated action: #comeToFront.
	self addEmbeddingMenuItemsTo: aMenu hand: aHandMorph.
	aMenu addLine.

	self addFillStyleMenuItems: aMenu hand: aHandMorph.
	self addBorderStyleMenuItems: aMenu hand: aHandMorph.
	self addHaloActionsTo: aMenu.
	owner isTextMorph ifTrue:[self addTextAnchorMenuItems: aMenu hand: aHandMorph].
	aMenu addLine.
	self addToggleItemsToHaloMenu: aMenu.
	aMenu addLine.
	self addCopyItemsTo: aMenu.
	self addExportMenuItems: aMenu hand: aHandMorph.
	self addDebuggingItemsTo: aMenu hand: aHandMorph.

	aMenu addLine.
	aMenu defaultTarget: self.

	aMenu addLine.

	unlockables _ self submorphs select:
		[:m | m isLocked].
	unlockables size = 1 ifTrue:
		[aMenu
			add: ('unlock "{1}"' translated format: unlockables first externalName)
			action: #unlockContents].
	unlockables size > 1 ifTrue:
		[aMenu add: 'unlock all contents' translated action: #unlockContents.
		aMenu add: 'unlock...' translated action: #unlockOneSubpart].

	aMenu defaultTarget: aHandMorph.
! !

!Morph methodsFor: 'meta-actions' stamp: 'jmv 5/11/2009 23:38'!
blueButtonDown: anEvent
	"Special gestures (cmd-mouse on the Macintosh; Alt-mouse on Windows and Unix) allow a mouse-sensitive morph to be moved or bring up a halo for the morph."
	| h tfm doNotDrag |
	h _ anEvent hand halo.
	"Prevent wrap around halo transfers originating from throwing the event back in"
	doNotDrag _ false.
	h ifNotNil:[
		(h innerTarget == self) ifTrue:[doNotDrag _ true].
		(h innerTarget hasOwner: self) ifTrue:[doNotDrag _ true].
		(self hasOwner: h target) ifTrue:[doNotDrag _ true]].

	tfm _ (self transformedFrom: nil) inverseTransformation.

	"cmd-drag on flexed morphs works better this way"
	h _ self addHalo: (anEvent transformedBy: tfm).
	doNotDrag ifTrue:[^self].
	"Initiate drag transition if requested"
	anEvent hand 
		waitForClicksOrDrag: h
		event: (anEvent transformedBy: tfm)
		clkSel: nil
		dblClkSel: nil
		dblClkTimeoutSel: nil
		dragSel: #dragTarget:.
	"Pass focus explicitly here"
	anEvent hand newMouseFocus: h.! !

!Morph methodsFor: 'meta-actions' stamp: 'jmv 5/4/2009 15:43'!
buildMetaMenu: evt 
	"Build the morph menu. This menu has two sections. The first section contains commands that are handled by the hand; the second contains commands handled by the argument morph."

	| menu |
	menu := MenuMorph new defaultTarget: self.
	menu addStayUpItem.
	menu add: 'grab' translated action: #grabMorph:.
	menu add: 'copy to paste buffer' translated action: #copyToPasteBuffer:.
	self maybeAddCollapseItemTo: menu.
	menu add: 'delete' translated action: #dismissMorph:.
	menu addLine.
	menu add: 'copy text' translated action: #clipText.
	menu addLine.
	menu add: 'go behind' translated action: #goBehind.
	menu add: 'add halo' translated action: #addHalo:.
	menu add: 'duplicate' translated action: #maybeDuplicateMorph:.
	self addEmbeddingMenuItemsTo: menu hand: evt hand.
	menu add: 'resize' translated action: #resizeMorph:.
	"Give the argument control over what should be done about fill styles"
	self addFillStyleMenuItems: menu hand: evt hand.
	menu 
		addUpdating: #hasClipSubmorphsString
		target: self
		selector: #changeClipSubmorphs
		argumentList: #().
	menu addLine.
	(self morphsAt: evt position) size > 1 
		ifTrue: 
			[menu 
				add: 'submorphs...' translated
				target: self
				selector: #invokeMetaMenuAt:event:
				argument: evt position].
	menu addLine.
	menu 
		add: 'inspect' translated
		selector: #inspectAt:event:
		argument: evt position.
	menu add: 'explore' translated action: #explore.
	menu add: 'browse hierarchy' translated action: #browseHierarchy.
	menu add: 'show actions' translated action: #showActions.
	menu addLine.
	self addDebuggingItemsTo: menu hand: evt hand.
	self addCustomMenuItems: menu hand: evt hand.
	^menu! !


!AlignmentMorph methodsFor: 'initialization' stamp: 'jmv 5/7/2009 15:34'!
initialize
	"initialize the state of the receiver"
	super initialize.

	self
		layoutInset: 0;
		extent: 1@1;
		borderWidth: 0;
		clipSubmorphs: true;
		layoutPolicy: ProportionalLayout new! !

!AlignmentMorph methodsFor: 'construction' stamp: 'jmv 5/5/2009 13:55'!
addInProportionalRow: morphs
	"Honors proportions between current width of morphs"
	
	self addInRow: morphs widthProportionalTo: (morphs collect: [ :m | m width]) inset: 2! !

!AlignmentMorph methodsFor: 'construction' stamp: 'jmv 5/6/2009 09:19'!
addInRow: morphs
	"All morphs are made equal width"
	
	self addInRow: morphs widthProportionalTo: (morphs collect: [ :m | 1]) inset: 2! !

!AlignmentMorph methodsFor: 'construction' stamp: 'jmv 5/4/2009 23:24'!
addInRow: morphs atFractions: fractions inset: inset
	"Please ensure:
	fractions size = (morphs size + 1)
	fractions first = 0.0
	fractions last = 1.0
	inset can be a Number, Point or Rectangle. If it is a rectangle, 
		right and bottom should be negative"

	morphs doWithIndex: [ :morph :i |
		self
			addMorph: morph
			fullFrame: (LayoutFrame
				fractions: ((fractions at: i)@0 corner: (fractions at: i + 1)@1)
				offsets: inset) ]! !

!AlignmentMorph methodsFor: 'construction' stamp: 'jmv 5/5/2009 13:54'!
addInRow: morphs widthProportionalTo: widths inset: inset
	"Widths can be in any arbitrary unit. The actual widths will be proportional to them."

	| fractions totalWidth prev |
	totalWidth _ widths sum * 1.0.
	fractions _ OrderedCollection new.
	prev _ 0.0.
	widths do: [ :w |
		fractions add: prev.
		prev _ w / totalWidth + prev ].
	fractions add: 1.0.
	self addInRow: morphs atFractions: fractions inset: inset! !


!FillInTheBlankMorph methodsFor: 'initialization' stamp: 'jmv 5/14/2009 14:56'!
initialize

	super initialize.
	self setDefaultParameters.
	self extent: 400 @ 150.
	responseUponCancel := ''
	! !

!FillInTheBlankMorph methodsFor: 'initialization' stamp: 'jmv 5/5/2009 22:53'!
setQuery: queryString initialAnswer: initialAnswer answerExtent: answerExtent acceptOnCR: acceptBoolean 
	| query topOffset accept cancel buttonAreaHeight |
	response := initialAnswer.
	done := false.
	self removeAllMorphs.
	query := self createQueryTextMorph: queryString.
	topOffset := query height + 4.
	accept := self createAcceptButton.
	cancel := self createCancelButton.
	buttonAreaHeight := (accept height max: cancel height)
				+ 4.
	textPane := self
				createTextPaneExtent: answerExtent
				acceptBoolean: acceptBoolean
				topOffset: topOffset
				buttonAreaHeight: buttonAreaHeight.
	self extent: (query extent x max: answerExtent x)
			+ 4 @ (topOffset + answerExtent y + 4 + buttonAreaHeight).
	! !


!HaloMorph methodsFor: 'meta-actions' stamp: 'jmv 5/11/2009 23:38'!
blueButtonDown: event
	"Transfer the halo to the next likely recipient"
	target ifNil:[^self delete].
	event hand obtainHalo: self.
	positionOffset _ event position - (target point: target position in: owner).
	"wait for drags or transfer"
	event hand 
		waitForClicksOrDrag: self 
		event: event
		clkSel: #transferHalo:
		dblClkSel: nil
		dblClkTimeoutSel: nil
		dragSel: #dragTarget! !

!HaloMorph methodsFor: 'private' stamp: 'jmv 5/12/2009 00:10'!
addNameBeneath: outerRectangle string: aString 
	"Add a name display centered beneath the bottom of the outer rectangle. Return the handle."

	| nameMorph namePosition w |
	w := self world ifNil: [target world].
	nameMorph := StringMorph contents: aString.
	nameMorph color: Color magenta.
	namePosition := outerRectangle bottomCenter 
				- ((nameMorph width // 2) @ (self handleSize negated // 2 - 1)).
	nameMorph 
		position: (namePosition min: w viewBox bottomRight - nameMorph extent y + 2).
	self addMorph: nameMorph.
	^nameMorph! !


!HandMorph methodsFor: 'double click support' stamp: 'jmv 5/11/2009 23:38'!
waitForClicksOrDrag: aMorph event: evt

	"Wait until the difference between click, double-click, or drag gesture is known, then inform the given morph what transpired. This message is sent when the given morph first receives a mouse-down event. If the mouse button goes up, then down again within DoubleClickTime, then 'doubleClick: evt' is sent to the morph. If the mouse button goes up but not down again within DoubleClickTime, then the message 'click: evt' is sent to the morph. Finally, if the button does not go up within DoubleClickTime, then 'drag: evt' is sent to the morph. In all cases, the event supplied is the original mouseDown event that initiated the gesture. mouseMove: and mouseUp: events are not sent to the morph until it becomes the mouse focus, which is typically done by the client in its click:, doubleClick:, or drag: methods." 
	
	^self 
		waitForClicksOrDrag: aMorph 
		event: evt 
		clkSel: #click:
		dblClkSel: #doubleClick:
		dblClkTimeoutSel: #doubleClickTimeout:
		dragSel: #startDrag:! !

!HandMorph methodsFor: 'double click support' stamp: 'jmv 5/11/2009 23:37'!
waitForClicksOrDrag: aMorph event: evt  clkSel: clkSel dblClkSel: dblClkSel dblClkTimeoutSel: dblClkTimeoutSel dragSel: dragSel

	"Wait until the difference between click, double-click, or drag gesture is known, then inform the given morph what transpired. This message is sent when the given morph first receives a mouse-down event. If the mouse button goes up, then down again within DoubleClickTime, then 'doubleClick: evt' is sent to the morph. If the mouse button goes up but not down again within DoubleClickTime, then the message 'click: evt' is sent to the morph. Finally, if the button does not go up within DoubleClickTime, then 'drag: evt' is sent to the morph. In all cases, the event supplied is the original mouseDown event that initiated the gesture. mouseMove: and mouseUp: events are not sent to the morph until it becomes the mouse focus, which is typically done by the client in its click:, doubleClick:, or drag: methods." 

	mouseClickState _ 
		MouseClickState new
			client: aMorph 
			click: clkSel 
			dblClick: dblClkSel
			dblClickTime: DoubleClickTime 
			dblClickTimeout: dblClkTimeoutSel
			drag: dragSel
			event: evt
			sendYellowButtonActivity: false! !

!HandMorph methodsFor: 'double click support' stamp: 'jmv 5/11/2009 23:38'!
waitForClicksOrDragOrSimulatedYellow: aMorph event: evt clkSel: clkSel dblClkSel: dblClkSel dblClkTimeoutSel: dblClkTimeoutSel dragSel: dragSel

	"Wait until the difference between click, double-click, or drag gesture is known, then inform the given morph what transpired. This message is sent when the given morph first receives a mouse-down event. If the mouse button goes up, then down again within DoubleClickTime, then 'doubleClick: evt' is sent to the morph. If the mouse button goes up but not down again within DoubleClickTime, then the message 'click: evt' is sent to the morph. Finally, if the button does not go up within DoubleClickTime, then 'drag: evt' is sent to the morph. In all cases, the event supplied is the original mouseDown event that initiated the gesture. mouseMove: and mouseUp: events are not sent to the morph until it becomes the mouse focus, which is typically done by the client in its click:, doubleClick:, or drag: methods." 

	mouseClickState _ 
		MouseClickState new
			client: aMorph 
			click: clkSel 
			dblClick: dblClkSel
			dblClickTime: DoubleClickTime 
			dblClickTimeout: dblClkTimeoutSel
			drag: dragSel
			event: evt
			sendYellowButtonActivity: true! !

!HandMorph methodsFor: 'double click support' stamp: 'jmv 5/11/2009 23:38'!
waitForSimulatedYellow: aMorph event: evt

	"Wait until the difference between click, double-click, or drag gesture is known, then inform the given morph what transpired. This message is sent when the given morph first receives a mouse-down event. If the mouse button goes up, then down again within DoubleClickTime, then 'doubleClick: evt' is sent to the morph. If the mouse button goes up but not down again within DoubleClickTime, then the message 'click: evt' is sent to the morph. Finally, if the button does not go up within DoubleClickTime, then 'drag: evt' is sent to the morph. In all cases, the event supplied is the original mouseDown event that initiated the gesture. mouseMove: and mouseUp: events are not sent to the morph until it becomes the mouse focus, which is typically done by the client in its click:, doubleClick:, or drag: methods." 

	mouseClickState _ 
		MouseClickState new
			client: aMorph 
			click: nil 
			dblClick: nil
			dblClickTime: DoubleClickTime 
			dblClickTimeout: nil
			drag: nil
			event: evt
			sendYellowButtonActivity: true! !


!MenuLineMorph methodsFor: 'initialization' stamp: 'jmv 5/14/2009 15:48'!
initialize
	super initialize.
	self height: 2! !

!MenuLineMorph methodsFor: 'layout' stamp: 'jmv 5/14/2009 15:44'!
minItemWidth
	^ 0
! !


!MenuMorph methodsFor: 'construction' stamp: 'jmv 5/14/2009 15:37'!
addStayUpIcons
	| closeBox pinBox w |
	titleMorph ifNil: [self setProperty: #needsTitlebarWidgets toValue: true.
		^ self].
	closeBox := IconicButton new target: self;
		actionSelector: #delete;
		labelGraphic: self class closeBoxImage;
		color: Color transparent;
		extent: 14 @ 16;
		borderWidth: 0.
	pinBox := IconicButton new target: self;
		actionSelector: #stayUp:;
		arguments: {true};
		labelGraphic: self class pushPinImage;
		color: Color transparent;
		extent: 14 @ 15;
		borderWidth: 0.
	w _ (titleMorph hasSubmorphs ifTrue: [ titleMorph firstSubmorph width ] ifFalse: [ 0 ]) + 42.
	self addMorphFront: 
		(AlignmentMorph proportional
			height: (titleMorph height max: 19);
			width: w;	"Make room for buttons"
			color: Color transparent;
			addMorph: closeBox
				fullFrame: (LayoutFrame fractions: (0@0 corner: 0@1) offsets: (0@0 corner: 16@0));
			addMorph: titleMorph
				fullFrame: (LayoutFrame fractions: (0@0 corner: 1@1) offsets: (17@0 corner: -17@0));
			addMorph: pinBox
				fullFrame: (LayoutFrame fractions: (1@0 corner: 1@1) offsets: (-16@0 corner: 0@0))).

	self flag: #jmvRemove.
	self setProperty: #hasTitlebarWidgets toValue: true.
	self removeProperty: #needsTitlebarWidgets.
	self removeStayUpItems! !

!MenuMorph methodsFor: 'construction' stamp: 'jmv 5/14/2009 15:30'!
addStayUpItem
	"Append a menu item that can be used to toggle this menu's persistence."

	self addStayUpItemSpecial! !

!MenuMorph methodsFor: 'construction' stamp: 'jmv 5/14/2009 15:36'!
addTitle: aString
	"Add a title line at the top of this menu Make aString its initial 
	contents.  
	If aSelector is not nil, then periodically obtain fresh values for its 
	contents by sending aSelector to aTarget.."

	| s p w |
	
	self flag: #jmvRemove.
	titleMorph := RectangleMorph new.
	self setTitleParametersFor: titleMorph.
	p _ titleMorph position + (4@2).
	(aString asString findTokens: String cr) do: [ :line | 
		s _ StringMorph new
			contents: line;
			font: Preferences standardMenuFont.
		s position: p.
		titleMorph addMorphBack: s.
		p _ p + (0@s height) ].
	w _ titleMorph submorphs inject: 0 into: [ :prev :each |
		prev max: each width ].
	titleMorph height: p y; width: w + 8.
	self addMorphFront: titleMorph.
	
	self flag: #jmvRemove.
	(self hasProperty: #needsTitlebarWidgets) ifTrue: [self addStayUpIcons]! !

!MenuMorph methodsFor: 'control' stamp: 'jmv 5/7/2009 08:35'!
popUpAdjacentTo: rightOrLeftPoint forHand: hand from: sourceItem
	"Present this menu at the given point under control of the given hand."

	| delta tryToPlace selectedOffset |

	hand world startSteppingSubmorphsOf: self.
	popUpOwner _ sourceItem.
	selectedOffset := (selectedItem ifNil:[self items first]) position - self position.

	tryToPlace :=
		[ :where :mustFit |
		self position: where - selectedOffset.
		delta _ self fullBoundsInWorld amountToTranslateWithin: sourceItem worldBounds.
		(delta x = 0 or: [mustFit]) ifTrue:
			[delta = (0@0) ifFalse: [self position: self position + delta].
			sourceItem owner owner addMorphFront: self.
			^ self]].
	tryToPlace 
		value: rightOrLeftPoint first value: false;
		value: rightOrLeftPoint last  - (self width @ 0) value: false;
		value: rightOrLeftPoint first value: true

	! !

!MenuMorph methodsFor: 'control' stamp: 'jmv 5/7/2009 08:35'!
popUpAt: aPoint forHand: hand in: aWorld allowKeyboard: aBoolean 
	"Present this menu at the given point under control of the given hand."

	| evt |
	self items isEmpty ifTrue: [^self].
	MenuIcons decorateMenu: self.
	(self submorphs select: [:m | m isKindOf: UpdatingMenuItemMorph]) 
		do: [:m | m updateContents].
	self 
		positionAt: aPoint
		relativeTo: (selectedItem ifNil: [self items first])
		inWorld: aWorld.
	aWorld addMorphFront: self.
	"Acquire focus for valid pop up behavior"
	hand newMouseFocus: self.
	aBoolean ifTrue: [hand newKeyboardFocus: self].
	evt := hand lastEvent.
	(evt isKeyboard or: [evt isMouse and: [evt anyButtonPressed not]]) 
		ifTrue: 
			["Select first item if button not down"

			self moveSelectionDown: 1 event: evt].
	self changed! !

!MenuMorph methodsFor: 'control' stamp: 'jmv 5/14/2009 16:15'!
popUpNoKeyboard
	"Present this menu in the current World, *not* allowing keyboard input into the menu"
self flag: #jmvRemove. "?"
	^ self popUpAt: ActiveHand position forHand: ActiveHand in: ActiveWorld allowKeyboard: false! !

!MenuMorph methodsFor: 'copying' stamp: 'jmv 5/14/2009 15:46'!
veryDeepInner: deepCopier
	"Copy all of my instance variables.  Some need to be not copied at all, but shared.  	Warning!!!!  Every instance variable defined in this class must be handled.  We must also implement veryDeepFixupWith:.  See DeepCopier class comment."

super veryDeepInner: deepCopier.
"defaultTarget _ defaultTarget.		Weakly copied"
selectedItem _ selectedItem veryDeepCopyWith: deepCopier.
stayUp _ stayUp veryDeepCopyWith: deepCopier.
popUpOwner _ popUpOwner.		"Weakly copied"
activeSubMenu _ activeSubMenu. "Weakly copied"

"deberiamos buscar el morph en la copia (1er submorph o adentro de el)"
self flag: #jmvRemove.
titleMorph _ titleMorph! !

!MenuMorph methodsFor: 'initialization' stamp: 'jmv 5/9/2009 14:47'!
initialize
	super initialize.
	bounds _ 0@0 corner: 40@10.
	self setDefaultParameters.
	defaultTarget _ nil.
	selectedItem _ nil.
	stayUp _ false.
	popUpOwner _ nil
! !

!MenuMorph methodsFor: 'initialization' stamp: 'jmv 5/7/2009 08:31'!
intoWorld: aWorld

	super intoWorld: aWorld.
	self adjustSubmorphsLayout! !

!MenuMorph methodsFor: 'keyboard control' stamp: 'jmv 5/7/2009 08:36'!
displayFiltered: evt 
	| matchStr allItems isMatch matches feedbackMorph |
	matchStr := self valueOfProperty: #matchString.
	allItems := self submorphs select: [:m | m isKindOf: MenuItemMorph].
	matches := allItems select: 
					[:m | 
					isMatch := matchStr isEmpty 
								or: [m contents includesSubstring: matchStr caseSensitive: false].
					m isEnabled: isMatch.
					isMatch].
	feedbackMorph := self valueOfProperty: #feedbackMorph.
	feedbackMorph ifNil: 
			[feedbackMorph := (TextMorph new)
						autoFit: true;
						color: Color darkGray.
			self
				addLine;
				addMorphBack: feedbackMorph lock.
			self setProperty: #feedbackMorph toValue: feedbackMorph].
	feedbackMorph contents: '<' , matchStr , '>'.
	matchStr isEmpty 
		ifTrue: 
			[feedbackMorph delete.
			self submorphs last delete.
			self removeProperty: #feedbackMorph].
	matches size = 1 ifTrue: [self selectItem: matches first event: evt]! !

!MenuMorph methodsFor: 'menu' stamp: 'jmv 5/7/2009 14:58'!
removeStayUpBox
	| box |
	submorphs isEmpty ifTrue: [^self].
	(submorphs first isAlignmentMorph) ifFalse: [^self].
	box := submorphs first submorphs first.
	(box isKindOf: IconicButton) 
		ifTrue: [
			box
				labelGraphic: (Form extent: box extent depth: 8);
				shedSelvedge;
				borderWidth: 0;
				lock]! !

!MenuMorph methodsFor: 'private' stamp: 'jmv 5/14/2009 15:44'!
adjustSubmorphsLayout
	"Enlarge the width of submorphs as needed
	so all of them are have the same width, and no less than #minWidth.
	Also adjust their vertical position.
	Finally, set our own extent."
	
	| w p tl outerTitle |
	
	submorphs isEmpty ifTrue: [ ^self ].
	outerTitle _ submorphs first.
	w _ submorphs inject: nil into: [ :prev :each |
		prev
			ifNil: [ outerTitle width ]
			ifNotNil: [ prev max: each minItemWidth ]].

	tl _ bounds topLeft.
	p _ tl + 5.
	submorphs do: [ :m |
		m width: w.
		m position: p.
		p _ m bounds bottomLeft + (0@2) ].
	
	self extent: submorphs last bottomRight - tl + 5! !

!MenuMorph methodsFor: 'private' stamp: 'jmv 5/9/2009 15:32'!
positionAt: aPoint relativeTo: aMenuItem inWorld: aWorld
	"Note: items may not be laid out yet (I found them all to be at 0@0),  
	so we have to add up heights of items above the selected item."

	| i yOffset sub delta |
	self adjustSubmorphsLayout.
	i _ 0.
	yOffset _ 0.
	[(sub _ self submorphs at: (i _ i + 1)) == aMenuItem]
		whileFalse: [yOffset _ yOffset + sub height].

	self position: aPoint - (2 @ (yOffset + 8)).

	"If it doesn't fit, show it to the left, not to the right of the hand."
	self right > aWorld worldBounds right
		ifTrue:
			[self right: aPoint x + 1].

	"Make sure that the menu fits in the world."
	delta _ self bounds amountToTranslateWithin:
		(aWorld worldBounds withHeight: ((aWorld worldBounds height - 18) max: (ActiveHand position y) + 1)).
	delta = (0 @ 0) ifFalse: [self position: self position + delta]! !


!MVCMenuMorph methodsFor: 'invoking' stamp: 'jmv 5/14/2009 15:28'!
informUserAt: aPoint during: aBlock
	"Add this menu to the Morphic world during the execution of the given block."

	| w titleString |

	titleString _ titleMorph submorphs first.
	self visible: false.
	w _ ActiveWorld.
	aBlock value:[:string|
		self visible ifFalse:[
			w addMorph: self centeredNear: aPoint.
			self visible: true].
		titleString contents: string.
		titleMorph width: titleString width + 8.
		self setConstrainedPosition: Sensor cursorPoint hangOut: false.
		self adjustSubmorphsLayout.
		self changed.
		w displayWorld		 "show myself"
	]. 
	self delete.
	w displayWorld! !


!AlignmentMorph class methodsFor: 'instance creation' stamp: 'jmv 5/7/2009 21:48'!
proportional

	^ self new! !


!MenuMorph class methodsFor: 'example' stamp: 'jmv 5/7/2009 08:32'!
example
	"MenuMorph example openInWorld"

	| menu |
	menu _ MenuMorph new.
	menu addStayUpItem.
	menu add: 'apples' action: #apples.
	menu add: 'oranges' action: #oranges.
	menu addLine.
	menu addLine.  "extra lines ignored"
	menu add: 'peaches' action: #peaches.
	menu addLine.
	menu add: 'pears' action: #pears.
	menu addLine.
	^ menu
! !

!MenuMorph class methodsFor: 'example' stamp: 'jmv 5/14/2009 15:23'!
example2
	"MenuMorph example2 openInWorld"

	| menu |
	menu _ MenuMorph entitled: 'sdfasdfa sfda sdf as df as fd'.
	menu addStayUpItem.
	menu add: 'apples' action: #apples.
	menu add: 'oranges' action: #oranges.
	menu addLine.
	menu addLine.  "extra lines ignored"
	menu add: 'peaches' action: #peaches.
	menu addLine.
	menu add: 'pears' action: #pears.
	menu addLine.
	^ menu
! !


!MorphExtension methodsFor: 'accessing - layout properties' stamp: 'jmv 5/7/2009 15:37'!
layoutFrame: aLayoutFrame 

"lo tuve que sacar de los botoncitos de las ventanas... si no sirve mas, sacarlo!!"
self flag: #jmvRemove.

	aLayoutFrame isNil
		ifTrue: [self removeProperty: #layoutFrame]
		ifFalse: [self setProperty: #layoutFrame toValue: aLayoutFrame]! !

!MorphExtension methodsFor: 'accessing - layout properties' stamp: 'jmv 5/4/2009 15:46'!
layoutPolicy	self flag: #jmvRemove.
	^self valueOfProperty: #layoutPolicy ifAbsent:[nil]! !

!MorphExtension methodsFor: 'accessing - layout properties' stamp: 'jmv 5/4/2009 15:46'!
layoutPolicy: aLayoutPolicy 	self flag: #jmvRemove.
	aLayoutPolicy isNil
		ifTrue: [self removeProperty: #layoutPolicy]
		ifFalse: [self setProperty: #layoutPolicy toValue: aLayoutPolicy]! !


!MouseClickState methodsFor: 'initialize' stamp: 'jmv 5/11/2009 23:37'!
client: aMorph click: aClickSelector dblClick: aDblClickSelector dblClickTime: timeOut dblClickTimeout: aDblClickTimeoutSelector drag: aDragSelector event: firstClickEvent sendYellowButtonActivity: aBoolean
	clickClient _ aMorph.
	clickSelector _ aClickSelector.
	dblClickSelector _ aDblClickSelector.
	dblClickTime _ timeOut.
	dblClickTimeoutSelector _ aDblClickTimeoutSelector.
	dragSelector _ aDragSelector.
	dragThreshold _ 4.
	firstClickDown _ firstClickEvent.
	firstClickTime _ firstClickEvent timeStamp.
	clickState _ #firstClickDown.
	sendYellowButtonActivity _ aBoolean! !


!NewHandleMorph methodsFor: 'initialization' stamp: 'jmv 5/11/2009 23:53'!
initialize
"initialize the state of the receiver"

	super initialize.
""
	waitingForClickInside _ true! !


!PasteUpMorph methodsFor: 'event handling' stamp: 'jmv 5/11/2009 23:38'!
mouseDown: evt
	"Handle a mouse down event."
	| grabbedMorph handHadHalos handler |
	grabbedMorph _ self morphToGrab: evt.
	grabbedMorph ifNotNil:[
		grabbedMorph isSticky ifTrue:[^self].
		^evt hand grabMorph: grabbedMorph].

	handler _ self eventHandler.
	(handler notNil and: [handler handlesMouseDown: evt])
		ifTrue: [^handler mouseDown: evt fromMorph: self].
		
	handHadHalos _ evt hand halo notNil.
	evt hand halo: nil. "shake off halos"
	evt hand releaseKeyboardFocus. "shake of keyboard foci"
	evt shiftPressed ifTrue:[
		^evt hand 
			waitForClicksOrDrag: self 
			event: evt 
			clkSel: #findWindow:
			dblClkSel: nil
			dblClkTimeoutSel: nil
			dragSel: #dragThroughOnDesktop:].
	self isWorldMorph ifTrue: [
		handHadHalos ifTrue: [^self addAlarm: #invokeWorldMenu: with: evt after: 200].
		^self invokeWorldMenu: evt
	].
	"otherwise, explicitly ignore the event if we're not the world,
	so that we could be picked up if need be"
	self isWorldMorph ifFalse:[evt wasHandled: false].
! !

!PasteUpMorph methodsFor: 'menu & halo' stamp: 'jmv 5/11/2009 23:53'!
addWorldHaloMenuItemsTo: aMenu hand: aHandMorph
	"Add standard halo items to the menu, given that the receiver is a World"

	| unlockables |
	self addFillStyleMenuItems: aMenu hand: aHandMorph.

	aMenu addLine.
	self addWorldToggleItemsToHaloMenu: aMenu.
	aMenu addLine.
	self addCopyItemsTo: aMenu.
	self addExportMenuItems: aMenu hand: aHandMorph.

	self addDebuggingItemsTo: aMenu hand: aHandMorph.

	aMenu addLine.
	aMenu defaultTarget: self.

	aMenu addLine.

	unlockables _ self submorphs select:
		[:m | m isLocked].
	unlockables size = 1 ifTrue:
		[aMenu add: ('unlock "{1}"' translated format:{unlockables first externalName})action: #unlockContents].
	unlockables size > 1 ifTrue:
		[aMenu add: 'unlock all contents' translated action: #unlockContents.
		aMenu add: 'unlock...' translated action: #unlockOneSubpart].

	aMenu defaultTarget: aHandMorph.
! !

!PasteUpMorph methodsFor: 'project state' stamp: 'jmv 5/14/2009 17:52'!
viewBox: newViewBox 
	self isWorldMorph
		ifTrue: [(self viewBox isNil
					or: [self viewBox extent ~= newViewBox extent])
				ifTrue: [worldState canvas: nil].
			worldState viewBox: newViewBox].
	super position: newViewBox topLeft.
	fullBounds _ bounds _ newViewBox! !


!PluggableButtonMorph methodsFor: 'accessing' stamp: 'jmv 5/6/2009 08:18'!
label: aString
	"Label this button with the given string."

	self label: aString font: nil! !

!PluggableButtonMorph methodsFor: 'accessing' stamp: 'jmv 5/6/2009 08:27'!
label: aString font: aFont
	"Label this button with the given string."

	label _ aString asString.
	font _ aFont! !

!PluggableButtonMorph methodsFor: 'copying' stamp: 'jmv 5/6/2009 08:19'!
veryDeepInner: deepCopier
	"Copy all of my instance variables.  Some need to be not copied at all, but shared.  	Warning!!!!  Every instance variable defined in this class must be handled.  We must also implement veryDeepFixupWith:.  See DeepCopier class comment."

super veryDeepInner: deepCopier.
"model _ model.		Weakly copied"
"getStateSelector _ getStateSelector.		a Symbol"
"actionSelector _ actionSelector.		a Symbol"
"getLabelSelector _ getLabelSelector.		a Symbol"
"getMenuSelector _ getMenuSelector.		a Symbol"
shortcutCharacter _ shortcutCharacter veryDeepCopyWith: deepCopier.
askBeforeChanging _ askBeforeChanging veryDeepCopyWith: deepCopier.
triggerOnMouseDown _ triggerOnMouseDown veryDeepCopyWith: deepCopier.
offColor _ offColor veryDeepCopyWith: deepCopier.
onColor _ onColor veryDeepCopyWith: deepCopier.
feedbackColor _ feedbackColor veryDeepCopyWith: deepCopier.
showSelectionFeedback _ showSelectionFeedback veryDeepCopyWith: deepCopier.
allButtons _ nil.		"a cache"
arguments _ arguments veryDeepCopyWith: deepCopier.
argumentsProvider _ argumentsProvider veryDeepCopyWith: deepCopier.
argumentsSelector _ argumentsSelector.  " a Symbol" ! !

!PluggableButtonMorph methodsFor: 'drawing' stamp: 'jmv 5/6/2009 08:45'!
drawOn: aCanvas 

	| w f center x y |
	super drawOn: aCanvas.
	f _ self fontToUse.
	center _ bounds center.
	w _ f widthOfString: label.
	x _ bounds width > w
		ifTrue: [ center x - (w // 2) ]
		ifFalse: [ bounds left +4].
	y _ center y - (f height // 2).
	aCanvas drawString: label at: x@y font: f color: Color black.
	showSelectionFeedback ifTrue: [
		aCanvas frameRectangle: self innerBounds width: 2 color: feedbackColor].! !

!PluggableButtonMorph methodsFor: 'drawing' stamp: 'jmv 5/6/2009 08:33'!
fontToUse
	| fontToUse |
	fontToUse := font ifNil: [Preferences standardButtonFont].
	"
	Could add emphasis...
	^(emphasis isNil or: [emphasis = 0]) 
		ifTrue: [fontToUse]
		ifFalse: [fontToUse emphasized: emphasis]
	"
	^fontToUse! !

!PluggableButtonMorph methodsFor: 'event handling' stamp: 'jmv 5/11/2009 23:39'!
mouseDown: evt
	"Details: If this button is triggered on mouse down or the event is the menu gesture, handle it immediately. Otherwise, make a list of buttons (including the receiver) for mouseMove feedback. This allows a simple radio-button effect among the button submorphs of a given morph."

	allButtons _ nil.
	evt yellowButtonPressed ifTrue: [^ self yellowButtonActivity: evt shiftPressed].
	triggerOnMouseDown
		ifTrue: [self performAction]
		ifFalse: [
			allButtons _ owner submorphs select: [:m | m class = self class].
			self updateFeedbackForEvt: evt].
	evt hand 
		waitForSimulatedYellow: self 
		event: evt ! !

!PluggableButtonMorph methodsFor: 'initialization' stamp: 'jmv 5/10/2009 10:23'!
initialize
	"initialize the state of the receiver"
	super initialize.

	model _ nil.
	getStateSelector _ nil.
	actionSelector _ nil.
	getLabelSelector _ nil.
	getMenuSelector _ nil.
	shortcutCharacter _ nil.
	askBeforeChanging _ false.
	triggerOnMouseDown _ false.
	onColor _ self color darker.
	offColor _ self color.
	feedbackColor _ Color red.
	showSelectionFeedback _ false.
	allButtons _ nil.
	argumentsProvider _ nil.
	argumentsSelector _ nil.
	self extent: 20 @ 15! !


!PluggableButtonMorph class methodsFor: 'example' stamp: 'jmv 5/6/2009 09:20'!
example
	"PluggableButtonMorph example openInWorld"

	| s1 s2 s3 b1 b2 b3 row |
	s1 _ Switch new.
	s2 _ Switch new turnOn.
	s3 _ Switch new.
	s2 onAction: [s3 turnOff].
	s3 onAction: [s2 turnOff].
	b1 _ (PluggableButtonMorph on: s1 getState: #isOn action: #switch) label: 'S1'.
	b2 _ (PluggableButtonMorph on: s2 getState: #isOn action: #turnOn) label: 'S2'.
	b3 _ (PluggableButtonMorph on: s3 getState: #isOn action: #turnOn) label: 'S3'.
	b1
		hResizing: #spaceFill;
		vResizing: #spaceFill.
	b2
		hResizing: #spaceFill;
		vResizing: #spaceFill.
	b3
		hResizing: #spaceFill;
		vResizing: #spaceFill.

	row _ AlignmentMorph proportional
		addInRow: (Array with: b1 with: b2 with: b3);
		extent: 120@35.
	^ row
! !


!Preferences class methodsFor: 'misc' stamp: 'jmv 5/11/2009 23:54'!
defaultValueTableForCurrentRelease
	"Answer a table defining default values for all the preferences in the release.  Returns a list of (pref-symbol, boolean-symbol) pairs"

	^  #(
		(abbreviatedBrowserButtons false)
		(alternativeBrowseIt false)
		(alternativeWindowLook true)
		(annotationPanes false)
		(automaticFlapLayout true)
		(automaticPlatformSettings true)
		(balloonHelpEnabled true)
		(browseWithPrettyPrint false)
		(browserShowsPackagePane false)
		(canRecordWhilePlaying false)
		(caseSensitiveFinds false)
		(changeSetVersionNumbers true)
		(checkForSlips true)
		(classicNewMorphMenu false)
		(cmdDotEnabled true)
		(collapseWindowsInPlace false)
		(colorWhenPrettyPrinting false)
		(confirmFirstUseOfStyle true)
		(conversionMethodsAtFileOut false)
		(cpuWatcherEnabled false)
		(debugHaloHandle true)
		(debugPrintSpaceLog false)
		(debugShowDamage false)
		(decorateBrowserButtons true)
		(diffsInChangeList true)
		(diffsWithPrettyPrint false)
		(dismissAllOnOptionClose false)
		(fastDragWindowForMorphic true)
		(fullScreenLeavesDeskMargins true)
		(hiddenScrollBars false)
		(higherPerformance false)
		(honorDesktopCmdKeys true)
		(ignoreStyleIfOnlyBold true)
		(inboardScrollbars true)
		(logDebuggerStackToFile true)
		(menuButtonInToolPane false)
		(menuColorFromWorld false)
		(menuKeyboardControl false)  
		(modalColorPickers true)
		(optionalButtons true)
		(personalizedWorldMenu true)
		(projectsSentToDisk false)
		(propertySheetFromHalo false)
		(restartAlsoProceeds false)
		(reverseWindowStagger true)
		(scrollBarsNarrow false)
		(scrollBarsWithoutMenuButton false)
		(selectiveHalos false)
		(showBoundsInHalo false)
		(simpleMenus false)
		(smartUpdating true)
		(soundQuickStart false)
		(soundStopWhenDone false)
		(soundsEnabled true)
		(systemWindowEmbedOK false)
		(thoroughSenders true)
		(twentyFourHourFileStamps true)
		(uniqueNamesInHalos false)
		(warnIfNoChangesFile true)
		(warnIfNoSourcesFile true))


"
Preferences defaultValueTableForCurrentRelease do:
	[:pair | (Preferences preferenceAt: pair first ifAbsent: [nil]) ifNotNilDo:
			[:pref | pref defaultValue: (pair last == #true)]].
Preferences chooseInitialSettings.
"! !

!Preferences class methodsFor: 'personalization' stamp: 'jmv 5/11/2009 23:55'!
disableProgrammerFacilities
	"Warning: do not call this lightly!!  It disables all access to menus, debuggers, halos.  There is no guaranteed return from this, which is to say, you cannot necessarily reenable these things once they are disabled -- you can only use whatever the UI of the current project affords, and you cannot even snapshot -- you can only quit. 

     You can completely reverse the work of this method by calling the dual Preferences method enableProgrammerFacilities, provided you have left yourself leeway to bring about a call to that method.

	To set up a system that will come up in such a state, you have to request the snapshot in the same breath as you disable the programmer facilities.  To do this, put the following line into the 'do' menu and then evaluate it from that 'do' menu:

         Preferences disableProgrammerFacilities.

You will be prompted for a new image name under which to save the resulting image."

	Beeper beep.
	(self confirm: 'CAUTION!!!!
This is a drastic step!!
Do you really want to do this?')
		ifFalse:
			[self beep.  ^ self inform: 'whew!!'].

	self disable: #cmdDotEnabled.       "No user-interrupt-into-debugger"

	self compileHardCodedPref: #cmdGesturesEnabled enable: false.  "No halos, etc."

	self compileHardCodedPref: #cmdKeysInText enable: false.    "No user commands invokable via cmd-key combos in text editor"

	"self enable: #noviceMode."           "No control-menu"
	self disable: #warnIfNoSourcesFile.
	self disable: #warnIfNoChangesFile.
	Smalltalk saveAs! !

!Preferences class methodsFor: 'personalization' stamp: 'jmv 5/11/2009 23:55'!
enableProgrammerFacilities
	"Meant as a one-touch recovery from a #disableProgrammerFacilities call."
	"Preferences enableProgrammerFacilities"

	self enable: #cmdDotEnabled.
	self compileHardCodedPref: #cmdGesturesEnabled enable: true. 
	self compileHardCodedPref: #cmdKeysInText enable: true.
"	self disable: #noviceMode."
	self enable: #warnIfNoSourcesFile.
	self enable: #warnIfNoChangesFile.! !

!Preferences class methodsFor: 'standard queries' stamp: 'dgd 3/21/2003 19:23'!
alternativeWindowBoxesLook
	^ self
		valueOfFlag: #alternativeWindowBoxesLook
		ifAbsent: [true]! !

!Preferences class methodsFor: 'standard queries' stamp: 'jmv 5/4/2009 23:27'!
alternativeWindowLook
	^ self
		valueOfFlag: #alternativeWindowLook
		ifAbsent: [true]! !

!Preferences class methodsFor: 'themes' stamp: 'jmv 5/11/2009 23:54'!
brightSqueak
	"The classic bright Squeak look.  Windows have saturated colors and relatively low contrast; scroll-bars are of the flop-out variety and are on the left.  Many power-user features are enabled."

	self setPreferencesFrom:
	#(
		(alternativeWindowLook false)
		(annotationPanes true)
		(automaticFlapLayout true)
		(balloonHelpEnabled true)
		(browseWithPrettyPrint false)
		(browserShowsPackagePane false)
		(classicNewMorphMenu false)
		(cmdDotEnabled true)
		(collapseWindowsInPlace false)
		(colorWhenPrettyPrinting false)
		(debugHaloHandle true)
		(debugPrintSpaceLog false)
		(debugShowDamage false)
		(decorateBrowserButtons true)
		(diffsInChangeList true)
		(diffsWithPrettyPrint false)
		(fastDragWindowForMorphic true)
		(fullScreenLeavesDeskMargins true)
		(hiddenScrollBars false)
		(ignoreStyleIfOnlyBold true)
		(inboardScrollbars false)
		(logDebuggerStackToFile true)
		(menuButtonInToolPane false)
		(menuColorFromWorld false)
		(menuKeyboardControl true)
		(optionalButtons true)
		(personalizedWorldMenu true)
		(propertySheetFromHalo false)
		(restartAlsoProceeds false)
		(reverseWindowStagger true)
		(scrollBarsNarrow false)
		(scrollBarsWithoutMenuButton false)
		(selectiveHalos false)
		(simpleMenus false)
		(smartUpdating true)
		(systemWindowEmbedOK false)
		(thoroughSenders true)
		(warnIfNoChangesFile true)
		(warnIfNoSourcesFile true))! !

!Preferences class methodsFor: 'themes' stamp: 'jmv 5/13/2009 15:56'!
juans

	self setPreferencesFrom:

	#(
		(alternativeWindowLook true)
		(annotationPanes true)
		(balloonHelpEnabled false)
		(browseWithPrettyPrint false)
		(browserShowsPackagePane false)
		(caseSensitiveFinds true)
		(checkForSlips true)
		(cmdDotEnabled true)
		(collapseWindowsInPlace false)
		(colorWhenPrettyPrinting false)
		(diffsInChangeList true)
		(diffsWithPrettyPrint false)
		(fastDragWindowForMorphic true)
		(honorDesktopCmdKeys false)
		(ignoreStyleIfOnlyBold true)
		(inboardScrollbars true)
		(menuColorFromWorld false)
		(menuKeyboardControl true)
		(optionalButtons true)
		(personalizedWorldMenu false)
		(restartAlsoProceeds false)
		(scrollBarsNarrow true)
		(scrollBarsWithoutMenuButton false)
		(simpleMenus false)
		(smartUpdating true)
		(subPixelRenderFonts true)
		(thoroughSenders true)
	)! !

!Preferences class methodsFor: 'themes' stamp: 'jmv 5/11/2009 23:55'!
paloAlto
	"Similar to the brightSqueak theme, but with a number of idiosyncratic personal settings.   Note that caseSensitiveFinds is true"


	self setPreferencesFrom:
	#(
		(abbreviatedBrowserButtons false)
		(accessOnlineModuleRepositories noOpinion)
		(alternativeBrowseIt noOpinion)
		(alternativeWindowLook false)
		(annotationPanes true)
		(automaticFlapLayout true)
		(automaticPlatformSettings noOpinion)
		(balloonHelpEnabled true)
		(browseWithPrettyPrint false)
		(browserShowsPackagePane false)
		(canRecordWhilePlaying noOpinion)
		(caseSensitiveFinds true)
		(changeSetVersionNumbers true)
		(checkForSlips true)
		(classicNewMorphMenu false)
		(cmdDotEnabled true)
		(collapseWindowsInPlace false)
		(colorWhenPrettyPrinting false)
		(confirmFirstUseOfStyle true)
		(conservativeModuleDeActivation noOpinion)
		(conversionMethodsAtFileOut true)
		(cpuWatcherEnabled noOpinion)
		(debugHaloHandle true)
		(debugPrintSpaceLog true)
		(debugShowDamage false)
		(decorateBrowserButtons true)
		(diffsInChangeList true)
		(diffsWithPrettyPrint false)
		(dismissAllOnOptionClose true)
		(duplicateControlAndAltKeys false)
		(extraDebuggerButtons true)
		(fastDragWindowForMorphic true)
		(fullScreenLeavesDeskMargins true)
		(hiddenScrollBars false)
		(higherPerformance noOpinion)
		(honorDesktopCmdKeys true)
		(ignoreStyleIfOnlyBold true)
		(inboardScrollbars false)
		(logDebuggerStackToFile true)
		(menuButtonInToolPane false)
		(menuColorFromWorld false)
		(menuKeyboardControl true)  
		(modalColorPickers true)
		(modularClassDefinitions noOpinion)
		(optionalButtons true)
		(personalizedWorldMenu true)
		(projectsSentToDisk noOpinion)
		(propertySheetFromHalo false)
		(restartAlsoProceeds false)
		(reverseWindowStagger true)
		(scrollBarsNarrow false)
		(scrollBarsWithoutMenuButton false)
		(selectiveHalos false)
		(showBoundsInHalo false)
		(simpleMenus false)
		(smartUpdating true)
		(soundQuickStart noOpinion)
		(soundsEnabled true)
		(soundStopWhenDone noOpinion)
		(strongModules noOpinion)
		(swapControlAndAltKeys noOpinion)
		(swapMouseButtons  noOpinion)
		(systemWindowEmbedOK false)
		(thoroughSenders true)
		(twentyFourHourFileStamps false)
		(uniqueNamesInHalos false)
		(warnIfNoChangesFile true)
		(warnIfNoSourcesFile true))! !

!Preferences class methodsFor: 'themes' stamp: 'jmv 5/13/2009 15:56'!
slowMachine

	self setPreferencesFrom:

	#(
		(alternativeWindowLook false)
		(annotationPanes false)
		(balloonHelpEnabled false)
		(browseWithPrettyPrint false)
		(browserShowsPackagePane false)
		(caseSensitiveFinds true)
		(checkForSlips false)
		(cmdDotEnabled true)
		(collapseWindowsInPlace false)
		(colorWhenPrettyPrinting false)
		(diffsInChangeList false)
		(diffsWithPrettyPrint false)
		(fastDragWindowForMorphic true)
		(honorDesktopCmdKeys false)
		(ignoreStyleIfOnlyBold true)
		(inboardScrollbars true)
		(menuColorFromWorld false)
		(menuKeyboardControl false)
		(optionalButtons false)
		(personalizedWorldMenu false)
		(restartAlsoProceeds false)
		(scrollBarsNarrow false)
		(scrollBarsWithoutMenuButton false)
		(simpleMenus false)
		(smartUpdating false)
		(subPixelRenderFonts false)
		(thoroughSenders false)
	)! !

!Preferences class methodsFor: 'themes' stamp: 'jmv 5/11/2009 23:55'!
smalltalk80
	"A traditional monochrome Smalltalk-80 look and feel, clean and austere, and lacking many features added to Squeak in recent years. Caution: this theme removes the standard Squeak flaps, turns off the 'smartUpdating' feature that keeps multiple browsers in synch, and much more."

	self setPreferencesFrom:

	#(
		(alternativeWindowLook false)
		(annotationPanes false)
		(balloonHelpEnabled false)
		(browseWithPrettyPrint false)
		(browserShowsPackagePane false)
		(caseSensitiveFinds true)
		(checkForSlips false)
		(cmdDotEnabled true)
		(collapseWindowsInPlace false)
		(colorWhenPrettyPrinting false)
		(diffsInChangeList false)
		(diffsWithPrettyPrint false)
		(fastDragWindowForMorphic true)
		(honorDesktopCmdKeys false)
		(ignoreStyleIfOnlyBold true)
		(inboardScrollbars false)
		(menuColorFromWorld false)
		(menuKeyboardControl false)
		(optionalButtons false)
		(personalizedWorldMenu false)
		(restartAlsoProceeds false)
		(scrollBarsNarrow false)
		(scrollBarsWithoutMenuButton false)
		(simpleMenus false)
		(smartUpdating false)
		(thoroughSenders false)
	)! !


!ProcessBrowser methodsFor: 'views' stamp: 'jmv 5/12/2009 18:11'!
asPrototypeInWindow
	"Create a pluggable version of me, answer a window"

	| window aTextMorph |
	window _ SystemWindow new model: self.
	window
		addMorph: ((PluggableListMorph
				on: self
				list: #processNameList
				selected: #processListIndex
				changeSelected: #processListIndex:
				menu: #processListMenu:
				keystroke: #processListKey:from:)
				enableDragNDrop: false)
		frame: (0 @ 0 extent: 0.5 @ 0.5).
	window
		addMorph: ((PluggableListMorph
				on: self
				list: #stackNameList
				selected: #stackListIndex
				changeSelected: #stackListIndex:
				menu: #stackListMenu:
				keystroke: #stackListKey:from:)
				enableDragNDrop: false)
		frame: (0.5 @ 0.0 extent: 0.5 @ 0.5).
	aTextMorph _ PluggableTextMorph
				on: self
				text: #selectedMethod
				accept: nil
				readSelection: nil
				menu: nil.
	window
		addMorph: aTextMorph
		frame: (0 @ 0.5 corner: 1 @ 1).
	window setLabel: 'Process Browser'.
	^ window! !

!ProcessBrowser methodsFor: 'views' stamp: 'jmv 5/12/2009 18:11'!
openAsMorph
	"Create a pluggable version of me, answer a window"
	| window aTextMorph |
	window _ SystemWindow new
				model: self.

	deferredMessageRecipient _ WorldState.
	window
		addMorph: ((PluggableListMorph
				on: self
				list: #processNameList
				selected: #processListIndex
				changeSelected: #processListIndex:
				menu: #processListMenu:
				keystroke: #processListKey:from:)
				enableDragNDrop: false)
		frame: (0 @ 0 extent: 0.5 @ 0.5).
	window
		addMorph: ((PluggableListMorph
				on: self
				list: #stackNameList
				selected: #stackListIndex
				changeSelected: #stackListIndex:
				menu: #stackListMenu:
				keystroke: #stackListKey:from:)
				enableDragNDrop: false)
		frame: (0.5 @ 0.0 extent: 0.5 @ 0.5).
	aTextMorph _ PluggableTextMorph
				on: self
				text: #selectedMethod
				accept: nil
				readSelection: nil
				menu: nil.
	aTextMorph askBeforeDiscardingEdits: false.
	window
		addMorph: aTextMorph
		frame: (0 @ 0.5 corner: 1 @ 1).
	window setUpdatablePanesFrom: #(#processNameList #stackNameList ).
	(window setLabel: 'Process Browser') openInWorld.
	startedCPUWatcher ifTrue: [ self setUpdateCallbackAfter: 7 ].
	^ window! !


!ProgressMorph methodsFor: 'accessing' stamp: 'jmv 5/4/2009 14:17'!
done
	^progress value contents! !

!ProgressMorph methodsFor: 'accessing' stamp: 'jmv 5/4/2009 14:17'!
done: amountDone
	progress value contents: ((amountDone min: 1.0) max: 0.0).
	"?
	self currentWorld displayWorld
	"! !

!ProgressMorph methodsFor: 'accessing' stamp: 'jmv 5/4/2009 14:57'!
label: aString
	self label: aString subLabel: ''! !

!ProgressMorph methodsFor: 'accessing' stamp: 'jmv 5/4/2009 14:58'!
label: aString subLabel: otherString
	labelMorph contents: aString.
	subLabelMorph contents: otherString.
	self setupMorphs! !

!ProgressMorph methodsFor: 'accessing' stamp: 'jmv 5/4/2009 14:17'!
subLabel: aString
	subLabelMorph contents: aString.
	"?
	self currentWorld displayWorld
	"! !

!ProgressMorph methodsFor: 'initialization' stamp: 'jmv 5/4/2009 14:59'!
initialize
	super initialize.
	self initLabelMorph; initSubLabelMorph; initProgressMorph.
	self addMorphBack: labelMorph.
	self addMorphBack: subLabelMorph.
	self addMorphBack: progress.! !

!ProgressMorph methodsFor: 'initialization' stamp: 'jmv 5/4/2009 15:01'!
setupMorphs
	|  x w y h |

	w _ ((labelMorph width max: subLabelMorph width) max: progress width) + 2.
	x _ w // 2.
	y _ 0.
	h _ labelMorph height + subLabelMorph height + progress height + 1.
	labelMorph position: x - (labelMorph width // 2)@y.
	y _ y + labelMorph height.
	subLabelMorph position: x - (subLabelMorph width // 2)@y.
	y _ y + subLabelMorph height.
	progress position: x - (progress width //2)@y.
	self bounds: (0@0 extent: w@h).

	self borderWidth: 2.
	self borderColor: Color black.

	self color: Color veryLightGray.
	self align: self fullBounds center with: Display boundingBox center
! !


!ProgressMorph class methodsFor: 'example' stamp: 'jmv 5/4/2009 14:59'!
example
	"ProgressMorph example"

	| progress |
	progress _ ProgressMorph label: 'Test progress' subLabel: 'this is the subheading'.
	progress openInWorld.
	[10 timesRepeat:
		[(Delay forMilliseconds: 200) wait.
		progress incrDone: 0.1].
	progress delete] fork! !

!ProgressMorph class methodsFor: 'instance creation' stamp: 'jmv 5/4/2009 15:00'!
label: aString
	^self label: aString subLabel: ''! !

!ProgressMorph class methodsFor: 'instance creation' stamp: 'jmv 5/4/2009 14:59'!
label: aString subLabel: otherString
	^self new label: aString subLabel: otherString! !


!RealEstateAgent class methodsFor: 'as yet unclassified' stamp: 'jmv 5/12/2009 08:50'!
assignCollapseFrameFor: aSystemWindow 
        "Offer up a location along the left edge of the screen for a collapsed SystemWindow. Make sure it doesn't overlap any other collapsed frames."
        | grid otherFrames topLeft viewBox collapsedFrame extent newFrame verticalBorderDistance top |
        grid _ 8.
        verticalBorderDistance _ 8.
	otherFrames _ (SystemWindow windowsIn: aSystemWindow world satisfying: [:w | w ~= aSystemWindow])
		collect: [:w | w collapsedFrame]
		thenSelect: [:rect | rect notNil].
	viewBox _ aSystemWindow world viewBox.
        collapsedFrame _ aSystemWindow collapsedFrame.
        extent _ collapsedFrame notNil
                                ifTrue: [collapsedFrame extent]
                                ifFalse: [ aSystemWindow collapsedExtent ].
        collapsedFrame notNil
                ifTrue: [(otherFrames anySatisfy: [:f | collapsedFrame intersects: f])
                                ifFalse: ["non overlapping"
                                        ^ collapsedFrame]].
        top _ viewBox top + verticalBorderDistance.
        [topLeft _ viewBox left @ top.
        newFrame _ topLeft extent: extent.
        newFrame bottom <= (viewBox height - verticalBorderDistance)]
                whileTrue: 
                        [(otherFrames anySatisfy: [:w | newFrame intersects: w])
                                ifFalse: ["no overlap"
                                        ^ newFrame].
                        top _ top + grid].
        "If all else fails... (really to many wins here)"
        ^ 0 @ 0 extent: extent! !


!ScrollPane methodsFor: 'event handling' stamp: 'jmv 5/11/2009 23:39'!
mouseDown: evt

	evt yellowButtonPressed  "First check for option (menu) click"
		ifTrue: [^ self yellowButtonActivity: evt shiftPressed].
	"If pane is not full, pass the event to the last submorph,
	assuming it is the most appropriate recipient (!!)"
	scroller hasSubmorphs ifTrue:
		[scroller submorphs last mouseDown: (evt transformedBy: (scroller transformFrom: self))].
	evt hand 
		waitForSimulatedYellow: self 
		event: evt! !


!PluggableListMorph methodsFor: 'events' stamp: 'jmv 5/11/2009 23:39'!
mouseDown: evt

	| row |
	evt yellowButtonPressed  "First check for option (menu) click"
		ifTrue: [^ self yellowButtonActivity: evt shiftPressed].
	self hasKeyboardFocus ifFalse: [
		evt hand newKeyboardFocus: self.
		"If we are focusing, deselect, so that later selection doesn't result in deselect."
		self listMorph noSelection].
	row _ self rowAtLocation: evt position.
	row = 0  ifTrue: [^super mouseDown: evt].
	"self dragEnabled ifTrue: [aMorph highlightForMouseDown]."
	evt hand 
		waitForClicksOrDragOrSimulatedYellow: self
		event: evt
		clkSel: #click:
		dblClkSel: (doubleClickSelector ifNotNil:[#doubleClick:])
		dblClkTimeoutSel: nil
		dragSel: (self dragEnabled ifTrue:[#startDrag:] ifFalse:[nil])! !


!PluggableListMorphOfMany methodsFor: 'event handling' stamp: 'jmv 5/11/2009 23:39'!
mouseDown: event

	| oldIndex oldVal row |
	event yellowButtonPressed ifTrue: [^ self yellowButtonActivity: event shiftPressed].

	self hasKeyboardFocus ifFalse: [
		event hand newKeyboardFocus: self ].

	row := self rowAtLocation: event position.

	row = 0 ifTrue: [^super mouseDown: event].

	model okToChange ifTrue: ["No change if model is locked"

		"Set meaning for subsequent dragging of selection"
		dragOnOrOff _ (self listSelectionAt: row) not.
		oldIndex _ self getCurrentSelectionIndex.
		oldIndex ~= 0 ifTrue: [oldVal _ self listSelectionAt: oldIndex].

		"Set or clear new primary selection (listIndex)"
		dragOnOrOff
			ifTrue: [self changeModelSelection: row]
			ifFalse: [self changeModelSelection: 0].

		"Need to restore the old one, due to how model works, and set new one."
		oldIndex ~= 0 ifTrue: [self listSelectionAt: oldIndex put: oldVal].
		self listSelectionAt: row put: dragOnOrOff.
		"event hand releaseMouseFocus: aMorph."
		"aMorph changed"
	].
	event hand 
		waitForSimulatedYellow: self 
		event: event ! !


!SimpleButtonMorph methodsFor: 'accessing' stamp: 'jmv 5/6/2009 12:09'!
fitContents
	| aCenter f w e |
	aCenter := self center.
	label ifNil: [^self].
	f _ self fontToUse.
	w _ f widthOfString: label.
	e _ w@f height.
	self extent: e + (borderWidth + 6).
	self center: aCenter! !

!SimpleButtonMorph methodsFor: 'accessing' stamp: 'jmv 5/6/2009 09:09'!
label

	^label ifNil: ['']! !

!SimpleButtonMorph methodsFor: 'accessing' stamp: 'jmv 5/6/2009 08:55'!
label: aString
	"Label this button with the given string."

	self label: aString font: nil! !

!SimpleButtonMorph methodsFor: 'accessing' stamp: 'jmv 5/6/2009 12:11'!
label: aString font: aFont
	"Label this button with the given string."

	label _ aString asString.
	font _ aFont.
	self fitContents! !

!SimpleButtonMorph methodsFor: 'copying' stamp: 'jmv 5/6/2009 09:16'!
veryDeepInner: deepCopier
	"Copy all of my instance variables.  Some need to be not copied at all, but shared.  	Warning!!!!  Every instance variable defined in this class must be handled.  We must also implement veryDeepFixupWith:.  See DeepCopier class comment."

super veryDeepInner: deepCopier.
"target _ target.		Weakly copied"
"actionSelector _ actionSelector.		a Symbol"
"arguments _ arguments.		All weakly copied"
actWhen _ actWhen veryDeepCopyWith: deepCopier.
oldColor _ oldColor veryDeepCopyWith: deepCopier.

"shared"
label _ label.
font _ font! !

!SimpleButtonMorph methodsFor: 'menu' stamp: 'jmv 5/6/2009 08:53'!
setLabel

	| newLabel |
	newLabel _ FillInTheBlank
		request: 'Please enter a new label for this button'
		initialAnswer: self label.
	newLabel isEmpty ifFalse: [self label: newLabel].
! !

!SimpleButtonMorph methodsFor: 'drawing' stamp: 'jmv 5/6/2009 09:10'!
drawOn: aCanvas 

	| w f center x y |
	super drawOn: aCanvas.
	label ifNotNil: [
		f _ self fontToUse.
		center _ bounds center.
		w _ f widthOfString: label.
		x _ bounds width > w
			ifTrue: [ center x - (w // 2) ]
			ifFalse: [ bounds left +4].
		y _ center y - (f height // 2).
		aCanvas drawString: label at: x@y font: f color: Color black ]! !

!SimpleButtonMorph methodsFor: 'drawing' stamp: 'jmv 5/6/2009 08:55'!
fontToUse
	| fontToUse |
	fontToUse := font ifNil: [Preferences standardButtonFont].
	"
	Could add emphasis...
	^(emphasis isNil or: [emphasis = 0]) 
		ifTrue: [fontToUse]
		ifFalse: [fontToUse emphasized: emphasis]
	"
	^fontToUse! !


!IconicButton methodsFor: 'as yet unclassified' stamp: 'jmv 5/6/2009 12:22'!
labelGraphic: aForm
	| oldLabel graphicalMorph |
	(oldLabel _ self findA: SketchMorph)
		ifNotNil: [oldLabel delete].
	graphicalMorph _ SketchMorph withForm: aForm.
	"this could use a #fitContents method, like the superclass..."
	self extent: graphicalMorph extent + (borderWidth + 6).
	graphicalMorph position: self center - (graphicalMorph extent // 2).
	self addMorph: graphicalMorph.
	graphicalMorph lock
! !

!IconicButton methodsFor: 'geometry' stamp: 'jmv 5/6/2009 12:21'!
extent: newExtent
	| i |
	super extent: newExtent.
	submorphs size = 1 ifTrue:
		["keep the icon centered"
		"NOTE: may want to test more that it IS an icon..."
		i _ self firstSubmorph.
		i position: self center - (i extent // 2)]! !


!SimpleHierarchicalListMorph methodsFor: 'event handling' stamp: 'jmv 5/11/2009 23:39'!
mouseDown: evt

	| aMorph |
	evt hand newKeyboardFocus: self.
	aMorph _ self itemFromPoint: evt position.
	(aMorph notNil and:[aMorph inToggleArea: (aMorph point: evt position from: self)])
		ifTrue:[^self toggleExpandedState: aMorph event: evt]. 
	evt yellowButtonPressed  "First check for option (menu) click"
		ifTrue: [^ self yellowButtonActivity: evt shiftPressed].
	aMorph ifNil:[^super mouseDown: evt].
	aMorph highlightForMouseDown.
	evt hand 
		waitForClicksOrDragOrSimulatedYellow: self 
		event: evt 
		clkSel: #click:
		dblClkSel: nil
		dblClkTimeoutSel: nil
		dragSel:  (self dragEnabled ifTrue:[#startDrag:] ifFalse:[nil])! !


!SketchMorph methodsFor: 'accessing' stamp: 'jmv 5/5/2009 16:46'!
form: aForm
	"Set the receiver's form"

	| oldForm |
	oldForm _ originalForm.
	originalForm _ aForm.
	self rotationCenter: 0.5@0.5.
	self layoutChanged.

	oldForm ifNotNil: [self position: self position + (oldForm extent - aForm extent // 2)].
! !

!SketchMorph methodsFor: 'menu' stamp: 'jmv 5/5/2009 16:42'!
addCustomMenuItems: aCustomMenu hand: aHandMorph
	"Add custom menu items"

	super addCustomMenuItems: aCustomMenu hand: aHandMorph.
	aCustomMenu addLine.
	aCustomMenu add: 'set as background' translated target: rotatedForm action: #setAsBackground.
	self addPaintingItemsTo: aCustomMenu hand: aHandMorph! !


!ColorPickerMorph methodsFor: 'accessing' stamp: 'jmv 5/7/2009 13:07'!
selector: aSymbol
	"Set the selector to be associated with the receiver.  Store it in the receiver's command, if appropriate"

	selector _ aSymbol! !

!ColorPickerMorph methodsFor: 'initialization' stamp: 'jmv 5/7/2009 13:07'!
buildChartForm
	| chartForm |
	chartForm _ ColorChart deepCopy asFormOfDepth: Display depth.
	chartForm fill: ((TransparentBox left + 9)@0 extent: 1@9) fillColor: Color lightGray.
	chartForm fill: ((TransparentBox right - 10)@0 extent: 1@9) fillColor: Color lightGray.
	TransText displayOn: chartForm at: 62@0.
	Display depth = 32 ifTrue:
		["Set opaque bits for 32-bit display"
		chartForm fill: chartForm boundingBox rule: Form under
				fillColor: (Color r: 0.0 g: 0.0 b: 0.0 alpha: 1.0)].
	chartForm borderWidth: 1.
	self form: chartForm.
	selectedColor ifNotNil: [self updateAlpha: selectedColor alpha]

! !

!ColorPickerMorph methodsFor: 'initialization' stamp: 'jmv 5/7/2009 13:07'!
initializeModal: beModal 
	"Initialize the receiver.  If beModal is true, it will be a modal color picker, else not"

	isModal := beModal.
	self removeAllMorphs.
	isModal ifFalse: [
		self addMorph: (SimpleButtonMorph new
			borderWidth: 0;
			label: 'x' font: nil;
			color: Color transparent;
			actionSelector: #delete;
			target: self;
			position: self topLeft - (0 @ 1);
			extent: 10 @ 12;
			setCenteredBalloonText: 'dismiss color picker')].
	self addMorph: ((Morph newBounds: (DragBox translateBy: self topLeft))
				color: Color transparent;
				setCenteredBalloonText: 'put me somewhere').
	self 
		addMorph: ((Morph newBounds: (RevertBox translateBy: self topLeft))
				color: Color transparent;
				setCenteredBalloonText: 'restore original color').
	self 
		addMorph: ((Morph newBounds: (FeedbackBox translateBy: self topLeft))
				color: Color transparent;
				setCenteredBalloonText: 'shows selected color').
	self 
		addMorph: ((Morph newBounds: (TransparentBox translateBy: self topLeft))
				color: Color transparent;
				setCenteredBalloonText: 'adjust translucency').
	self buildChartForm.
	selectedColor ifNil: [selectedColor := Color white].
	sourceHand := nil.
	deleteOnMouseUp := false.
	updateContinuously := true! !

!ColorPickerMorph methodsFor: 'private' stamp: 'jmv 5/7/2009 13:08'!
updateTargetColor
	| nArgs |
	(target notNil and: [selector notNil]) 
		ifTrue: [
			nArgs := selector numArgs.
			nArgs = 1 ifTrue: [^target perform: selector with: selectedColor].
			nArgs = 2 
				ifTrue: 
					[^target 
						perform: selector
						with: selectedColor
						with: sourceHand].
			nArgs = 3 
				ifTrue: 
					[^target 
						perform: selector
						with: selectedColor
						with: argument
						with: sourceHand]]! !

!ColorPickerMorph methodsFor: 'private' stamp: 'jmv 5/7/2009 13:08'!
updateTargetColorWith: aColor 
	"Update the target so that it reflects aColor as the color choice"

	(target notNil and: [selector notNil]) 
		ifTrue: [
			^target perform: selector withArguments: (self argumentsWith: aColor)]! !


!StringHolder methodsFor: 'updating' stamp: 'jmv 5/12/2009 00:04'!
updateListsAndCodeIn: aWindow
	self canDiscardEdits ifFalse: [^ self].
	aWindow updatablePanes do: [:aPane | aPane verifyContents]! !


!CodeHolder methodsFor: 'controls' stamp: 'jmv 5/6/2009 09:17'!
contentsSymbolQuints
	"Answer a list of quintuplets representing information on the alternative views available in the code pane
		first element:	the contentsSymbol used
		second element:	the selector to call when this item is chosen.
		third element:	the selector to call to obtain the wording of the menu item.
		fourth element:	the wording to represent this view
		fifth element:	balloon help
	A hypen indicates a need for a seperator line in a menu of such choices"

	^ #(
(source				togglePlainSource 				showingPlainSourceString		'source'			'the textual source code as writen')
(documentation	toggleShowDocumentation	showingDocumentationString	'documentation'	'the first comment in the method')
-
(prettyPrint		togglePrettyPrint 				prettyPrintString				'prettyPrint'		'the method source presented in a standard text format')
(colorPrint			toggleColorPrint				colorPrintString				'colorPrint'			'the method source in a standard text format with colors to distinguish structural parts') 
-
(showDiffs			toggleRegularDiffing			showingRegularDiffsString		'showDiffs'			'the textual source diffed from its prior version')
(prettyDiffs		togglePrettyDiffing			showingPrettyDiffsString		'prettyDiffs'		'formatted textual source diffed from formatted form of prior version')
-
(decompile			toggleDecompile				showingDecompileString		'decompile'			'source code decompiled from byteCodes')
(byteCodes		toggleShowingByteCodes		showingByteCodesString		'byteCodes'		'the bytecodes that comprise the compiled method'))! !

!CodeHolder methodsFor: 'controls' stamp: 'jmv 5/12/2009 00:20'!
optionalButtonRow
	"Answer a row of control buttons"

	| row button aLabel buttons widths |
	buttons _ OrderedCollection new.
	widths _ OrderedCollection new.
	Preferences menuButtonInToolPane ifTrue: [
		buttons add: self menuButton.
		widths add: 4 ].
	self optionalButtonTuples do: [ :tuple | 
		widths add: tuple first.
		button _ PluggableButtonMorph 
					on: self
					getState: nil
					action: tuple third.
		button
			clipSubmorphs: true;
			onColor: Color transparent offColor: Color transparent.
		aLabel := Preferences abbreviatedBrowserButtons 
			ifTrue: [self abbreviatedWordingFor: tuple third]
			ifFalse: [nil].
		button label: (aLabel ifNil: [tuple second asString]).
		tuple size > 3 ifTrue: [button setBalloonText: tuple fourth].
		tuple size > 4 ifTrue: [button triggerOnMouseDown: tuple fifth].
		buttons add: button ].
	row _ AlignmentMorph proportional.
	row addInRow: buttons widthProportionalTo: widths inset: 2.
	^row! !

!CodeHolder methodsFor: 'controls' stamp: 'jmv 5/12/2009 00:20'!
optionalButtonTuples
	"Answer a tuple buttons, in the format:
			button label
			selector to send
			help message"

	| aList |

	aList _ #(
	(10	'browse'			browseMethodFull				'view this method in a browser')
	(11	'senders' 			browseSendersOfMessages	'browse senders of...')
	(16	'implementors'	browseMessages					'browse implementors of...')
	(11	'versions'			browseVersions				'browse versions')), 

	(Preferences decorateBrowserButtons
		ifTrue:
			[{#(13	'inheritance'		methodHierarchy 	'browse method inheritance
green: sends to super
tan: has override(s)
mauve: both of the above
pink: is an override but doesn''t call super
pinkish tan: has override(s), also is an override but doesn''t call super' )}]
		ifFalse:
			[{#(13	'inheritance'		methodHierarchy			'browse method inheritance')}]),

	#(
	(12	'hierarchy'			classHierarchy					'browse class hierarchy')
	(11	'inst vars'			browseInstVarRefs			'inst var refs...')
	(13	'class vars'			browseClassVarRefs			'class var refs...')
	(9	'show...'				offerWhatToShowMenu		'menu of what to show in lower pane')).

	^ aList! !

!CodeHolder methodsFor: 'controls' stamp: 'jmv 5/5/2009 14:41'!
sourceAndDiffsQuintsOnly
	"Answer a list of quintuplets representing information on the alternative views available in the code pane for the case where the only plausible choices are showing source or either of the two kinds of diffs"

	^ #(
(source			togglePlainSource 		showingPlainSourceString		'source'		'the textual source code as writen')
(showDiffs		toggleRegularDiffing	showingRegularDiffsString		'showDiffs'		'the textual source diffed from its prior version')
(prettyDiffs	togglePrettyDiffing	showingPrettyDiffsString		'prettyDiffs'	'formatted textual source diffed from formatted form of prior version'))! !

!CodeHolder methodsFor: 'diffs' stamp: 'jmv 5/7/2009 16:34'!
prettyDiffButton
	"Return a checkbox that lets the user decide whether prettyDiffs should be shown or not"

	|  outerButton button |
	outerButton _ AlignmentMorph proportional.
	outerButton color:  Color transparent.
	button _ UpdatingThreePhaseButtonMorph checkBox.
	button
		target: self;
		actionSelector: #togglePrettyDiffing;
		getSelector: #showingPrettyDiffs.
	outerButton 
		addMorph: button
			fullFrame: (LayoutFrame fractions: (0@0 corner: 0@1) offsets: (2@3 corner: 18@0));
		addMorph: (StringMorph contents: 'prettyDiffs') lock
			fullFrame: (LayoutFrame fractions: (0@0 corner: 1@1) offsets: (18@2 corner: 0@0)).
	(self isKindOf: VersionsBrowser)
		ifTrue:
			[outerButton setBalloonText: 'If checked, then pretty-printed code differences from the previous version, if any, will be shown.']
		ifFalse:
			[outerButton setBalloonText: 'If checked, then pretty-printed code differences between the file-based method and the in-memory version, if any, will be shown.'].

	^ outerButton
! !

!CodeHolder methodsFor: 'diffs' stamp: 'jmv 5/7/2009 16:34'!
regularDiffButton
	"Return a checkbox that lets the user decide whether regular diffs should be shown or not"

	|  outerButton button |
	outerButton _ AlignmentMorph proportional.
	outerButton color:  Color transparent.
	button _ UpdatingThreePhaseButtonMorph checkBox.
	button
		target: self;
		actionSelector: #toggleRegularDiffing;
		getSelector: #showingRegularDiffs.
	outerButton 
		addMorph: button
			fullFrame: (LayoutFrame fractions: (0@0 corner: 0@1) offsets: (2@3 corner: 18@0));
		addMorph: (StringMorph contents: 'diffs') lock
			fullFrame: (LayoutFrame fractions: (0@0 corner: 1@1) offsets: (18@2 corner: 0@0)).
	outerButton setBalloonText: 'If checked, then code differences from the previous version, if any, will be shown.'.

	^ outerButton
! !

!CodeHolder methodsFor: 'misc' stamp: 'jmv 5/5/2009 22:54'!
addLowerPanesTo: window at: nominalFractions with: editString

	| verticalOffset column innerFractions |
	column _ AlignmentMorph proportional.
	verticalOffset _ 0.
	innerFractions _ 0@0 corner: 1@0.
	verticalOffset _ self addOptionalAnnotationsTo: column at: innerFractions plus: verticalOffset.
	verticalOffset _ self addOptionalButtonsTo: column  at: innerFractions plus: verticalOffset.

	column 
		addMorph: ((self buildMorphicCodePaneWith: editString) borderWidth: 0)
		fullFrame: (
			LayoutFrame 
				fractions: (innerFractions withBottom: 1) 
				offsets: (0@verticalOffset corner: 0@0)
		).
	window 
		addMorph: column
		frame: nominalFractions.

	column on: #mouseEnter send: #paneTransition: to: window.
	column on: #mouseLeave send: #paneTransition: to: window.! !

!CodeHolder methodsFor: 'misc' stamp: 'jmv 5/5/2009 14:37'!
menuButton
	"Answer a button that brings up a menu.  Useful when adding new features, but at present is between uses"

	| aButton |
	aButton _ IconicButton new target: self;
		clipSubmorphs: true;
		borderWidth: 0;
		labelGraphic: (ScriptingSystem formAtKey: #TinyMenu);
		color: Color transparent; 
		actWhen: #buttonDown;
		actionSelector: #offerMenu;
		yourself.
	aButton setBalloonText: 'click here to get a menu with further options'.
	^ aButton
! !


!Browser methodsFor: 'initialize-release' stamp: 'jmv 5/5/2009 17:15'!
addClassAndSwitchesTo: window at: nominalFractions plus: verticalOffset

	| column |
	column _ self morphicClassColumn.	

	window addMorph: column
		fullFrame: (LayoutFrame fractions: nominalFractions
				offsets: (0 @ verticalOffset corner: 0 @ 0)).
	column 
		on: #mouseEnter
		send: #paneTransition:
		to: window.
	column 
		on: #mouseLeave
		send: #paneTransition:
		to: window! !

!Browser methodsFor: 'initialize-release' stamp: 'jmv 5/5/2009 22:55'!
buildMorphicSwitches
	| instanceSwitch commentSwitch classSwitch row aColor |
	instanceSwitch := PluggableButtonMorph 
				on: self
				getState: #instanceMessagesIndicated
				action: #indicateInstanceMessages.
	instanceSwitch
		label: 'instance';
		askBeforeChanging: true;
		borderWidth: 0.
	commentSwitch := PluggableButtonMorph 
				on: self
				getState: #classCommentIndicated
				action: #plusButtonHit.
	commentSwitch
		label: '?' asText allBold;
		askBeforeChanging: true;
		setBalloonText: 'class comment';
		borderWidth: 0.
	classSwitch := PluggableButtonMorph 
				on: self
				getState: #classMessagesIndicated
				action: #indicateClassMessages.
	classSwitch
		label: 'class';
		askBeforeChanging: true;
		borderWidth: 0.
	row _ AlignmentMorph proportional.
	row
		addInRow: {instanceSwitch. commentSwitch. classSwitch}
		atFractions: #(0.0 0.5 0.65 1.0)
		inset: 1@0.
	aColor := Color colorFrom: self class windowColor.
	row color: aColor duller.	"ensure matching button divider color. (see #paneColor)"
	Preferences alternativeWindowLook ifTrue: [aColor := aColor muchLighter].
	{ 
		instanceSwitch.
		commentSwitch.
		classSwitch} do: 
				[:m | 
				m
					color: aColor;
					onColor: aColor twiceDarker offColor: aColor;
					hResizing: #spaceFill;
					vResizing: #spaceFill].
	^row! !

!Browser methodsFor: 'initialize-release' stamp: 'jmv 5/5/2009 22:54'!
morphicClassColumn
	| column switchHeight divider |
	column _ AlignmentMorph proportional.
	switchHeight _ Preferences standardDefaultTextFont height + 4.
	column 
		addMorph: (self buildMorphicSwitches borderWidth: 0)
		fullFrame: (LayoutFrame fractions: (0 @ 1 corner: 1 @ 1)
				offsets: (0 @ (1 - switchHeight) corner: 0 @ 0)).
	divider _ BorderedSubpaneDividerMorph forTopEdge.
	Preferences alternativeWindowLook 
		ifTrue: [
			divider
				extent: 4 @ 4;
				color: Color transparent;
				borderColor: #raised;
				borderWidth: 2].
	column addMorph: divider
		fullFrame: (LayoutFrame fractions: (0 @ 1 corner: 1 @ 1)
				offsets: (0 @ switchHeight negated corner: 0 @ (1 - switchHeight))).
	column addMorph: self buildMorphicClassList 
		fullFrame: (LayoutFrame fractions: (0 @ 0 corner: 1 @ 1)
				offsets: (0 @ 0 corner: 0 @ switchHeight negated)).
	^column! !

!Browser methodsFor: 'initialize-release' stamp: 'jmv 5/12/2009 18:09'!
openAsMorphClassEditing: editString 
	"Create a pluggable version a Browser on just a single class."

	| window dragNDropFlag hSepFrac switchHeight mySingletonClassList switches c |
	window := SystemWindow new model: self.
	dragNDropFlag := false.
	hSepFrac := 0.3.
	switchHeight _ Preferences standardDefaultTextFont height + 10.
	mySingletonClassList := PluggableListMorph 
				on: self
				list: #classListSingleton
				selected: #indexIsOne
				changeSelected: #indexIsOne:
				menu: #classListMenu:shifted:
				keystroke: #classListKey:from:.
	mySingletonClassList enableDragNDrop: dragNDropFlag.
	self 
		addLowerPanesTo: window
		at: (0 @ hSepFrac corner: 1 @ 1)
		with: editString.
	window addMorph: mySingletonClassList
		fullFrame: (LayoutFrame fractions: (0 @ 0 corner: 0.5 @ 0)
				offsets: (0 @ 0 corner: 0 @ switchHeight)).
	switches _ self buildMorphicSwitches.
	c _ switches color.
	window addMorph: (switches borderWidth: 0)
		fullFrame: (LayoutFrame fractions: (0.5 @ 0 corner: 1.0 @ 0)
				offsets: (0 @ 0 corner: 0 @ switchHeight)).
	switches color: c.
	window addMorph: self buildMorphicMessageCatList
		fullFrame: (LayoutFrame fractions: (0 @ 0 corner: 0.5 @ hSepFrac)
				offsets: (0 @ switchHeight corner: 0 @ 0)).
	window addMorph: self buildMorphicMessageList
		fullFrame: (LayoutFrame fractions: (0.5 @ 0 corner: 1.0 @ hSepFrac)
				offsets: (0 @ switchHeight corner: 0 @ 0)).
	window setUpdatablePanesFrom: #(#messageCategoryList #messageList).
	^window! !

!Browser methodsFor: 'initialize-release' stamp: 'jmv 5/12/2009 18:09'!
openAsMorphEditing: editString
	"Create a pluggable version of all the morphs for a Browser in Morphic"
	| window hSepFrac |

	hSepFrac _ 0.4.
	window _ SystemWindow new model: self.
	
"The method SystemWindow>>addMorph:fullFrame: checks scrollBarsOnRight, then adds the morph at the back if true, otherwise it is added in front. But flopout hScrollbars need the lowerpanes to be behind the upper ones in the draw order. Hence the value of scrollBarsOnRight affects the order in which the lowerpanes are added. "
	Preferences scrollBarsOnRight ifFalse: [
		self 
			addLowerPanesTo: window 
			at: (0@hSepFrac corner: 1@1) 
			with: editString].
		
	window 
		addMorph: self buildMorphicSystemCatList
		frame: (0@0 corner: 0.25@hSepFrac).
	self 
		addClassAndSwitchesTo: window 
		at: (0.25@0 corner: 0.5@hSepFrac)
		plus: 0.
	window 
		addMorph: self buildMorphicMessageCatList
		frame: (0.5@0 extent: 0.25@hSepFrac).
	window addMorph: self buildMorphicMessageList
		frame: (0.75@0 extent: 0.25@hSepFrac).
		
	Preferences scrollBarsOnRight ifTrue: [
		self 
			addLowerPanesTo: window 
			at: (0@hSepFrac corner: 1@1) 
			with: editString].
		
	window setUpdatablePanesFrom: #(systemCategoryList classList messageCategoryList messageList).
	^ window! !

!Browser methodsFor: 'initialize-release' stamp: 'jmv 5/12/2009 18:09'!
openAsMorphMessageEditing: editString 
	"Create a pluggable version a Browser that shows just one message"

	| window mySingletonMessageList verticalOffset nominalFractions |
	window := SystemWindow new model: self.
	mySingletonMessageList := PluggableListMorph 
				on: self
				list: #messageListSingleton
				selected: #indexIsOne
				changeSelected: #indexIsOne:
				menu: #messageListMenu:shifted:
				keystroke: #messageListKey:from:.
	mySingletonMessageList enableDragNDrop: false.
	verticalOffset := 25.
	nominalFractions := 0 @ 0 corner: 1 @ 0.
	window addMorph: mySingletonMessageList
		fullFrame: (LayoutFrame fractions: nominalFractions
				offsets: (0 @ 0 corner: 0 @ verticalOffset)).
	verticalOffset := self 
				addOptionalAnnotationsTo: window
				at: nominalFractions
				plus: verticalOffset.
	verticalOffset := self 
				addOptionalButtonsTo: window
				at: nominalFractions
				plus: verticalOffset.
	window addMorph: (self buildMorphicCodePaneWith: editString)
		fullFrame: (LayoutFrame fractions: (0 @ 0 corner: 1 @ 1)
				offsets: (0 @ verticalOffset corner: 0 @ 0)).
	^window! !

!Browser methodsFor: 'initialize-release' stamp: 'jmv 5/12/2009 18:09'!
openAsMorphMsgCatEditing: editString 
	"Create a pluggable version a Browser on just a message category."

	| window hSepFrac |
	window := SystemWindow new model: self.
	hSepFrac := 0.3.
	window 
		addMorph: ((PluggableListMorph 
				on: self
				list: #messageCatListSingleton
				selected: #indexIsOne
				changeSelected: #indexIsOne:
				menu: #messageCategoryMenu:) 
					enableDragNDrop: false)
		fullFrame: (LayoutFrame fractions: (0 @ 0 corner: 1 @ 0)
				offsets: (0 @ 0 corner: 0 @ 25)).
	window addMorph: self buildMorphicMessageList
		fullFrame: (LayoutFrame fractions: (0 @ 0 corner: 1 @ hSepFrac)
				offsets: (0 @ 25 corner: 0 @ 0)).
	self 
		addLowerPanesTo: window
		at: (0 @ hSepFrac corner: 1 @ 1)
		with: editString.
	window setUpdatablePanesFrom: #(#messageCatListSingleton #messageList).
	^window! !

!Browser methodsFor: 'initialize-release' stamp: 'jmv 5/12/2009 18:09'!
openAsMorphSysCatEditing: editString 
	"Create a pluggable version of all the views for a Browser, including views and controllers."

	| window hSepFrac switchHeight mySingletonList nextOffsets |
	window := SystemWindow new model: self.
	hSepFrac := 0.3.
	switchHeight := Preferences standardCodeFont height + 4.
	mySingletonList := PluggableListMorph 
				on: self
				list: #systemCategorySingleton
				selected: #indexIsOne
				changeSelected: #indexIsOne:
				menu: #systemCatSingletonMenu:
				keystroke: #systemCatSingletonKey:from:.
	mySingletonList enableDragNDrop: false.
	mySingletonList hideScrollBarsIndefinitely.
	window addMorph: mySingletonList
		fullFrame: (LayoutFrame fractions: (0 @ 0 corner: 1 @ 0)
				offsets: (0 @ 0 corner: 0 @ switchHeight)).
	self 
		addClassAndSwitchesTo: window
		at: (0 @ 0 corner: 0.3333 @ hSepFrac)
		plus: switchHeight.
	nextOffsets := 0 @ switchHeight corner: 0 @ 0.
	window addMorph: self buildMorphicMessageCatList
		fullFrame: (LayoutFrame 
				fractions: (0.3333 @ 0 corner: 0.6666 @ hSepFrac)
				offsets: nextOffsets).
	window addMorph: self buildMorphicMessageList
		fullFrame: (LayoutFrame fractions: (0.6666 @ 0 corner: 1 @ hSepFrac)
				offsets: nextOffsets).
	self 
		addLowerPanesTo: window
		at: (0 @ hSepFrac corner: 1 @ 1)
		with: editString.
	window 
		setUpdatablePanesFrom: #(#classList #messageCategoryList #messageList).
	^window! !


!ChangeList methodsFor: 'initialization-release' stamp: 'jmv 5/5/2009 14:20'!
buttonSpecs

	^#(
		(11		'select all' 			selectAll			'select all entries')
		(14		'deselect all'		deselectAll			'deselect all entries')
		(18		'select conflicts'	selectAllConflicts	'select all methods that occur in any change set')
		(19		'file in selections' 	fileInSelections		'file in all selected entries')
	)! !

!ChangeList methodsFor: 'menu actions' stamp: 'jmv 5/5/2009 22:55'!
optionalButtonRow
	"Answer a row of buttons to occur in a tool pane"

	| row button buttons widths |
	buttons _ OrderedCollection new.
	widths _ OrderedCollection new.
	self buttonSpecs do: [ :tuple | 
		widths add: tuple first.
		button _ PluggableButtonMorph 
					on: self
					getState: nil
					action: tuple third.
		button
			clipSubmorphs: true;
			hResizing: #spaceFill;
			vResizing: #spaceFill;
			label: tuple second asString;
			askBeforeChanging: true;
			onColor: Color transparent offColor: Color transparent.
		buttons add: button.
		button setBalloonText: tuple fourth].
	buttons add: self regularDiffButton.
	widths add: 9.
	self wantsPrettyDiffOption ifTrue: [
		buttons add:  self prettyDiffButton.
		widths add: 16 ].
	row _ AlignmentMorph proportional.
	row addInRow: buttons widthProportionalTo: widths inset: 2.
	^row! !


!Debugger methodsFor: 'initialize' stamp: 'jmv 5/6/2009 12:15'!
buttonRowForPreDebugWindow: aDebugWindow
	| row aButton quads buttons |
	buttons _ OrderedCollection new.
	quads _ OrderedCollection withAll: self preDebugButtonQuads.
	(self interruptedContext selector == #doesNotUnderstand:) ifTrue: [
		quads add: { 'Create'. #createMethod. #magenta. 'create the missing method' }
	].
	quads do: [ :quad |
		aButton _ SimpleButtonMorph new target: aDebugWindow.
		aButton clipSubmorphs: true; color: Color transparent; borderWidth: 1.
		aButton actionSelector: quad second.
		aButton label: quad first.
		aButton color: (Color colorFrom: quad third) muchLighter.
		aButton setBalloonText: quad fourth.
		Preferences alternativeWindowLook
			ifTrue: [aButton borderWidth: 2; borderColor: #raised].
		buttons add: aButton].
	
	row _ AlignmentMorph proportional.
	row addInRow: buttons.
	^row! !

!Debugger methodsFor: 'initialize' stamp: 'jmv 5/5/2009 22:55'!
customButtonRow
	"Answer a button pane affording the user one-touch access to certain functions; the pane is given the formal name 'customButtonPane' by which it can be retrieved by code wishing to send messages to widgets residing on the pane"

	| aButton aLabel buttons row |
	buttons _ OrderedCollection new.
	self customButtonSpecs do: [ :tuple | 
		aButton := PluggableButtonMorph 
					on: self
					getState: nil
					action: tuple second.
		aButton
			clipSubmorphs: true;
			hResizing: #spaceFill;
			vResizing: #spaceFill;
			onColor: Color transparent offColor: Color transparent.
		(#(#proceed #restart #send #doStep #stepIntoBlock #fullStack #where) 
			includes: tuple second) ifTrue: [aButton askBeforeChanging: true].
		aLabel := Preferences abbreviatedBrowserButtons 
					ifTrue: [self abbreviatedWordingFor: tuple second]
					ifFalse: [nil].
		aButton label: (aLabel ifNil: [tuple first asString]).
		tuple size > 2 ifTrue: [aButton setBalloonText: tuple third].
		Preferences alternativeWindowLook ifTrue: [
			aButton
				borderWidth: 2;
				borderColor: #raised].
		buttons add: aButton].
		
	row _ AlignmentMorph proportional.
	row addInProportionalRow: buttons.
	^row! !

!Debugger methodsFor: 'initialize' stamp: 'jmv 5/5/2009 15:05'!
preDebugButtonQuads

	^ #(('Proceed'		proceed 	blue 	'continue execution' )
		('Abandon'		delete	 	black 	'abandon this execution by closing this window')
		('Debug'		debug 		red 	'bring up a debugger'))! !

!Debugger methodsFor: 'context stack menu' stamp: 'jmv 5/11/2009 23:44'!
buildMorphicNotifierLabelled: label message: messageString 
	| notifyPane window contentTop extentToUse |
	self expandStack.
	window := (PreDebugWindow labelled: label) model: self.
	contentTop := 0.2.
	extentToUse := 650 @ 320.	"nice and wide to show plenty of the error msg"
	window addMorph: (self buttonRowForPreDebugWindow: window)
		frame: (0 @ 0 corner: 1 @ contentTop).
	messageString notNil 
		ifFalse: [
			notifyPane := PluggableListMorph 
						on: self
						list: #contextStackList
						selected: #contextStackIndex
						changeSelected: #debugAt:
						menu: nil
						keystroke: nil]
		ifTrue: [
			notifyPane := PluggableTextMorph 
						on: self
						text: nil
						accept: nil
						readSelection: nil
						menu: #debugProceedMenu:.
			notifyPane
				editString: (self preDebugNotifierContentsFrom: messageString);
				askBeforeDiscardingEdits: false].
	window addMorph: notifyPane frame: (0 @ contentTop corner: 1 @ 1).
	^window openInWorldExtent: extentToUse! !

!Debugger methodsFor: 'controls' stamp: 'jmv 5/5/2009 14:50'!
addOptionalButtonsTo: window at: fractions plus: verticalOffset
	"Add button panes to the window.  A row of custom debugger-specific buttons (Proceed, Restart, etc.) is always added, and if optionalButtons is in force, then the standard code-tool buttons are also added.  Answer the verticalOffset plus the height added."

	| delta buttons divider anOffset |
	anOffset _ (Preferences optionalButtons and: [Preferences extraDebuggerButtons | true])
		ifTrue:
			[super addOptionalButtonsTo: window at: fractions plus: verticalOffset]
		ifFalse:
			[verticalOffset].

	delta _ self defaultButtonPaneHeight.
	buttons _ self customButtonRow.
	buttons color: (Display depth <= 8 ifTrue: [Color transparent] ifFalse: [Color gray alpha: 0.2]);
		borderWidth: 0.
	Preferences alternativeWindowLook ifTrue:
		[buttons color: Color transparent.
		buttons submorphsDo:[:m | m borderWidth: 2; borderColor: #raised]].
	divider _ BorderedSubpaneDividerMorph forBottomEdge.
	Preferences alternativeWindowLook ifTrue:
		[divider extent: 4@4; color: Color transparent; borderColor: #raised; borderWidth: 2].
	window 
		addMorph: buttons
		fullFrame: (LayoutFrame 
				fractions: fractions 
				offsets: (0@anOffset corner: 0@(anOffset + delta - 1))).
	window 
		addMorph: divider
		fullFrame: (LayoutFrame 
				fractions: fractions 
				offsets: (0@(anOffset + delta - 1) corner: 0@(anOffset + delta))).
	^ anOffset + delta! !


!FileContentsBrowser methodsFor: 'creation' stamp: 'jmv 5/5/2009 22:54'!
addLowerPanesTo: window at: nominalFractions with: editString

	| verticalOffset column codePane infoPane infoHeight divider |


	column _ AlignmentMorph proportional.

	codePane _ PluggableTextMorph on: self text: #contents accept: #contents:notifying:
			readSelection: #contentsSelection menu: #codePaneMenu:shifted:.
	infoPane _ PluggableTextMorph on: self text: #infoViewContents accept: nil
			readSelection: nil menu: nil.
	infoPane askBeforeDiscardingEdits: false.
	verticalOffset _ 0.

">>not with this browser--- at least not yet ---
	innerFractions _ 0@0 corner: 1@0.
	verticalOffset _ self addOptionalAnnotationsTo: row at: innerFractions plus: verticalOffset.
	verticalOffset _ self addOptionalButtonsTo: row  at: innerFractions plus: verticalOffset.
<<<<"

	infoHeight _ 20.
	column 
		addMorph: (codePane borderWidth: 0)
		fullFrame: (
			LayoutFrame 
				fractions: (0@0 corner: 1@1) 
				offsets: (0@verticalOffset corner: 0@infoHeight negated)
		).
	divider _ BorderedSubpaneDividerMorph forTopEdge.
	Preferences alternativeWindowLook ifTrue:[
		divider extent: 4@4; color: Color transparent; borderColor: #raised; borderWidth: 2.
	].
	column 
		addMorph: divider
		fullFrame: (
			LayoutFrame 
				fractions: (0@1 corner: 1@1) 
				offsets: (0@infoHeight negated corner: 0@(1-infoHeight))
		).
	column 
		addMorph: (infoPane borderWidth: 0; hideScrollBarsIndefinitely)
		fullFrame: (
			LayoutFrame 
				fractions: (0@1 corner: 1@1) 
				offsets: (0@(1-infoHeight) corner: 0@0)
		).
	window 
		addMorph: column
		frame: nominalFractions.

	column on: #mouseEnter send: #paneTransition: to: window.
	column on: #mouseLeave send: #paneTransition: to: window.

! !

!FileContentsBrowser methodsFor: 'creation' stamp: 'jmv 5/12/2009 18:10'!
openAsMorph
	"Create a pluggable version of all the views for a Browser, including views and controllers."
	| window aListExtent next mySingletonList |
	window _ SystemWindow new model: self.
	self packages size = 1
		ifTrue: [
			aListExtent _ 0.333333 @ 0.34.
			self systemCategoryListIndex: 1.
			mySingletonList _ PluggableListMorph on: self list: #systemCategorySingleton
					selected: #indexIsOne changeSelected: #indexIsOne:
					menu: #packageListMenu:
					keystroke: #packageListKey:from:.
			mySingletonList hideScrollBarsIndefinitely.
			window addMorph: mySingletonList frame: (0@0 extent: 1.0@0.06).
			next := 0@0.06]
		ifFalse: [
			aListExtent _ 0.25 @ 0.4.
			window addMorph: (PluggableListMorph on: self list: #systemCategoryList
					selected: #systemCategoryListIndex changeSelected: #systemCategoryListIndex:
					menu: #packageListMenu:
					keystroke: #packageListKey:from:)
				frame: (0@0 extent: aListExtent).
			next := aListExtent x @ 0].

	self addClassAndSwitchesTo: window at: (next extent: aListExtent) plus: 0.

	next := next + (aListExtent x @ 0).
	window addMorph: (PluggableListMorph on: self list: #messageCategoryList
			selected: #messageCategoryListIndex changeSelected: #messageCategoryListIndex:
			menu: #messageCategoryMenu:)
		frame: (next extent: aListExtent).
	next := next + (aListExtent x @ 0).
	window addMorph: (PluggableListMorph on: self list: #messageList
			selected: #messageListIndex changeSelected: #messageListIndex:
			menu: #messageListMenu:
			keystroke: #messageListKey:from:)
		frame: (next extent: aListExtent).

	self addLowerPanesTo: window at: (0@0.4 corner: 1@1) with: nil.
	^ window
! !


!FileList methodsFor: 'initialization' stamp: 'jmv 5/13/2009 17:39'!
labelString
	^ directory pathName "contractTo: 50"! !

!FileList methodsFor: 'initialization' stamp: 'jmv 5/5/2009 22:55'!
optionalButtonRow
	"Answer the button row associated with a file list"

	| row |
	row _ AlignmentMorph proportional.
	row setProperty: #buttonRow toValue: true.  "Used for dynamic retrieval later on"
	self updateButtonRow: row.
	^row! !

!FileList methodsFor: 'initialization' stamp: 'jmv 5/5/2009 17:42'!
updateButtonRow
	"Dynamically update the contents of the button row, if any."

	| window row |
	window _ self dependents 
				detect: [:m | (m isSystemWindow) and: [m model == self]]
				ifNone: [^self].
	row _ window 
		findDeepSubmorphThat: [:m | m hasProperty: #buttonRow]
		ifAbsent: [^self].
		
	self updateButtonRow: row! !

!FileList methodsFor: 'initialization' stamp: 'jmv 5/5/2009 17:42'!
updateButtonRow: row
	"Dynamically update the contents of the button row, if any."

	| buttons |
	row removeAllMorphs.
	buttons _ OrderedCollection new.
	self universalButtonServices do: [ :service |
		buttons add: (service buttonToTriggerIn: self) ].
	self dynamicButtonServices do: [ :service | 
		buttons add: (service buttonToTriggerIn: self).
		service addDependent: self].
	row addInRow: buttons.! !

!FileList methodsFor: 'to be transformed in registration' stamp: 'jmv 5/5/2009 16:38'!
perform: selector orSendTo: otherTarget 
	"Selector was just chosen from a menu by a user.
	If it's one of the three sort-by items, handle it specially.
	If I can respond myself, then perform it on myself. 
	If not, send it to otherTarget, presumably the editPane from which the menu was invoked."

	^ (#(sortByDate sortBySize sortByName) includes: selector)
		ifTrue:
			[self resort: selector]
		ifFalse:
			[(#(get getHex copyName renameFile deleteFile addNewFile) includes: selector)
				ifTrue: [self perform: selector]
				ifFalse: [super perform: selector orSendTo: otherTarget]]! !


!FileList class methodsFor: 'instance creation' stamp: 'jmv 5/5/2009 22:54'!
addButtonsAndFileListPanesTo: window at: upperFraction plus: offset forFileList: aFileList 
	| fileListMorph column buttonHeight fileListTop divider dividerDelta buttons |
	fileListMorph _ PluggableListMorph
				on: aFileList
				list: #fileList
				selected: #fileListIndex
				changeSelected: #fileListIndex:
				menu: #fileListMenu:.
	fileListMorph enableDrag: true; enableDrop: false.
	aFileList wantsOptionalButtons
		ifTrue: [buttons _ aFileList optionalButtonRow.
			divider _ BorderedSubpaneDividerMorph forBottomEdge.
			dividerDelta _ 0.
			Preferences alternativeWindowLook
				ifTrue: [
					buttons color: Color transparent.
					buttons
						submorphsDo: [:m | m borderWidth: 2;
								 borderColor: #raised].
						divider extent: 4 @ 4;
						 color: Color transparent;
						 borderColor: #raised;
						 borderWidth: 2.
					fileListMorph borderColor: Color transparent.
					dividerDelta _ 3].
			column _ AlignmentMorph proportional.
			buttonHeight _ self defaultButtonPaneHeight.
			column
				addMorph: buttons
				fullFrame: (LayoutFrame
						fractions: (0 @ 0 corner: 1 @ 0)
						offsets: (0 @ 0 corner: 0 @ buttonHeight)).
			column
				addMorph: divider
				fullFrame: (LayoutFrame
						fractions: (0 @ 0 corner: 1 @ 0)
						offsets: (0 @ buttonHeight corner: 0 @ buttonHeight + dividerDelta)).
			column
				addMorph: fileListMorph
				fullFrame: (LayoutFrame
						fractions: (0 @ 0 corner: 1 @ 1)
						offsets: (0 @ buttonHeight + dividerDelta corner: 0 @ 0)).
			window
				addMorph: column
				fullFrame: (LayoutFrame
						fractions: upperFraction
						offsets: (0 @ offset corner: 0 @ 0)).
			Preferences alternativeWindowLook
				ifTrue: [column borderWidth: 2]
				ifFalse: [column borderWidth: 0]]
		ifFalse: [
			fileListTop _ 0.
			window
				addMorph: fileListMorph
				frame: (0.3 @ fileListTop corner: 1 @ 0.3)].! !

!FileList class methodsFor: 'instance creation' stamp: 'jmv 5/5/2009 22:55'!
addVolumesAndPatternPanesTo: window at: upperFraction plus: offset forFileList: aFileList 
	| column patternHeight volumeListMorph patternMorph divider dividerDelta |
	column _ AlignmentMorph proportional.
	patternHeight _ 25.
	volumeListMorph _ (PluggableListMorph
				on: aFileList
				list: #volumeList
				selected: #volumeListIndex
				changeSelected: #volumeListIndex:
				menu: #volumeMenu:)
				autoDeselect: false.
	volumeListMorph enableDrag: false; enableDrop: true.
	patternMorph _ PluggableTextMorph
				on: aFileList
				text: #pattern
				accept: #pattern:.
	patternMorph acceptOnCR: true.
	patternMorph hideScrollBarsIndefinitely.
	divider _ BorderedSubpaneDividerMorph horizontal.
	dividerDelta _ 0.
	Preferences alternativeWindowLook
		ifTrue: [
			divider
				extent: 4 @ 4;
				color: Color transparent;
				borderColor: #raised;
				borderWidth: 2.
			volumeListMorph borderColor: Color transparent.
			patternMorph borderColor: Color transparent.
			dividerDelta _ 3].
	column
		addMorph: (volumeListMorph autoDeselect: false)
		fullFrame: (LayoutFrame
				fractions: (0 @ 0 corner: 1 @ 1)
				offsets: (0 @ 0 corner: 0 @ patternHeight negated - dividerDelta)).
	column
		addMorph: divider
		fullFrame: (LayoutFrame
				fractions: (0 @ 1 corner: 1 @ 1)
				offsets: (0 @ patternHeight negated - dividerDelta corner: 0 @ patternHeight negated)).
	column
		addMorph: patternMorph
		fullFrame: (LayoutFrame
				fractions: (0 @ 1 corner: 1 @ 1)
				offsets: (0 @ patternHeight negated corner: 0 @ 0)).
	window
		addMorph: column
		fullFrame: (LayoutFrame
				fractions: upperFraction
				offsets: (0 @ offset corner: 0 @ 0)).
	Preferences alternativeWindowLook
		ifTrue: [column borderWidth: 2] ifFalse: [column borderWidth: 0]! !


!FileList2 methodsFor: 'initialization' stamp: 'jmv 5/13/2009 17:39'!
labelString
	^ (directory ifNil: [^'[]']) pathName "contractTo: 50"! !


!FileList2 class methodsFor: 'morphic ui' stamp: 'jmv 5/5/2009 22:45'!
morphicViewFileSelectorForSuffixes: aList 
	"Answer a morphic file-selector tool for the given suffix list"

	| dir aFileList window fixedSize midLine gap |
	dir := FileDirectory default.
	aFileList := self new directory: dir.
	aFileList optionalButtonSpecs: aFileList okayAndCancelServices.
	aList ifNotNil: 
			[aFileList 
				fileSelectionBlock: 
					[:entry :myPattern | 
					entry isDirectory 
						ifTrue: [false]
						ifFalse: 
							[aList includes: (FileDirectory extensionFor: entry name asLowercase)]] 
							fixTemps].
	window := AlignmentMorph proportional
				color: Color lightBlue;
				borderColor: Color blue;
				borderWidth: 4;
				layoutInset: 4;
				extent: 600 @ 400.
	window setProperty: #fileListModel toValue: aFileList.
	aFileList modalView: window.
	midLine := 0.4.
	fixedSize := 25.
	gap := 5.
	self addFullPanesTo: window
		from: {
				{ 
					self textRow: 'Please select a file' translated.
					0 @ 0 corner: 1 @ 0.
					0 @ 4 corner: 0 @ fixedSize}.
				{ 
					aFileList optionalButtonRow.
					0 @ 0 corner: 1 @ 0.
					0 @ fixedSize corner: 0 @ (fixedSize * 2)}.
				{ 
					aFileList morphicDirectoryTreePane.
					0 @ 0 corner: midLine @ 1.
					gap @ (fixedSize * 2) corner: gap negated @ 0}.
				{ 
					aFileList morphicFileListPane.
					midLine @ 0 corner: 1 @ 1.
					gap @ (fixedSize * 2) corner: gap negated @ 0}}.
	aFileList postOpen.
	^window! !

!FileList2 class methodsFor: 'morphic ui' stamp: 'jmv 5/5/2009 18:14'!
morphicViewFolderSelector: aDir
	"Answer a tool that allows the user to select a folder"

	| aFileList window fixedSize |
	aFileList _ self new directory: aDir.
	aFileList optionalButtonSpecs: aFileList servicesForFolderSelector.
	window _ (SystemWindow labelled: aDir pathName) model: aFileList.
	aFileList modalView: window.

	fixedSize _ 25.
	self addFullPanesTo: window from: {
		{self textRow: 'Please select a folder'. 0 @ 0 corner: 1 @ 0. 
				0@0 corner: 0@fixedSize}.
		{aFileList optionalButtonRow. 0 @ 0 corner: 1 @ 0. 
				0@fixedSize corner: 0@(fixedSize * 5 // 2)}.
		{aFileList morphicDirectoryTreePane. 0@0 corner: 1@1.
				0@(fixedSize * 5 // 2) corner: 0@0}.
	}.
	aFileList postOpen.
	^ window ! !

!FileList2 class methodsFor: 'morphic ui' stamp: 'jmv 5/5/2009 15:51'!
morphicViewNoFile

	| dir aFileList window midLine fixedSize |

	dir _ FileDirectory default.
	aFileList _ self new directory: dir.
	window _ (SystemWindow labelled: dir pathName) model: aFileList.

	fixedSize _ 30.
	midLine _ 0.4.
	self addFullPanesTo: window from: {
		{aFileList morphicPatternPane. 0@0 corner: 0.3@0. 0@0 corner: 0@fixedSize}.
		{aFileList optionalButtonRow. 0.3 @ 0 corner: 1@0. 0@0 corner: 0@fixedSize}.
		{aFileList morphicDirectoryTreePane. 0@0 corner: midLine@1. 0@fixedSize corner: 0@0}.
		{aFileList morphicFileListPane. midLine @ 0 corner: 1@1. 0@fixedSize corner: 0@0}.
	}.
	aFileList postOpen.
	^ window ! !

!FileList2 class methodsFor: 'utility' stamp: 'jmv 5/5/2009 22:55'!
textRow: aString 

	^AlignmentMorph proportional
		addMorph:
			((TextMorph new contents: aString)
				color: Color blue; 
				lock; 
				autoFitOnOff; 
				wrapFlag: true; 
				centered)
		fullFrame: (LayoutFrame fractions: (0 @ 0 corner: 1 @ 1)
				offsets: (0 @ 3 corner: 0 @ 0))! !

!FileList2 class methodsFor: '*smloader-extension' stamp: 'jmv 5/5/2009 16:01'!
morphicViewOnDirectory: aFileDirectory
	| aFileList window fileListBottom midLine fileListTopOffset |

	aFileList _ self new directory: aFileDirectory.
	window _ (SystemWindow labelled: aFileDirectory pathName) model: aFileList.

	fileListTopOffset _ (TextStyle defaultFont pointSize * 2) + 14.
	fileListBottom _ 0.4.
	midLine _ 0.4.
	
	self addFullPanesTo: window from: {
		{aFileList morphicPatternPane. 			0@0 corner: 0.3@0. 						0@0 corner: 0@fileListTopOffset}.
		{aFileList optionalButtonRow. 				0.3 @ 0 corner: 1@0. 						0@0 corner: 0@fileListTopOffset}.
		{aFileList morphicDirectoryTreePane. 	0@0 corner: midLine@fileListBottom. 		0@fileListTopOffset corner: 0@0}.
		{aFileList morphicFileListPane. 			midLine @ 0 corner: 1@fileListBottom. 	0@fileListTopOffset corner: 0@0}.
		{aFileList morphicFileContentsPane. 		0@fileListBottom corner: 1@1. 			nil}.
	}.
	"
	self addFullPanesTo: window from: {
		{aFileList morphicPatternPane. 0@0 corner: 0.3@0. 0@0 corner: 0@fixedSize}.
		{aFileList optionalButtonRow. 0.3 @ 0 corner: 1@0. 0@0 corner: 0@fixedSize}.
		{aFileList morphicDirectoryTreePane. 0@0 corner: midLine@1. 0@fixedSize corner: 0@0}.
		{aFileList morphicFileListPane. midLine @ 0 corner: 1@1. 0@fixedSize corner: 0@0}.
	}.
	"
	aFileList postOpen.
	^ window ! !


!MessageNames methodsFor: 'initialization' stamp: 'jmv 5/7/2009 15:33'!
inMorphicWindowWithInitialSearchString: initialString
	"Answer a morphic window with the given initial search string, nil if none"

"MessageNames openMessageNames"

	| window selectorListView firstDivider secondDivider horizDivider typeInPane searchButton plugTextMor |
	window _ (SystemWindow labelled: 'Message Names') model: self.
	firstDivider _ 0.07.
	secondDivider _ 0.5.
	horizDivider _ 0.5.
	typeInPane _ AlignmentMorph proportional height: 14.

	plugTextMor _ PluggableTextMorph on: self
					text: #searchString accept: #searchString:notifying:
					readSelection: nil menu: nil.
	plugTextMor setProperty: #alwaysAccept toValue: true.
	plugTextMor askBeforeDiscardingEdits: false.
	plugTextMor acceptOnCR: true.
	plugTextMor setTextColor: Color brown.
	plugTextMor setNameTo: 'Search'.
	plugTextMor vResizing: #spaceFill; hResizing: #spaceFill.
	plugTextMor hideScrollBarsIndefinitely.
	plugTextMor setTextMorphToSelectAllOnMouseEnter.

	searchButton _ SimpleButtonMorph new 
		target: self;
		beTransparent;
		label: 'Search';
		actionSelector: #doSearchFrom:;
		arguments: {plugTextMor}.
	searchButton setBalloonText: 'Type some letters into the pane at right, and then press this Search button (or hit RETURN) and all method selectors that match what you typed will appear in the list pane below.  Click on any one of them, and all the implementors of that selector will be shown in the right-hand pane, and you can view and edit their code without leaving this tool.'.

	typeInPane addInProportionalRow: { searchButton. plugTextMor. }.
	initialString isEmptyOrNil ifFalse:
		[plugTextMor setText: initialString].

	window addMorph: typeInPane frame: (0@0 corner: horizDivider @ firstDivider).

	selectorListView _ PluggableListMorph on: self
		list: #selectorList
		selected: #selectorListIndex
		changeSelected: #selectorListIndex:
		menu: #selectorListMenu:
		keystroke: #selectorListKey:from:.
	selectorListView menuTitleSelector: #selectorListMenuTitle.
	window addMorph: selectorListView frame: (0 @ firstDivider corner: horizDivider @ secondDivider).

	window addMorph: self buildMorphicMessageList frame: (horizDivider @ 0 corner: 1@ secondDivider).

	self 
		addLowerPanesTo: window 
		at: (0 @ secondDivider corner: 1@1) 
		with: nil.

	initialString isEmptyOrNil ifFalse:
		[self searchString: initialString notifying: nil].
	^ window! !


!PackagePaneBrowser methodsFor: 'initialize-release' stamp: 'jmv 5/12/2009 18:11'!
openAsMorphEditing: editString 
	"Create a pluggable version of all the views for a Browser, including 
	views and controllers."
	"PackagePaneBrowser openBrowser"

	| listHeight window |
	listHeight _ 0.4.
	window _ SystemWindow new model: self.

"The method SystemWindow>>addMorph:fullFrame: checks scrollBarsOnRight, then adds the morph at the back if true, otherwise it is added in front. But flopout hScrollbars need the lowerpanes to be behind the upper ones in the draw order. Hence the value of scrollBarsOnRight affects the order in which the lowerpanes are added. "
	Preferences scrollBarsOnRight ifFalse: [
		self 
			addLowerPanesTo: window 
			at: (0@listHeight corner: 1@1) 
			with: editString].

	window
		addMorph: (PluggableListMorph
				on: self
				list: #packageList
				selected: #packageListIndex
				changeSelected: #packageListIndex:
				menu: #packageMenu:
				keystroke: #packageListKey:from:)
		frame: (0 @ 0 extent: 0.15 @ listHeight).
	window
		addMorph: self buildMorphicSystemCatList
		frame: (0.15 @ 0 extent: 0.2 @ listHeight).
	self
		addClassAndSwitchesTo: window
		at: (0.35 @ 0 extent: 0.25 @ listHeight)
		plus: 0.
	window
		addMorph: self buildMorphicMessageCatList
		frame: (0.6 @ 0 extent: 0.15 @ listHeight).
	window
		addMorph: self buildMorphicMessageList
		frame: (0.75 @ 0 extent: 0.25 @ listHeight).
		
	Preferences scrollBarsOnRight ifTrue: [
		self
			addLowerPanesTo: window
			at: (0 @ listHeight corner: 1 @ 1)
			with: editString ].
	window setUpdatablePanesFrom: #(#packageList #systemCategoryList #classList #messageCategoryList #messageList ).
	^ window! !


!SelectorBrowser methodsFor: 'as yet unclassified' stamp: 'jmv 5/13/2009 15:34'!
morphicWindow
	"Create a Browser that lets you type part of a selector, shows a list of selectors, shows the classes of the one you chose, and spawns a full browser on it.  Answer the window
	SelectorBrowser new open "

	| window typeInView selectorListView classListView |
	window := SystemWindow new model: self.
	selectorIndex := classListIndex := 0.
	typeInView := PluggableTextMorph 
				on: self
				text: #contents
				accept: #contents:notifying:
				readSelection: #contentsSelection
				menu: #codePaneMenu:shifted:.
	typeInView acceptOnCR: true.
	typeInView hideScrollBarsIndefinitely.
	window addMorph: typeInView frame: (0 @ 0 corner: 0.5 @ 0.14).
	selectorListView := PluggableListMorph 
				on: self
				list: #messageList
				selected: #messageListIndex
				changeSelected: #messageListIndex:
				menu: #selectorMenu:
				keystroke: #messageListKey:from:.
	selectorListView menuTitleSelector: #selectorMenuTitle.
	window addMorph: selectorListView frame: (0 @ 0.14 corner: 0.5 @ 0.6).
	classListView := PluggableListMorph 
				on: self
				list: #classList
				selected: #classListIndex
				changeSelected: #classListIndex:
				menu: nil
				keystroke: #arrowKey:from:.
	classListView menuTitleSelector: #classListSelectorTitle.
	window addMorph: classListView frame: (0.5 @ 0 corner: 1 @ 0.6).
	window 
		addMorph: ((PluggableTextMorph 
				on: self
				text: #byExample
				accept: #byExample:
				readSelection: #contentsSelection
				menu: #codePaneMenu:shifted:) askBeforeDiscardingEdits: false)
		frame: (0 @ 0.6 corner: 1 @ 1).
	window setLabel: 'Method Finder'.
	^window! !


!SelectorBrowser class methodsFor: 'window color' stamp: 'jmv 5/22/2006 20:12'!
windowColor
	^Color lightCyan! !


!MenuItemMorph methodsFor: 'drawing' stamp: 'jmv 5/14/2009 16:27'!
drawOn: aCanvas 
	| stringColor stringBounds leftEdge |

	stringColor := color.
	isSelected & isEnabled
		ifTrue: [
			aCanvas fillRectangle: self bounds color: (
				Display depth < 8
					ifTrue: [ Color veryLightGray ]
					ifFalse: [ Color lightBlue ])].
	leftEdge := 0.
	self hasIcon
		ifTrue: [| iconForm | 
			iconForm := isEnabled ifTrue:[self icon] ifFalse:[self icon asGrayScale].
			aCanvas paintImage: iconForm at: self left @ (self top + (self height - iconForm height // 2)).
			leftEdge := iconForm width + 2].

	self hasMarker
		ifTrue: [ leftEdge := leftEdge + self submorphBounds width + 8 ].

	stringBounds := bounds left: bounds left + leftEdge.

	aCanvas
		drawString: contents
		in: stringBounds
		font: self fontToUse
		color: stringColor.
	subMenu
		ifNotNil: [aCanvas paintImage: SubMenuMarker at: self right - 8 @ (self top + self bottom - SubMenuMarker height // 2)]! !

!MenuItemMorph methodsFor: 'events' stamp: 'jmv 5/14/2009 16:13'!
deselectTimeOut: evt
	"Deselect timout. Now really deselect"
	self flag: #jmvRemove. "?"
	owner selectedItem == self ifTrue:[owner selectItem: nil event: evt].! !

!MenuItemMorph methodsFor: 'events' stamp: 'jmv 5/6/2009 21:26'!
invokeWithEvent: evt
	"Perform the action associated with the given menu item."

	| selArgCount w |
	self isEnabled ifFalse: [^ self].
	owner ifNotNil:[self isStayUpItem ifFalse:[
		self flag: #workAround. "The tile system invokes menus straightforwardly so the menu might not be in the world."
		(w _ self world) ifNotNil:[
			owner deleteIfPopUp: evt.
			"Repair damage before invoking the action for better feedback"
			w displayWorldSafely]]].
	selector ifNil:[^self].
	Cursor normal showWhile: [  "show cursor in case item opens a new MVC window"
		(selArgCount _ selector numArgs) = 0
			ifTrue:
				[target perform: selector]
			ifFalse:
				[selArgCount = arguments size
					ifTrue: [target perform: selector withArguments: arguments]
					ifFalse: [target perform: selector withArguments: (arguments copyWith: evt)]]].! !

!MenuItemMorph methodsFor: 'grabbing' stamp: 'jmv 5/6/2009 21:26'!
aboutToBeGrabbedBy: aHand
	"Don't allow the receiver to act outside a Menu"
	| menu box |
	(owner notNil and:[owner submorphs size = 1]) ifTrue:[
		"I am a lonely menuitem already; just grab my owner"
		owner stayUp: true.
		^owner aboutToBeGrabbedBy: aHand].
	box _ self bounds.
	menu _ MenuMorph new defaultTarget: nil.
	menu addMorphFront: self.
	menu bounds: box.
	menu stayUp: true.
	self isSelected: false.
	^menu! !

!MenuItemMorph methodsFor: 'initialization' stamp: 'jmv 5/10/2009 10:23'!
initialize
	"initialize the state of the receiver"
	super initialize.
	""
	
	contents _ ''.
	isEnabled _ true.
	subMenu _ nil.
	isSelected _ false.
	target _ nil.
	selector _ nil.
	arguments _ nil.
	font _ Preferences standardMenuFont! !

!MenuItemMorph methodsFor: 'layout' stamp: 'jmv 5/14/2009 15:44'!
minItemWidth
	| fontToUse iconWidth subMenuWidth markerWidth |
	fontToUse := self fontToUse.
	subMenuWidth := self hasSubMenu
				ifFalse: [0]
				ifTrue: [10].
	iconWidth := self hasIcon
				ifTrue: [self icon width + 2]
				ifFalse: [0].
	markerWidth := self hasMarker
		ifTrue: [ self submorphBounds width + 8 ]
		ifFalse: [ 0 ].
	^ (fontToUse widthOfString: contents)
		+ subMenuWidth + iconWidth + markerWidth.! !

!MenuItemMorph methodsFor: 'layout-properties' stamp: 'jmv 5/14/2009 15:11'!
hResizing
	"Default to #spaceFill"
	self flag: #jmvRemove.
	^hResizing ifNil:[#spaceFill]! !


!SystemWindow methodsFor: 'drawing' stamp: 'jmv 5/14/2009 16:24'!
drawOn: aCanvas
	| titleColor r |
	super drawOn: aCanvas.
	"ATENCION paneColor es una fea property... ponerla como ivar!!"
	self flag: #jmvRemove.
	titleColor _ self isTopWindow
		ifTrue: [ self paneColorToUse paler ]
		ifFalse: [ self paneColorToUse ].
	r _ self labelRect.
	aCanvas
		frameAndFillRectangle: r
		fillColor: titleColor
		borderWidth: borderWidth
		borderColor: titleColor.
		
	self flag: #jmvRemove.
	r _ self labelRect2.
	"DarkGray is just a trick to turn off SubPixelRendering. Something better is needed!!"
	aCanvas drawString: labelString in: r font: Preferences windowTitleFont color: 
		"Color veryVeryDarkGray"
		(Color r: 0 g: 0 b: 1/256.0)! !

!SystemWindow methodsFor: 'events' stamp: 'JW 2/2/2001 12:26'!
secondaryPaneTransition: event divider: aMorph
	"Mouse has entered or left a pane"
	^ self spawnOffsetReframeHandle: event divider: aMorph! !

!SystemWindow methodsFor: 'geometry' stamp: 'jmv 5/12/2009 17:34'!
extent: aPoint 
	"Set the receiver's extent to value provided. Respect my minimumExtent."

	| newExtent |
	newExtent _ self isCollapsed
		ifTrue: [aPoint]
		ifFalse: [aPoint max: self minimumExtent].
	newExtent = self extent ifTrue: [^ self].

	isCollapsed
		ifTrue: [super extent: newExtent x @ (self labelHeight + 2)]
		ifFalse: [super extent: newExtent].
	isCollapsed
		ifTrue: [collapsedFrame _ self bounds]
		ifFalse: [fullFrame _ self bounds]! !

!SystemWindow methodsFor: 'geometry' stamp: 'jmv 5/12/2009 17:54'!
labelRect
	"Actually the whole label area"

	self flag: #jmvRemove.
	^ self innerBounds withHeight: self labelHeight.
! !

!SystemWindow methodsFor: 'geometry' stamp: 'jmv 5/12/2009 17:59'!
labelRect2
	"Actually the whole label area"

	| tl br e x0 y0 x1 y1 |
	self flag: #jmvRemove.
	tl _ bounds topLeft.
	br _ bounds bottomRight.
	e _ self boxExtent.
	x0 _ tl x + ( e x * 4 + 14).
	y0 _ tl y + 2.
	x1 _ br x - 1.
	y1 _ tl y + e y + 1.
	^x0@y0 corner: x1@y1
	
	
	
! !

!SystemWindow methodsFor: 'initialization' stamp: 'jmv 5/13/2009 15:59'!
boxExtent
	"answer the extent to use in all the buttons. 
	 
	the label height is used to be proportional to the fonts preferences"
	| e |
	e _ 18 max: Preferences windowTitleFont height.
	^e@e! !

!SystemWindow methodsFor: 'initialization' stamp: 'jmv 5/13/2009 15:58'!
createBox
	"create a button with default to be used in the label area"

	| box |
	box := IconicButton new.
	box
		color: Color transparent;
		target: self;
		borderWidth: 1.
	
	Preferences alternativeWindowLook
		ifTrue: [ box borderColor: #raised ].
		
	^box! !

!SystemWindow methodsFor: 'initialization' stamp: 'jmv 5/11/2009 23:45'!
initialize
	"Initialize a system window. Add label, stripes, etc., if desired"
	super initialize.
	labelString ifNil: [labelString := 'Untitled Window' translated].
	isCollapsed := false.
	paneMorphs := Array new.
	Preferences alternativeWindowLook 
		ifTrue: 
			[""

			borderColor := #raised.
			borderWidth := 2.
			color := Color white]
		ifFalse: 
			[""

			borderColor := Color black.
			borderWidth := 1.
			color := Color black].
	
	self layoutPolicy: ProportionalLayout new.
	
	self wantsLabel ifTrue: [self initializeLabelArea].
	self 
		on: #mouseEnter
		send: #spawnReframeHandle:
		to: self.
	self 
		on: #mouseLeave
		send: #spawnReframeHandle:
		to: self.
	self extent: 300 @ 200.
	updatablePanes := Array new! !

!SystemWindow methodsFor: 'initialization' stamp: 'jmv 5/13/2009 15:41'!
initializeLabelArea
	"Initialize the label area (titlebar) for the window."

	| spacing |	
	self flag: #jmvRemove.
	spacing _ self boxExtent x + 2.

	self
		addMorph: (self createCloseBox position: 2@2);
		addMorph: (self createMenuBox position: spacing+2@2);
		addMorph: (self createExpandBox position: spacing*2+2@2);
		addMorph: (self createCollapseBox position: spacing*3+2@2)! !

!SystemWindow methodsFor: 'label' stamp: 'jmv 5/12/2009 17:43'!
labelHeight
	"Answer the height for the window label."

	^ self boxExtent y+1! !

!SystemWindow methodsFor: 'label' stamp: 'jmv 5/13/2009 17:33'!
setLabel: aString

	labelString _ aString.
	self invalidateTitleArea! !

!SystemWindow methodsFor: 'menu' stamp: 'jmv 5/11/2009 23:44'!
buildWindowMenu
	| aMenu |
	aMenu _ MenuMorph new defaultTarget: self.
	aMenu add: 'change title...' translated action: #relabel.
	aMenu addLine.
	aMenu add: 'send to back' translated action: #sendToBack.
	aMenu add: 'make next-to-topmost' translated action: #makeSecondTopmost.
	aMenu addLine.
	aMenu
		add: (self isSticky ifTrue: ['make draggable'] ifFalse: ['make undraggable']) translated 
		action: #toggleStickiness.
	aMenu addLine.
	aMenu add: 'full screen' translated action: #fullScreen.
	self isCollapsed ifFalse: [aMenu add: 'window color...' translated action: #setWindowColor].
	^aMenu! !

!SystemWindow methodsFor: 'menu' stamp: 'jmv 5/13/2009 15:44'!
setWindowColor: incomingColor
	| existingColor aColor |
	incomingColor ifNil: [^ self].  "it happens"
	aColor _ incomingColor asNontranslucentColor.
	(aColor = ColorPickerMorph perniciousBorderColor 
		or: [aColor = Color black]) ifTrue: [^ self].
	existingColor _ self paneColorToUse.
	existingColor ifNil: [^ Beeper beep].
	Preferences alternativeWindowLook ifFalse:[
		(self allMorphs copyWithout: self) do:[:aMorph |
			((aMorph isKindOf: PluggableButtonMorph) and: [aMorph offColor = existingColor])
				ifTrue:
					[aMorph onColor: aColor darker offColor: aColor].
			aMorph color = existingColor
				ifTrue:
					[aMorph color: aColor]]].
	self paneColor: aColor.
	self changed! !

!SystemWindow methodsFor: 'open/close' stamp: 'jmv 5/11/2009 23:45'!
delete
	| thisWorld |
	model okToChange ifFalse: [^self].
	thisWorld := self world.
	super delete.
	model
		windowIsClosing;
		release.
	model := nil.
	SystemWindow noteTopWindowIn: thisWorld! !

!SystemWindow methodsFor: 'panes' stamp: 'jmv 4/7/2009 08:11'!
addMorph: aMorph fullFrame: aLayoutFrame

	super addMorph: aMorph fullFrame: aLayoutFrame.

	paneMorphs _ paneMorphs copyReplaceFrom: 1 to: 0 with: (Array with: aMorph).
	Preferences alternativeWindowLook
		ifFalse:
			[aMorph borderWidth: 1.
			aMorph color: self paneColor]
		ifTrue:
			[aMorph adoptPaneColor: self paneColor.
			aMorph borderWidth: 2; borderColor: #inset; color: Color transparent].
	"reorder panes so flop-out right-side scrollbar is visible"
	Preferences scrollBarsOnRight
		ifTrue: [ self addMorphBack: aMorph ]! !

!SystemWindow methodsFor: 'panes' stamp: 'jmv 5/12/2009 17:35'!
restoreDefaultPaneColor
	"Useful when changing from monochrome to color display"

	Preferences alternativeWindowLook ifFalse:[
		paneMorphs do: [:p | p color: self paneColor]].! !

!SystemWindow methodsFor: 'panes' stamp: 'jmv 5/12/2009 17:35'!
updatePaneColors
	"Useful when changing from monochrome to color display"

	Preferences alternativeWindowLook ifFalse:[
		paneMorphs do: [:p | p color: self paneColorToUse]].! !

!SystemWindow methodsFor: 'resize/collapse' stamp: 'jmv 5/11/2009 23:50'!
collapseOrExpand
	"Collapse or expand the window, depending on existing state"
	| cf |
	isCollapsed
		ifTrue: [
			"Expand -- restore panes to morphics structure"
			isCollapsed _ false.
			self activate.  "Bring to frint first"
			Preferences collapseWindowsInPlace
				ifTrue: [
					fullFrame := fullFrame align: fullFrame topLeft with: self bounds topLeft]
				ifFalse: [
					collapsedFrame _ self bounds].
			self bounds: fullFrame.
			paneMorphs reverseDo: [ :m |  
				self addMorph: m.
				self world startSteppingSubmorphsOf: m]]
		ifFalse: [
			"Collapse -- remove panes from morphics structure"
			isCollapsed _ true.
			fullFrame _ self bounds.
			"First save latest fullFrame"
			paneMorphs do: [:m | m delete; releaseCachedState].
			model modelSleep.
			cf := self getCollapsedFrame.
			(collapsedFrame isNil and: [Preferences collapseWindowsInPlace not]) ifTrue:
				[collapsedFrame _ cf].
			self bounds: cf].
	self layoutChanged! !

!SystemWindow methodsFor: 'resize/collapse' stamp: 'jmv 5/12/2009 17:38'!
collapsedExtent
	^ (Preferences windowTitleFont widthOfString: labelString) + (self boxExtent x *4 + 20 ) @ (self labelHeight + 2)! !

!SystemWindow methodsFor: 'resize/collapse' stamp: 'jmv 5/11/2009 23:51'!
expandBoxHit
	"The full screen expand box has been hit"

	isCollapsed
		ifTrue: [
			self hide.
			self collapseOrExpand.
			self unexpandedFrame ifNil: [ self unexpandedFrame: fullFrame. ].
			self fullScreen.
			^ self show].
	self unexpandedFrame
		ifNil: [
			self unexpandedFrame: fullFrame.
			self fullScreen]
		ifNotNil: [
			self bounds: self unexpandedFrame.
			self unexpandedFrame: nil]! !

!SystemWindow methodsFor: 'resize/collapse' stamp: 'jmv 5/12/2009 17:19'!
getCollapsedFrame

	^Preferences collapseWindowsInPlace
		ifTrue: [ bounds topLeft extent: self collapsedExtent]
		ifFalse: [ RealEstateAgent assignCollapseFrameFor: self ]! !

!SystemWindow methodsFor: 'resize/collapse' stamp: 'jmv 5/14/2009 15:50'!
spawnOffsetReframeHandle: event divider: divider 
	"The mouse has crossed a secondary (fixed-height) pane divider.  Spawn a reframe handle."

	"Only supports vertical adjustments."

	| siblings topAdjustees bottomAdjustees topOnly bottomOnly resizer pt delta minY maxY cursor |
	owner ifNil: [^self	"Spurious mouseLeave due to delete"].
	self isCollapsed ifTrue: [^self].
	((self world ifNil: [^self]) firstSubmorph isKindOf: NewHandleMorph) 
		ifTrue: [^self	"Prevent multiple handles"].
	divider layoutFrame ifNil: [^self].
	(#(#top #bottom) includes: divider resizingEdge) ifFalse: [^self].
	siblings := divider owner submorphs select: [:m | m layoutFrame notNil].
	divider resizingEdge = #bottom 
		ifTrue: 
			[cursor := Cursor resizeTop.
			topAdjustees := siblings select: 
							[:m | 
							m layoutFrame topFraction = divider layoutFrame bottomFraction 
								and: [m layoutFrame topOffset >= divider layoutFrame topOffset]].
			bottomAdjustees := siblings select: 
							[:m | 
							m layoutFrame bottomFraction = divider layoutFrame topFraction 
								and: [m layoutFrame bottomOffset >= divider layoutFrame topOffset]]].
	divider resizingEdge = #top 
		ifTrue: 
			[cursor := Cursor resizeBottom.
			topAdjustees := siblings select: 
							[:m | 
							m layoutFrame topFraction = divider layoutFrame bottomFraction 
								and: [m layoutFrame topOffset <= divider layoutFrame bottomOffset]].
			bottomAdjustees := siblings select: 
							[:m | 
							m layoutFrame bottomFraction = divider layoutFrame topFraction 
								and: [m layoutFrame bottomOffset <= divider layoutFrame bottomOffset]]].
	topOnly := topAdjustees copyWithoutAll: bottomAdjustees.
	bottomOnly := bottomAdjustees copyWithoutAll: topAdjustees.
	(topOnly isEmpty or: [bottomOnly isEmpty]) ifTrue: [^self].
	minY := bottomOnly inject: -9999
				into: [:y :m | y max: m top + 16 + (divider bottom - m bottom)].
	maxY := topOnly inject: 9999
				into: [:y :m | y min: m bottom - 16 - (m top - divider top)].
	pt := event cursorPoint.
	resizer := NewHandleMorph new 
				followHand: event hand
				forEachPointDo: 
					[:p | 
					delta := (p y min: maxY max: minY) - pt y.
					topAdjustees 
						do: [:m | m layoutFrame topOffset: m layoutFrame topOffset + delta].
					bottomAdjustees 
						do: [:m | m layoutFrame bottomOffset: m layoutFrame bottomOffset + delta].
					divider layoutChanged.
					pt := pt + delta]
				lastPointDo: [:p | ]
				withCursor: cursor.
	event hand world addMorphInLayer: resizer.
	resizer startStepping! !

!SystemWindow methodsFor: 'resize/collapse' stamp: 'aoy 2/15/2003 21:06'!
spawnPaneFrameHandle: event 
	| resizer localPt side growingPane newBounds adjoiningPanes limit cursor |
	(self world firstSubmorph isKindOf: NewHandleMorph) 
		ifTrue: [^self	"Prevent multiple handles"].
	((self innerBounds withHeight: self labelHeight + 4) 
		containsPoint: event cursorPoint) 
			ifTrue: [^self	"in label or top of top pane"].
	growingPane := self paneWithLongestSide: [:s | side := s]
				near: event cursorPoint.
	growingPane ifNil: [^self].
	"don't resize pane side coincident with window side - RAA 5 jul 2000"
	(growingPane perform: side) = (self innerBounds perform: side) 
		ifTrue: [^self].
	(side == #top and: [growingPane top = self panelRect top]) ifTrue: [^self].
	adjoiningPanes := paneMorphs 
				select: [:pane | pane bounds bordersOn: growingPane bounds along: side].
	limit := adjoiningPanes isEmpty 
				ifFalse: 
					[(adjoiningPanes collect: [:pane | pane bounds perform: side]) 
						perform: ((#(#top #left) includes: side) ifTrue: [#max] ifFalse: [#min])]
				ifTrue: [self bounds perform: side].
	cursor := Cursor resizeForEdge: side.
	resizer := (NewHandleMorph new)
				sensorMode: self fastFramingOn;
				followHand: event hand
					forEachPointDo: 
						[:p | 
						localPt := self pointFromWorld: p.
						newBounds := growingPane bounds 
									withSideOrCorner: side
									setToPoint: localPt
									minExtent: 40 @ 20
									limit: limit.
						self fastFramingOn 
							ifTrue: 
								["For fast display, only higlight the rectangle during loop"

								Cursor currentCursor == cursor 
									ifFalse: 
										[(event hand)
											visible: false;
											refreshWorld;
											visible: true.
										cursor show].
								newBounds := growingPane bounds newRectButtonPressedDo: 
												[:f | 
												growingPane bounds 
													withSideOrCorner: side
													setToPoint: (self pointFromWorld: Sensor cursorPoint)
													minExtent: 40 @ 20
													limit: limit].].
								self 
									reframePanesAdjoining: growingPane
									along: side
									to: newBounds.
]
					lastPointDo: [:p | ]
					withCursor: cursor.
	event hand world addMorphInLayer: resizer.
	resizer startStepping! !

!SystemWindow methodsFor: 'resize/collapse' stamp: 'jmv 5/5/2009 16:16'!
spawnReframeHandle: event 
	"The mouse has crossed a pane border.  Spawn a reframe handle."

	| resizer localPt pt ptName newBounds cursor |
	owner ifNil: [^self	"Spurious mouseLeave due to delete"].
	self isCollapsed ifTrue: [^self].
	((self world ifNil: [^self]) firstSubmorph isKindOf: NewHandleMorph) 
		ifTrue: [^self	"Prevent multiple handles"].
	pt := event cursorPoint.
	"prevent spurios mouse leave when dropping morphs"
	owner 
		morphsInFrontOf: self
		overlapping: (pt - 2 extent: 4 @ 4)
		do: [:m | m isHandMorph ifFalse: [(m fullContainsPoint: pt) ifTrue: [^self]]].
	self bounds forPoint: pt
		closestSideDistLen: [ :side :dist :len | 
			"Check for window side adjust"

			dist <= 2 ifTrue: [ptName := side]].
	ptName ifNil: ["Check for pane border adjust"

			^self spawnPaneFrameHandle: event].
	#(#topLeft #bottomRight #bottomLeft #topRight) do: [ :corner | 
			"Check for window corner adjust"

			(pt dist: (self bounds perform: corner)) < 20 ifTrue: [ptName := corner]].
	cursor := Cursor resizeForEdge: ptName.
	resizer := (NewHandleMorph new)
				sensorMode: self fastFramingOn;
				followHand: event hand
					forEachPointDo: 
						[:p | 
						localPt := self pointFromWorld: p.
						newBounds := self bounds 
									withSideOrCorner: ptName
									setToPoint: localPt
									minExtent: self minimumExtent.
						self fastFramingOn 
							ifTrue: 
								[Cursor currentCursor == cursor 
									ifFalse: 
										[(event hand)
											visible: false;
											refreshWorld;
											visible: true.
										cursor show].
								self doFastWindowReframe: ptName]
							ifFalse: 
								[self bounds: newBounds]]
					lastPointDo: [:p | ]
					withCursor: cursor.
	event hand world addMorphInLayer: resizer.
	resizer startStepping! !

!SystemWindow methodsFor: 'top window' stamp: 'jmv 5/13/2009 17:34'!
activateAndSendTopToBack: aBoolean
	"Bring me to the front and make me able to respond to mouse and keyboard"

	| oldTop |
	self owner 
		ifNil: [^self	"avoid spurious activate when drop in trash"].
	oldTop := TopWindow.
	TopWindow := self.

	oldTop ifNotNil: [
		oldTop passivate.
		aBoolean ifTrue: [
			oldTop owner addMorphBack: oldTop ]].

	self owner firstSubmorph == self 
		ifFalse: [
			"Bring me (with any flex) to the top if not already"
			self owner addMorphFront: self].
	self invalidateTitleArea.
	self isCollapsed 
		ifFalse: [
			model modelWakeUpIn: self.
			self positionSubmorphs]! !

!SystemWindow methodsFor: 'top window' stamp: 'jmv 5/13/2009 17:34'!
passivate
	"Make me unable to respond to mouse and keyboard"

	| focus |
	focus _ ActiveHand keyboardFocus.
	focus ifNotNil: [
		(focus ownerThatIsA: SystemWindow) == self
			ifTrue: [ ActiveHand releaseKeyboardFocus ]].

	model modelSleep.
	
	self world ifNotNil:  "clean damage now, so dont merge this rect with new top window"
		[self world == World ifTrue: [self world displayWorld]].

	self invalidateTitleArea! !

!SystemWindow methodsFor: 'change reporting' stamp: 'jmv 5/13/2009 17:33'!
invalidateTitleArea
	
	bounds ifNotNil: [
		self invalidRect: self labelRect ]! !


!PreDebugWindow methodsFor: 'initialization' stamp: 'jmv 5/11/2009 23:59'!
initialize

	super initialize.
	self adjustBookControls! !


!TestRunner methodsFor: 'interface opening' stamp: 'jmv 5/5/2009 22:55'!
buildLowerPanes
	| failuresList errorsList column tHeight divider |
	column _ AlignmentMorph proportional.
	self buildPassFailText.
	self buildDetailsText.
	self buildTestsList.
	failuresList _ self buildFailuresList.
	errorsList _ self buildErrorsList.
	tHeight _ 26.
	divider _ Array new: 3.
	1
		to: divider size
		do: [:index | 
			divider at: index put: BorderedSubpaneDividerMorph forBottomEdge.
			Preferences alternativeWindowLook
				ifTrue: [(divider at: index) extent: 4 @ 4;
						 color: Color transparent;
						 borderColor: #raised;
						 borderWidth: 2]].
	column
		addMorph: (passFailText borderWidth: 0)
		fullFrame: (LayoutFrame
				fractions: (0 @ 0 corner: 1 @ 0)
				offsets: (0 @ 0 corner: 0 @ tHeight - 1)).
	column
		addMorph: (divider at: 1)
		fullFrame: (LayoutFrame
				fractions: (0 @ 0 corner: 1 @ 0)
				offsets: (0 @ (tHeight - 1) corner: 0 @ tHeight)).
	column
		addMorph: (detailsText borderWidth: 0)
		fullFrame: (LayoutFrame
				fractions: (0 @ 0 corner: 1 @ 0)
				offsets: (0 @ tHeight corner: 0 @ (2 * tHeight - 1))).
	column
		addMorph: (divider at: 2)
		fullFrame: (LayoutFrame
				fractions: (0 @ 0 corner: 1 @ 0)
				offsets: (0 @ (2 * tHeight - 1) corner: 0 @ (2 * tHeight))).
	column
		addMorph: (failuresList borderWidth: 0)
		fullFrame: (LayoutFrame
				fractions: (0 @ 0 corner: 1 @ 0.6)
				offsets: (0 @ (2 * tHeight) corner: 0 @ -1)).
	column
		addMorph: (divider at: 3)
		fullFrame: (LayoutFrame
				fractions: (0 @ 0.6 corner: 1 @ 0.6)
				offsets: (0 @ - 1 corner: 0 @ 0)).
	column
		addMorph: (errorsList borderWidth: 0)
		fullFrame: (LayoutFrame
				fractions: (0 @ 0.6 corner: 1 @ 1)
				offsets: (0 @ 0 corner: 0 @ 0)).
	^ column! !

!TestRunner methodsFor: 'interface opening' stamp: 'jmv 5/5/2009 22:55'!
buildTestsList
	| column offset buttonRow |
	column _ AlignmentMorph proportional.
	testsList _ PluggableListMorphOfMany
				on: self
				list: #tests
				primarySelection: #selectedSuite
				changePrimarySelection: #selectedSuite:
				listSelection: #listSelectionAt:
				changeListSelection: #listSelectionAt:put:
				menu: #listMenu:shifted:.
	testsList autoDeselect: false.
	offset _ 0.
	self wantsOptionalButtons
		ifTrue: [offset _ TextStyle default lineGrid + 16 ].
	column
		addMorph: testsList
		fullFrame: (LayoutFrame
				fractions: (0 @ 0 corner: 1 @ 1)
				offsets: (0 @ 0 corner: 0 @ offset negated)).
	self wantsOptionalButtons
		ifTrue: [buttonRow _ self optionalButtonRow.
			buttonRow
				color: (Display depth <= 8
						ifTrue: [Color transparent]
						ifFalse: [Color gray alpha: 0.2]);
				 borderWidth: 0.
			Preferences alternativeWindowLook
				ifTrue: [buttonRow color: Color transparent.
					buttonRow
						submorphsDo: [:m | m borderWidth: 1;
								 borderColor: #raised]].
			column
				addMorph: buttonRow
				fullFrame: (LayoutFrame
						fractions: (0 @ 1 corner: 1 @ 1)
						offsets: (0 @ (offset - 1) negated corner: 0 @ 0))].
	^ column! !

!TestRunner methodsFor: 'interface opening' stamp: 'jmv 5/7/2009 18:52'!
buildUpperControls
	| refreshButton filterButton stopButton runOneButton runButton row bWidth listsMorph |
	row _ AlignmentMorph proportional.
	row
		color: (Display depth <= 8
				ifTrue: [Color transparent]
				ifFalse: [Color gray alpha: 0.2]);
		 clipSubmorphs: true;
		 borderWidth: 0.
	refreshButton _ self buildRefreshButton.
	filterButton _ self buildFilterButton.
	stopButton _ self buildStopButton.
	runOneButton _ self buildRunOneButton.
	runButton _ self buildRunButton.
	listsMorph _ self buildTestsList.
	bWidth _ 90.
	row
		addMorph: refreshButton
		fullFrame: (LayoutFrame
				fractions: (0 @ 0 corner: 0 @ 0.33)
				offsets: (4 @ 2 corner: bWidth - 4 @ -2)).
	row
		addMorph: filterButton
		fullFrame: (LayoutFrame
				fractions: (0 @ 0.33 corner: 0 @ 0.66)
				offsets: (4 @ 2 corner: bWidth - 4 @ -2)).
	row
		addMorph: stopButton
		fullFrame: (LayoutFrame
				fractions: (0 @ 0.66 corner: 0 @ 1)
				offsets: (4 @ 2 corner: bWidth - 4 @ -2)).
	row
		addMorph: listsMorph
		fullFrame: (LayoutFrame
				fractions: (0 @ 0 corner: 1 @ 1)
				offsets: (bWidth  @ 0 corner: bWidth negated @ 0)).
	row
		addMorph: runOneButton
		fullFrame: (LayoutFrame
				fractions: (1 @ 0 corner: 1 @ 0.5)
				offsets: (bWidth negated + 4 @ 2 corner: -4 @ -2)).
	row
		addMorph: runButton
		fullFrame: (LayoutFrame
				fractions: (1 @ 0.5 corner: 1 @ 1)
				offsets: (bWidth negated + 4 @ 2 corner: -4 @ -2)).
	Preferences alternativeWindowLook
		ifTrue: [row color: Color transparent.
			row
				submorphsDo: [:m | m borderWidth: 2;
						 borderColor: #raised]].
	^ row! !

!TestRunner methodsFor: 'interface opening' stamp: 'jmv 5/5/2009 22:55'!
optionalButtonRow
	| row btn buttons widths |

	buttons _ OrderedCollection new.
	widths _ OrderedCollection new.
	self optionalButtonTuples do: [ :tuple | 
		widths add: tuple first.
		btn _ PluggableButtonMorph 
			on: self
			getState: nil
			action: tuple third.
		btn
			clipSubmorphs: true;
			onColor: Color transparent offColor: Color transparent;
			label: tuple second.
		buttons add: btn].
	row _ AlignmentMorph proportional.
	row addInRow: buttons widthProportionalTo: widths inset: 2.
	^row! !

!TestRunner methodsFor: 'menus' stamp: 'jmv 5/7/2009 18:57'!
installProgressWatcher
	| win host |
	win _ self dependents first.
	host _ win submorphs first.
	progress _ ProgressMorph label: 'Test progress'.
	progress
		borderWidth: 0;
		position: host position;
		extent: host extent;
		color: Color transparent;
		hResizing: #spaceFill;
		vResizing: #spaceFill.
	win
		addMorph: progress 
		frame: (0.0 @ 0.7 extent: 1.0 @ 0.3).
! !

!TestRunner methodsFor: 'menus' stamp: 'jmv 5/12/2009 00:16'!
optionalButtonTuples
	^#(
		#(11	'select all' 				#selectAll) 
		#(14	'deselect all' 			#deselectAll) 
		#(20	'toggle selections' 		#toggleSelections)
	)! !


!TextMorph methodsFor: 'menu' stamp: 'jmv 5/11/2009 23:54'!
addCustomMenuItems: aCustomMenu hand: aHandMorph 
	"Add text-related menu items to the menu"

	| outer |
	super addCustomMenuItems: aCustomMenu hand: aHandMorph.
	aCustomMenu 
		addUpdating: #autoFitString
		target: self
		action: #autoFitOnOff.
	aCustomMenu 
		addUpdating: #wrapString
		target: self
		action: #wrapOnOff.
	aCustomMenu add: 'text margins...' translated action: #changeMargins:.
	Preferences simpleMenus
		ifFalse: 
			[aCustomMenu add: 'code pane menu...' translated
				action: #yellowButtonActivity.
			aCustomMenu add: 'code pane shift menu....' translated
				action: #shiftedYellowButtonActivity].
	outer := self owner.
	((outer isKindOf: PolygonMorph) and: [outer isOpen]) 
		ifTrue: 
			[container isNil 
				ifFalse: 
					[aCustomMenu add: 'reverse direction' translated
						action: #reverseCurveDirection.
					aCustomMenu add: 'set baseline' translated action: #setCurveBaseline:]]
		ifFalse: 
			[(container isNil or: [container fillsOwner not]) 
				ifTrue: 
					[aCustomMenu add: 'fill owner''s shape' translated action: #fillingOnOff]
				ifFalse: 
					[aCustomMenu add: 'rectangular bounds' translated action: #fillingOnOff].
			(container isNil or: [container avoidsOcclusions not]) 
				ifTrue: 
					[aCustomMenu add: 'avoid occlusions' translated action: #occlusionsOnOff]
				ifFalse: 
					[aCustomMenu add: 'ignore occlusions' translated action: #occlusionsOnOff]]! !


!TextMorphForEditView methodsFor: 'event handling' stamp: 'jmv 5/11/2009 23:39'!
mouseDown: event

	event yellowButtonPressed ifTrue: [^ self yellowButtonActivity: event shiftPressed].
	super mouseDown: event.
	event hand 
		waitForSimulatedYellow: self 
		event: event! !


!TheWorldMenu methodsFor: 'construction' stamp: 'jmv 5/6/2009 22:48'!
fillIn: aMenu from: dataForMenu
	"A menu constructor utility by RAA.  dataForMenu is a list of items which mean:
			nil								Indicates to add a line

			first element is symbol		Add updating item with the symbol as the wording selector
			second element is a list		second element has the receiver and selector

			first element is a string		Add menu item with the string as its wording
			second element is a list		second element has the receiver and selector

			a third element exists			Use it as the balloon text
			a fourth element exists		Use it as the enablement selector (updating case only)"

	| item |

	dataForMenu do: [ :itemData |
		itemData ifNil: [aMenu addLine] ifNotNil:
			[item _ (itemData first isKindOf: Symbol)
				ifTrue: 
					[aMenu 
						addUpdating: itemData first 
						target: self 
						selector: #doMenuItem:with: 
						argumentList: {itemData second}]
				 ifFalse:
					[aMenu 
						add: itemData first translated
						target: self 
						selector: #doMenuItem:with: 
						argumentList: {itemData second}].
			itemData size >= 3 ifTrue:
				[aMenu balloonTextForLastItem: itemData third translated.
			itemData size >= 4 ifTrue:
				[item enablementSelector: itemData fourth]]]].

	^ aMenu! !

!TheWorldMenu methodsFor: 'construction' stamp: 'jmv 5/5/2009 16:34'!
helpMenu
        "Build the help menu for the world."
        |  menu |

  	menu := self menu: 'help...' translated.

        self fillIn: menu from:
        {
                {'about this system...'. {Smalltalk. #aboutThisSystem}. 'current version information.'}.
                {'preferences...'. {Preferences. #openPreferencesInspector}. 'view and change various options.'}.
                nil.
               {'command-key help'. { Utilities . #openCommandKeyHelp}. 'summary of keyboard shortcuts.'}
	}.

	self addGestureHelpItemsTo: menu.

	self fillIn: menu from:
	{
                {'world menu help'. { self . #worldMenuHelp}. 'helps find menu items buried in submenus.'}.
                        "{'info about flaps' . { Utilities . #explainFlaps}. 'describes how to enable and use flaps.'}."
                {'font size summary' . { TextStyle . #fontSizeSummary}.  'summary of names and sizes of available fonts.'}.
                {'useful expressions' . { Utilities . #openStandardWorkspace}. 'a window full of useful expressions.'}.
			nil.
                {#soundEnablingString . { Preferences . #toggleSoundEnabling}. 'turning sound off will completely disable Squeak''s use of sound.'}.
                nil.

                {'set author initials...' . { Utilities . #setAuthorInitials }. 'supply initials to be used to identify the author of code and other content.'}.
                {'vm statistics' . { self . #vmStatistics}.  'obtain some intriguing data about the vm.'}.
			  nil.
                {'space left' . { self . #garbageCollect}. 'perform a full garbage-collection and report how many bytes of space remain in the image.'}.
        }.

	^menu

! !


!VersionsBrowser methodsFor: 'init & update' stamp: 'jmv 5/5/2009 14:17'!
buttonSpecs

	^#(
		(22
		'compare to current'
		compareToCurrentVersion
		'opens a separate window which shows the text differences between the selected version and the current version')

		(9
		'revert'
		fileInSelections
		'reverts the method to the version selected')

		(24
		'remove from changes'
		removeMethodFromChanges
		'remove this method from the current change set')

		(6
		'help'
		offerVersionsHelp
		'further explanation about use of Versions browsers')
	)! !


!ClassCommentVersionsBrowser methodsFor: 'misc' stamp: 'jmv 5/5/2009 14:41'!
contentsSymbolQuints
	"Answer a list of quintuplets representing information on the alternative views available in the code pane"

	^ #(
(source			togglePlainSource 		showingPlainSourceString		'source'		'the textual source code as writen')
(showDiffs		toggleRegularDiffing	showingRegularDiffsString		'showDiffs'		'the textual source diffed from its prior version'))! !

VersionsBrowser removeSelector: #changeListButtonSpecs!
Utilities class removeSelector: #storeTextWindowContentsToFileNamed:!
TestRunner removeSelector: #optionalButtonPairs!
SystemWindow class removeSelector: #newWithoutLabel!
PreDebugWindow removeSelector: #setBalloonTextForCloseBox!
PreDebugWindow removeSelector: #setLabelWidgetAllowance!
SystemWindow removeSelector: #addCloseBox!
SystemWindow removeSelector: #addExpandBox!
SystemWindow removeSelector: #addLabelArea!
SystemWindow removeSelector: #addMenuControl!
SystemWindow removeSelector: #adjustBorderUponActivationWhenLabeless!
SystemWindow removeSelector: #adjustBorderUponDeactivationWhenLabeless!
SystemWindow removeSelector: #deleteCloseBox!
SystemWindow removeSelector: #getRawLabel!
SystemWindow removeSelector: #holdsTranscript!
SystemWindow removeSelector: #labelWidgetAllowance!
SystemWindow removeSelector: #makeClosable!
SystemWindow removeSelector: #makeUnclosable!
SystemWindow removeSelector: #maximumExtent!
SystemWindow removeSelector: #maximumExtent:!
SystemWindow removeSelector: #mouseLeaveEvent:fromPane:!
SystemWindow removeSelector: #mustNotClose!
SystemWindow removeSelector: #openAsIs!
SystemWindow removeSelector: #replaceBoxes!
SystemWindow removeSelector: #replacePane:with:!
SystemWindow removeSelector: #scrollBarColor!
SystemWindow removeSelector: #setFramesForLabelArea!
SystemWindow removeSelector: #setLabelWidgetAllowance!
SystemWindow removeSelector: #setStripeColorsFrom:!
SystemWindow removeSelector: #titleAndPaneText!
SystemWindow removeSelector: #tryToRenameTo:!
SystemWindow removeSelector: #updateBox:color:!
SystemWindow removeSelector: #updateBoxesColor:!
SystemWindow removeSelector: #wantsExpandBox!
SystemWindow removeSelector: #widthOfFullLabelText!
!classDefinition: #SystemWindow category: #'Morphic-OldWindows'!
MorphWithModel subclass: #SystemWindow
	instanceVariableNames: 'labelString paneMorphs collapsedFrame fullFrame isCollapsed updatablePanes'
	classVariableNames: 'CloseBoxImage CollapseBoxImage TopWindow'
	poolDictionaries: ''
	category: 'Morphic-OldWindows'!
StringMorph class removeSelector: #test!
StringMorph class removeSelector: #test2!
MenuItemMorph removeSelector: #allWordingsNotInSubMenus:!
MenuItemMorph removeSelector: #hasSubMenu:!
MenuItemMorph removeSelector: #itemWithWording:!
MenuItemMorph removeSelector: #minHeight!
MenuItemMorph removeSelector: #minWidth!
MenuItemMorph removeSelector: #notObsolete!
MenuItemMorph removeSelector: #vResizing!
StringMorph removeSelector: #minHeight!
FileList2 removeSelector: #dropDestinationDirectory:event:!
FileList2 removeSelector: #importImage!

!FileList2 reorganize!
('initialization' directory: fileSelectionBlock: initialDirectoryList labelString optionalButtonSpecs optionalButtonSpecs: universalButtonServices updateDirectory)
('initialize-release' initialize)
('own services' addNewDirectory deleteDirectory okayAndCancelServices serviceCancel serviceOkay servicesForFolderSelector)
('user interface' morphicDirectoryTreePane morphicDirectoryTreePaneFiltered: morphicFileContentsPane morphicFileListPane morphicPatternPane)
('volume list and pattern' directory listForPatterns:)
('private' cancelHit currentDirectorySelected directoryNamesFor: getSelectedDirectory getSelectedFile modalView: okHit postOpen setSelectedDirectoryTo:)
!

FileList class removeSelector: #detectService:ifNone:!
FileList removeSelector: #dirAndFileName!
FileList removeSelector: #dragTransferTypeForMorph:!
FileList removeSelector: #dropDestinationDirectory:event:!
FileList removeSelector: #isDirectoryList:!
FileList removeSelector: #listForPattern:!
FileList removeSelector: #primitiveCopyFileNamed:to:!

!FileList reorganize!
('file list' fileList fileListIndex fileListIndex: fileName readOnlyStream)
('file list menu' compressFile fileContentsMenu:shifted: fileListMenu: fileSelectedMenu: fullFileListMenu:shifted: itemsForAnyFile itemsForFile: itemsForNoFile myServicesForFile:suffix: noFileSelectedMenu: offerAllFileOptions suffixOfSelectedFile)
('file menu action' addNew:byEvaluating: addNewDirectory addNewFile deleteFile get getHex renameFile sortByDate sortByName sortBySize spawn:)
('initialization' buttonSelectorsToSuppress directory: dynamicButtonServices labelString modelSleep modelWakeUp optionalButtonRow optionalButtonSpecs release setFileStream: universalButtonServices updateButtonRow updateButtonRow:)
('menu messages' copyName)
('own services' serviceAddNewDirectory serviceAddNewFile serviceAllFileOptions serviceBrowseCodeFiles serviceCompressFile serviceCopyName serviceDeleteFile serviceGet serviceGetHex serviceRenameFile serviceSortByDate serviceSortByName serviceSortBySize serviceViewContentsInWorkspace servicesFromSelectorSpecs: viewContentsInWorkspace)
('to be transformed in registration' perform:orSendTo: volumeMenu:)
('updating' update:)
('volume list and pattern' deleteDirectory directory fileNameFormattedFrom:sizePad: pattern pattern: veryDeepFixupWith: volumeList volumeListIndex volumeListIndex:)
('private' addPath: contents defaultContents entriesMatching: fileNameFromFormattedItem: folderString fullName isFileSelected listForPatterns: put: readContentsBrief: readContentsHex: readServerBrief recentDirs registeredFileReaderClasses resort: sortBlock sortingByDate sortingByName sortingBySize updateFileList)
!

Debugger removeSelector: #optionalButtonRow!
ChangeList removeSelector: #changeListButtonSpecs!
Browser removeSelector: #addAListPane:to:at:plus:!
Browser removeSelector: #addMorphicSwitchesTo:at:!
Browser removeSelector: #dragTransferTypeForMorph:!
CodeHolder removeSelector: #codePaneProvenanceButton!
CodeHolder removeSelector: #diffButton!
CodeHolder removeSelector: #optionalButtonPairs!
ColorPickerMorph removeSelector: #updateSelectorDisplay!
!classDefinition: #ColorPickerMorph category: #'Morphic-OldWidgets'!
SketchMorph subclass: #ColorPickerMorph
	instanceVariableNames: 'selectedColor sourceHand deleteOnMouseUp updateContinuously target selector argument originalColor command isModal clickedTranslucency'
	classVariableNames: 'ColorChart DragBox FeedbackBox RevertBox TransText TransparentBox'
	poolDictionaries: ''
	category: 'Morphic-OldWidgets'!
SketchMorph removeSelector: #baseGraphic!
SketchMorph removeSelector: #baseGraphic:!
SketchMorph removeSelector: #callThisBaseGraphic!
SketchMorph removeSelector: #collapse!
SketchMorph removeSelector: #restoreBaseGraphic!
SketchMorph removeSelector: #restoreBaseGraphicFromMenu!
SimpleButtonMorph removeSelector: #extent:!
SimpleButtonMorph removeSelector: #labelString:!
!classDefinition: #SimpleButtonMorph category: #'Morphic-OldWidgets'!
RectangleMorph subclass: #SimpleButtonMorph
	instanceVariableNames: 'target actionSelector arguments actWhen oldColor label font'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Morphic-OldWidgets'!
ProportionalLayout removeSelector: #isProportionalLayout!
ProportionalLayout removeSelector: #minExtentOf:in:!
ProgressMorph removeSelector: #label!
ProgressMorph removeSelector: #labelMorph!
ProgressMorph removeSelector: #progress!
ProgressMorph removeSelector: #subLabel!
ProgressMorph removeSelector: #subLabelMorph!
Preferences class removeSelector: #annotationEditingWindow!
Preferences class removeSelector: #debugMenuItemsInvokableFromScripts!
Preferences class removeSelector: #editAnnotations!
Preferences class removeSelector: #noviceMode!
Preferences class removeSelector: #refreshFontSettings!
Preference removeSelector: #offerPreferenceNameMenu:with:in:!
Preference removeSelector: #representativeButtonWithColor:inPanel:!
Preference removeSelector: #tearOffButton!
PluggableButtonMorph removeSelector: #label!
!classDefinition: #PluggableButtonMorph category: #'Morphic-OldWindows'!
AlignmentMorph subclass: #PluggableButtonMorph
	instanceVariableNames: 'model label font getStateSelector actionSelector getLabelSelector getMenuSelector shortcutCharacter askBeforeChanging triggerOnMouseDown offColor onColor feedbackColor showSelectionFeedback allButtons arguments argumentsProvider argumentsSelector'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Morphic-OldWindows'!
MouseClickState removeSelector: #client:click:dblClick:dblClickTime:dblClickTimeout:drag:threshold:event:sendYellowButtonActivity:!
MorphExtension removeSelector: #layoutProperties!
MorphExtension removeSelector: #layoutProperties:!
AlignmentMorph class removeSelector: #newColumn!
AlignmentMorph class removeSelector: #newRow!
AlignmentMorph class removeSelector: #newSpacer:!
AlignmentMorph class removeSelector: #newVariableTransparentSpacer!
Morph class removeSelector: #defaultArrowheadSize!
MenuMorph removeSelector: #addTitle:updatingSelector:updateTarget:!
MenuMorph removeSelector: #allWordings!
MenuMorph removeSelector: #allWordingsNotInSubMenus:!
MenuMorph removeSelector: #hasSubMenu:!
MenuMorph removeSelector: #itemWithWording:!
MenuMorph removeSelector: #lastSelection!
!classDefinition: #MenuMorph category: #'Morphic-OldMenus'!
BorderedMorph subclass: #MenuMorph
	instanceVariableNames: 'defaultTarget selectedItem stayUp popUpOwner activeSubMenu titleMorph'
	classVariableNames: 'CloseBoxImage PushPinImage'
	poolDictionaries: ''
	category: 'Morphic-OldMenus'!
MenuLineMorph removeSelector: #minHeight!
MenuLineMorph removeSelector: #minWidth!
HandMorph removeSelector: #waitForClicksOrDrag:event:clkSel:dblClkSel:dblClkTimeoutSel:dragSel:threshold:!
HandMorph removeSelector: #waitForClicksOrDragOrSimulatedYellow:event:clkSel:dblClkSel:dblClkTimeoutSel:dragSel:threshold:!
HandMorph removeSelector: #waitForSimulatedYellow:event:threshold:!
!classDefinition: #FillInTheBlankMorph category: #'Morphic-OldWindows'!
AlignmentMorph subclass: #FillInTheBlankMorph
	instanceVariableNames: 'response done textPane responseUponCancel'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Morphic-OldWindows'!
BorderedMorph removeSelector: #acquireBorderWidth:!
Morph removeSelector: #addCellLayoutMenuItems:hand:!
Morph removeSelector: #addLayoutMenuItems:hand:!
Morph removeSelector: #addTableLayoutMenuItems:hand:!
Morph removeSelector: #addTransparentSpacerOfSize:!
Morph removeSelector: #adjustLayoutBounds!
Morph removeSelector: #assureLayoutProperties!
Morph removeSelector: #assureTableProperties!
Morph removeSelector: #cellInset!
Morph removeSelector: #cellInset:!
Morph removeSelector: #cellPositioning!
Morph removeSelector: #cellPositioning:!
Morph removeSelector: #cellPositioningString:!
Morph removeSelector: #cellSpacing!
Morph removeSelector: #cellSpacing:!
Morph removeSelector: #cellSpacingString:!
Morph removeSelector: #changeAllBorderColorsFrom:to:!
Morph removeSelector: #changeCellInset:!
Morph removeSelector: #changeClipLayoutCells!
Morph removeSelector: #changeDisableTableLayout!
Morph removeSelector: #changeLayoutInset:!
Morph removeSelector: #changeListDirection:!
Morph removeSelector: #changeMaxCellSize:!
Morph removeSelector: #changeMinCellSize:!
Morph removeSelector: #changeNoLayout!
Morph removeSelector: #changeProportionalLayout!
Morph removeSelector: #changeReverseCells!
Morph removeSelector: #changeRubberBandCells!
Morph removeSelector: #changeTableLayout!
Morph removeSelector: #chooseNewGraphic!
Morph removeSelector: #chooseNewGraphicCoexisting:!
Morph removeSelector: #chooseNewGraphicFromHalo!
Morph removeSelector: #clipLayoutCells!
Morph removeSelector: #clipLayoutCells:!
Morph removeSelector: #defaultArrowheadSize!
Morph removeSelector: #disableTableLayout!
Morph removeSelector: #disableTableLayout:!
Morph removeSelector: #hResizingString:!
Morph removeSelector: #hasClipLayoutCellsString!
Morph removeSelector: #hasDisableTableLayoutString!
Morph removeSelector: #hasNoLayoutString!
Morph removeSelector: #hasProportionalLayoutString!
Morph removeSelector: #hasReverseCellsString!
Morph removeSelector: #hasRubberBandCellsString!
Morph removeSelector: #hasTableLayoutString!
Morph removeSelector: #layoutMenuPropertyString:from:!
Morph removeSelector: #layoutProperties!
Morph removeSelector: #layoutProperties:!
Morph removeSelector: #listCentering!
Morph removeSelector: #listCentering:!
Morph removeSelector: #listCenteringString:!
Morph removeSelector: #listDirection!
Morph removeSelector: #listDirection:!
Morph removeSelector: #listDirectionString:!
Morph removeSelector: #listSpacing!
Morph removeSelector: #listSpacing:!
Morph removeSelector: #listSpacingString:!
Morph removeSelector: #maxCellSize!
Morph removeSelector: #maxCellSize:!
Morph removeSelector: #minCellSize!
Morph removeSelector: #minCellSize:!
Morph removeSelector: #minExtent!
Morph removeSelector: #minHeight!
Morph removeSelector: #minWidth!
Morph removeSelector: #reverseTableCells!
Morph removeSelector: #reverseTableCells:!
Morph removeSelector: #rootMorphsAt:!
Morph removeSelector: #rubberBandCells!
Morph removeSelector: #rubberBandCells:!
Morph removeSelector: #seizesNavigationFocus!
Morph removeSelector: #spaceFillWeight!
Morph removeSelector: #transparentSpacerOfSize:!
Morph removeSelector: #uncollapseSketch!
Morph removeSelector: #useDefaultFill!
Morph removeSelector: #vResizingString:!
Morph removeSelector: #wrapCentering!
Morph removeSelector: #wrapCentering:!
Morph removeSelector: #wrapCenteringString:!
Morph removeSelector: #wrapDirection!
Morph removeSelector: #wrapDirection:!
Morph removeSelector: #wrapDirectionString:!
!classDefinition: #Morph category: #'Morphic-OldKernel'!
Object subclass: #Morph
	instanceVariableNames: 'bounds owner submorphs fullBounds color extension layoutInset hResizing vResizing'
	classVariableNames: 'EmptyArray'
	poolDictionaries: ''
	category: 'Morphic-OldKernel'!
ListItemLW removeSelector: #seizesNavigationFocus!
ButtonLW removeSelector: #seizesNavigationFocus!
LightWidget removeSelector: #seizesNavigationFocus!
LayoutPolicy removeSelector: #indexForInserting:at:in:!
LayoutPolicy removeSelector: #isProportionalLayout!
LayoutPolicy removeSelector: #isTableLayout!
LayoutPolicy removeSelector: #minExtentOf:in:!
FormsAndHelpsRepository removeSelector: #inspectFormDictionary!
Form class removeSelector: #importImage:!
Form class removeSelector: #serviceImageImports!
Object removeSelector: #dragTransferTypeForMorph:!
Object removeSelector: #updateListsAndCodeIn:!
Smalltalk removeClassNamed: #BorderedStringMorph!
Smalltalk removeClassNamed: #GraphicalDictionaryMenu!
Smalltalk removeClassNamed: #GraphicalMenu!
Smalltalk removeClassNamed: #Imports!
Smalltalk removeClassNamed: #LayoutCell!
Smalltalk removeClassNamed: #LayoutProperties!
Smalltalk removeClassNamed: #NameStringInHalo!
Smalltalk removeClassNamed: #SystemWindowWithButton!
Smalltalk removeClassNamed: #TableLayout!
Smalltalk removeClassNamed: #TableLayoutProperties!
Smalltalk removeClassNamed: #UpdatingSimpleButtonMorph!
Smalltalk removeClassNamed: #UpdatingStringMorph!
