'From Squeak3.7 of ''4 September 2004'' [latest update: #5989] on 18 November 2008 at 2:00:05 pm'!

!CompositeLW commentStamp: 'jmv 11/18/2008 10:23' prior: 0!
A Composite Light Widget can contain other widgets as submorphs!

!classDefinition: #DialogLW category: #'LightWidgets-Kernel'!
CompositeLW subclass: #DialogLW
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'LightWidgets-Kernel'!

!DialogLW commentStamp: '<historical>' prior: 0!
A Dialog is a composite that cycles only its submorph tree. This means it will decide when to close and give up keyboard focus.!

!classDefinition: #EntryField2LW category: #'LightWidgets-Kernel'!
LightWidget subclass: #EntryField2LW
	instanceVariableNames: 'font contents editor foreColor backColor selectedForeColor selectedBackColor crAction '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'LightWidgets-Kernel'!

!LightWidget methodsFor: 'view of a model or target' stamp: 'jmv 11/18/2008 11:13'!
updateView
	"The model or some Model Extension changed is some way.
	We must update ourselves to reflect the new state.

	This is the place to update secondary Model Extensions or any other state that must be updated
	after model or Model Extension change.

	This method is usually reimplemented in CompositeLWs, to update subviews.
	
	The subviews should be sent one of the following messages:
		modelChanged
		target:
		target:aspect:
		target:aspect:aspectAdaptor:
		target:aspect:aspectAdaptor:aspectChangeEvent:
	to update their model and do a full update, as triggered by #modelChanged"
	
	self changed! !


!ButtonLW methodsFor: 'events-processing' stamp: 'jmv 11/18/2008 13:54'!
handlesKeyboard

	^self visible! !


!CheckBoxLW methodsFor: 'events-processing' stamp: 'jmv 11/18/2008 13:54'!
handlesKeyboard

	^self visible! !


!DialogLW methodsFor: 'iteration of all morphs' stamp: 'jmv 11/18/2008 10:25'!
nextMorphPart2

	"This morph reimplements #previousMorph and #nextMorph to cycle only
	through its submorph tree"
	^ submorphs first! !

!DialogLW methodsFor: 'iteration of all morphs' stamp: 'jmv 11/18/2008 10:25'!
previousMorph

	"This morph reimplements #previousMorph and #nextMorph to cycle only
	through its submorph tree"
	^self veryLastLeave! !


!EntryField2LW methodsFor: 'accessing' stamp: 'jmv 11/18/2008 10:04'!
crAction: aSymbol
	"Set the action to execute when the user presses <Enter>.
	Optional. Used usually when there are no others widgets to go to, 
	and input should be accepted and processed"
	
	^ crAction _ aSymbol! !

!EntryField2LW methodsFor: 'drawing' stamp: 'jmv 11/17/2008 16:28'!
characterIndexAtPoint: aPoint

	| line block |
	
	line _ OldTextLine 
		start: 1
		stop: contents size
		internalSpaces: 0
		paddingWidth: 0.
	line
		rectangle: bounds;
		lineHeight: font height baseline: font ascent.
		
	block _ (CharacterBlockScanner new text: contents asText textStyle: (TextStyle fontArray: {font}))
		characterBlockAtPoint: aPoint index: nil
		in: line.

	^ block stringIndex! !

!EntryField2LW methodsFor: 'drawing' stamp: 'jmv 11/18/2008 09:39'!
drawCaretOn: aCanvas
	|  w caretColor leftX top bottom |

	top _ bounds top + 4.
	bottom _ top + font height + 1.
	leftX _ (font widthOfString: contents from: 1 to: editor startIndex-1) + bounds left + 4.
	w := 3.
	caretColor := self insertionPointColor.
	
	1 to: w do: [:i |
		"Draw caret triangles at top and bottom"
		aCanvas fillRectangle: ((leftX - w + i - 1) @ (top + i - 1) 
				extent: ((w - i) * 2 + 4) @ 1)
			color: caretColor.
		aCanvas fillRectangle: ((leftX - w + i - 1) @ (bottom - i) 
				extent: ((w - i) * 2 + 4) @ 1)
			color: caretColor].
	aCanvas fillRectangle: (leftX @ top corner: leftX+2 @ bottom)
		color: caretColor! !

!EntryField2LW methodsFor: 'drawing' stamp: 'jmv 11/17/2008 16:31'!
drawOn: aCanvas

	aCanvas frameAndFillRectangle: bounds fillColor: self backColor borderWidth: 2 borderColor: Color black.
	self hasSelection ifTrue: [
		self drawSelectionOn: aCanvas ].
	self hasCaret ifTrue: [
		self drawCaretOn: aCanvas].
	aCanvas drawString: contents in: (bounds insetBy: 5) font: font color: self foreColor! !

!EntryField2LW methodsFor: 'drawing' stamp: 'jmv 11/17/2008 16:37'!
drawSelectionOn: aCanvas
	| rightX leftX top bottom |

	top _ bounds top + 5.
	bottom _ top + font height.
	leftX _ (font widthOfString: contents from: 1 to: editor startIndex-1) + bounds left + 5.
	rightX _ (font widthOfString: contents from: 1 to: editor stopIndex-1) + bounds left + 5.

	aCanvas fillRectangle: (leftX @ top corner: rightX @ bottom)
		color: self selectionColor! !

!EntryField2LW methodsFor: 'event handling' stamp: 'jmv 11/18/2008 13:54'!
handlesKeyboard

	^self visible! !

!EntryField2LW methodsFor: 'event handling' stamp: 'jmv 11/17/2008 16:28'!
handlesMouseDown: evt
	^ bounds containsPoint: evt cursorPoint! !

!EntryField2LW methodsFor: 'event handling' stamp: 'jmv 11/18/2008 10:13'!
keyStroke: aKeyboardEvent
	"Handle a keystroke event."

	| k |
	aKeyboardEvent commandKeyPressed
		ifTrue: [ ^super keyStroke: aKeyboardEvent ].
	
	k _ aKeyboardEvent keyValue.
	k = 13 ifTrue: [
		crAction notNil ifTrue: [	
			self performActionWith: contents.
			self updateView.
			^target perform: crAction ].
		^ aKeyboardEvent hand keyboardFocusNext ].
	(k = 30 or: [ k = 31 ])
		ifTrue: [ ^super keyStroke: aKeyboardEvent ].
	(k = 28 and: [ editor isAtStart ])
		ifTrue: [ ^super keyStroke: aKeyboardEvent ].
	(k = 29 and: [ editor isAtEnd ])
		ifTrue: [ ^super keyStroke: aKeyboardEvent ].

	self handleInteraction: [editor readKeyboard] fromEvent: aKeyboardEvent.
	self updateFromContents! !

!EntryField2LW methodsFor: 'event handling' stamp: 'jmv 11/18/2008 10:13'!
keyboardFocusChange: aBoolean 
	aBoolean ifTrue: [
		"A hand is wanting to send us characters... Ensure editor."
		self editor.
		self changed ]
	ifFalse: [
		self performActionWith: contents.
		self updateView ]! !

!EntryField2LW methodsFor: 'unaccepted edits' stamp: 'jmv 11/17/2008 16:22'!
hasUnacceptedEdits: aBoolean
	"Set the hasUnacceptedEdits flag to the given value. "
	
	self flag: #jmv.
	"Not used in this morph, as it doesn't do accept / cancel"
	self changed! !

!EntryField2LW methodsFor: 'updating' stamp: 'jmv 11/17/2008 16:35'!
modelChanged

	contents _ self targetAspect.
	super modelChanged! !


!EntryFieldLW methodsFor: 'events-processing' stamp: 'jmv 11/17/2008 15:23'!
keyStroke: aKeyboardEvent

	| c |
	aKeyboardEvent commandKeyPressed  ifTrue:[^super keyStroke: aKeyboardEvent].
	target isNil ifTrue:[ ^ self].
	
	c _ aKeyboardEvent keyCharacter.
	( aKeyboardEvent shiftPressed and:[ c isLetter not] ) ifTrue:[^ self selectionChanged: aKeyboardEvent].
	c = Character arrowRight ifTrue:[
		cursorPosition  = (self value size + 1) ifTrue:[ ^super keyStroke: aKeyboardEvent].
		^ self moveCursorForth].
	c = Character arrowLeft ifTrue:[
		cursorPosition  = 1 ifTrue:[ ^super keyStroke: aKeyboardEvent].
		 ^ self moveCursorBack].
	c = Character backspace ifTrue:[^ self backspaceEntered].
	c = Character delete ifTrue:[^self deleteEntered].
	c = Character end ifTrue:[ ^ self moveCursorToEnd].
	c = Character home ifTrue:[ ^ self moveCursorToBeggining].
	c  = Character escape ifTrue:[^ self escapeEntered].
	c isSeparator ifTrue:[^self separatorEntered:c].

	c asciiValue >= 32
		ifTrue: [ self characterEntered: c ]
		ifFalse: [
			"Call super for ignored keys"
			^ super keyStroke: aKeyboardEvent]! !

!EntryFieldLW methodsFor: 'event handling' stamp: 'jmv 11/18/2008 13:54'!
handlesKeyboard

	^ self visible ! !


!ListLW methodsFor: 'focus handling' stamp: 'jmv 11/14/2008 13:24'!
focused: aSubmorph
	"Default is to do nothing."
	
	| delta |
	delta _ aSubmorph bounds amountToTranslateWithin: bounds.
	delta = (0@0) ifFalse: [
		submorphs do: [ :m |
			m privateFullMoveBy: delta].
		self changed]! !


!MenuItemLW methodsFor: 'focus handling' stamp: 'jmv 11/14/2008 13:25'!
keyboardFocusChange: aBoolean

	aBoolean ifTrue: [
		owner focused: self ].
	self changed! !


!OldMenuMorph methodsFor: 'keyboard control' stamp: 'jmv 11/18/2008 13:53'!
handlesKeyboard
	"Answer whether the receiver handle keyboard events"

	^self visible! !


!OldOneLineEditorMorph methodsFor: 'event handling' stamp: 'jmv 11/18/2008 13:53'!
handlesKeyboard

	^self visible! !


!OldPluggableListMorph methodsFor: 'event handling' stamp: 'jmv 11/18/2008 13:53'!
handlesKeyboard

	^self visible! !


!OldPluggableListMorphOfMany methodsFor: 'event handling' stamp: 'jmv 11/18/2008 10:17'!
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 ifFalse: [^ self].  "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"! !


!OldPluggableTextMorph methodsFor: 'event handling' stamp: 'jmv 11/18/2008 13:53'!
handlesKeyboard

	self flag: #jmv.
	"Not answering true helps not hitting pluggable texts twice during navigation. Only the internal text morph will receive it.
	If some problem is found, introduce a new selector, that answers ^self handlesKeyboard in morph (and LW) 
	and only in this class it will answer false"
"	^self visible" 
	^ super handlesKeyboard! !

!OldPluggableTextMorph methodsFor: 'menu commands' stamp: 'jmv 11/14/2008 11:05'!
accept
	"Inform the model of text to be accepted, and return true if OK."

	"sps 8/13/2001 22:41: save selection and scroll info"

	| textToAccept ok saveSelection saveScrollerOffset |
	saveSelection := self selectionInterval copy.
	saveScrollerOffset := scroller offset copy.
	(self canDiscardEdits and: [(self hasProperty: #alwaysAccept) not]) 
		ifTrue: [^self flash].
	self hasEditingConflicts 
		ifTrue: 
			[(self 
				confirm: 'Caution!! This method may have been
changed elsewhere since you started
editing it here.  Accept anyway?' 
						translated) 
					ifFalse: [^self flash]].
	textToAccept := textMorph asText.
	ok := setTextSelector isNil or: 
					[setTextSelector numArgs = 2 
						ifTrue: 
							[model 
								perform: setTextSelector
								with: textToAccept
								with: self]
						ifFalse: [model perform: setTextSelector with: textToAccept]].
	ok == true 
		ifTrue: 
			[self setText: self getText.
			self hasUnacceptedEdits: false.
			(model dependents detect: 
					[:dep | 
					(dep isKindOf: OldPluggableTextMorph) 
						and: [dep getTextSelector == #annotation]]
				ifNone: [nil]) ifNotNilDo: [:aPane | model changed: #annotation]].

	"sps 8/13/2001 22:41: restore selection and scroll info"
	
	["During the step for the browser, updateCodePaneIfNeeded is called, and 
		invariably resets the contents of the codeholding PluggableTextMorph
		at that time, resetting the cursor position and scroller in the process.
		The following line forces that update without waiting for the step, 		then restores the cursor and scrollbar"

	ok 
		ifTrue: 
			["(don't bother if there was an error during compile)"

			(model isKindOf: CodeHolder) ifTrue: [model updateCodePaneIfNeeded].
			"jmv - moved this outside the deferred message.
			See 'Re: [squeak-dev] scrambled input fields'
			from Gary Chambers on Nov 14, 2008."
			self selectFrom: saveSelection first to: saveSelection last.
			OldWorldState addDeferredUIMessage: 
					[self currentHand newKeyboardFocus: textMorph.
					scroller offset: saveScrollerOffset.
					self setScrollDeltas.
					"self selectFrom: saveSelection first to: saveSelection last"]]] 
			on: Error
			do: []! !


!OldSimpleHierarchicalListMorph methodsFor: 'event handling' stamp: 'jmv 11/18/2008 13:53'!
handlesKeyboard

	^self visible! !


!OldTextMorph methodsFor: 'event handling' stamp: 'jmv 11/18/2008 13:53'!
handlesKeyboard

	^self visible! !


!SimpleEditor methodsFor: 'testing' stamp: 'jmv 11/17/2008 17:01'!
isAtEnd
	^pointIndex = (string size + 1)! !

!SimpleEditor methodsFor: 'testing' stamp: 'jmv 11/17/2008 17:01'!
isAtStart
	^pointIndex = 1! !


!SliderLW methodsFor: 'events-processing' stamp: 'jmv 11/18/2008 13:54'!
handlesKeyboard

	^self visible! !

EntryField2LW removeSelector: #caretWidth!
!classDefinition: #EntryField2LW category: #'LightWidgets-Kernel'!
LightWidget subclass: #EntryField2LW
	instanceVariableNames: 'font contents editor foreColor backColor selectedForeColor selectedBackColor crAction'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'LightWidgets-Kernel'!

!EntryField2LW reorganize!
('accessing' backColor backColor: crAction: editor font: foreColor foreColor: insertionPointColor installEditorToReplace: selectedBackColor: selectedForeColor: selectionColor updateFromContents)
('drawing' characterIndexAtPoint: drawCaretOn: drawOn: drawSelectionOn:)
('editing' handleInteraction:fromEvent:)
('event handling' handlesKeyboard handlesMouseDown: keyStroke: keyboardFocusChange: mouseDown: mouseMove:)
('initialization' initialize)
('testing' hasCaret hasSelection)
('unaccepted edits' hasUnacceptedEdits:)
('updating' modelChanged)
!

CheckBoxLW removeSelector: #hasUnacceptedEdits:!

!CheckBoxLW reorganize!
('initialization' initialize)
('accessing' backColor backColor: font: foreColor foreColor: label label: selectedBackColor: selectedForeColor:)
('drawing' drawOn:)
('event handling' keyStroke: mouseDown: mouseUp:)
('events-processing' handlesKeyboard handlesMouseDown:)
('updating' modelChanged)
!

