'From Squeak6.0alpha of 30 December 2021 [latest update: #20921] on 30 December 2021 at 2:25:07 pm'!
Form subclass: #DisplayScreen
	instanceVariableNames: 'clippingBox extraRegions '
	classVariableNames: 'DeferringUpdates DisplayChangeSignature DisplayIsFullScreen PlatformScaleFactor RelativeScaleFactorEnabled '
	poolDictionaries: ''
	category: 'Graphics-Display Objects'!
Morph subclass: #PreferenceWizardMorph
	instanceVariableNames: 'previewWorld titleMorph buttonRowMorph controlMorph startButton previousButton nextButton pages currentPageIndex pagesLabel skipButton isFullScreen lowPerformanceMorph checkmark doneButton radiomark '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'PreferenceBrowser'!

!Controller methodsFor: 'basic control sequence' stamp: 'mt 12/23/2021 11:18'!
interActivityPause
	"if we are looping quickly, insert a short delay.  Thus if we are just doing UI stuff, we won't take up much CPU"
	| currentTime wait |
	MinActivityLapse ifNotNil: [
		lastActivityTime ifNotNil: [ 
			currentTime := Time millisecondClockValue.
			wait := lastActivityTime + MinActivityLapse - currentTime.
			wait > 0 ifTrue: [ 
				wait <= MinActivityLapse  "big waits happen after a snapshot"
					ifTrue: [DisplayScreen checkForNewScreenScaleFactor; checkForNewScreenSize.
							(Delay forMilliseconds: wait) wait ]. ]. ]. ].

	lastActivityTime := Time millisecondClockValue.! !


!DisplayScreen methodsFor: 'scale factor' stamp: 'mt 12/29/2021 21:11'!
currentScaleError
	"Documentation and debugging only. The scale error originates in rounding errors while rendering the standard TTCFont font into pixels or using a pre-rendered StrikeFont in the first place.
	
	Display currentScaleError
	"
	
	^ RealEstateAgent scaleFactor - self uiScaleFactor
	
"
| errors current |
errors := OrderedDictionary new.
current := Display uiScaleFactor.
1.0 to: 3.0 by: 0.25 do: [:s |
	Display uiScaleFactor: s.
	errors at: s put: Display currentScaleError].
Display uiScaleFactor: current.
errors explore.
"! !

!DisplayScreen methodsFor: 'scale factor' stamp: 'mt 12/30/2021 10:30'!
platformScaleFactor
	"Answers the platform's (and thus monitor's) current scale factor as last reported via VM primitive. See #checkForNewScreenScaleFactor."

	^ PlatformScaleFactor ifNil: [1.0 "Primitive not ready."]! !

!DisplayScreen methodsFor: 'scale factor' stamp: 'mt 12/30/2021 12:38'!
platformScaleFactor: aFloatOrNil
	"Report a new scale factor from the platform to the image. This can happen if you move Squeak's window between monitors with different pixels-per-inch. On some platforms, you can also set a scale factor independent of monitor PPI. Note that the user might have scaled the image regardless of the previous platform scale factor."

	| old new |
	aFloatOrNil ifNil: [
		"Ignore. Primitive not ready (anymore)."
		PlatformScaleFactor := nil.
		^ self].
	PlatformScaleFactor ifNil: [
		"First time. Ignore. Assume that the user scaled manually until now."
		PlatformScaleFactor := aFloatOrNil.
		^ self].
	
	(old := self platformScaleFactor) = (new := aFloatOrNil) ifTrue: [^ self].
	PlatformScaleFactor := new.
	self uiScaleFactor: self uiScaleFactor * (new/old).! !

!DisplayScreen methodsFor: 'scale factor' stamp: 'mt 12/30/2021 12:45'!
platformScaleFactorKnown
	"Tools can help users understand whether Squeak will adjust the scale factor automatically or whether they have to scale manually. See class-side's #actualScreenScaleFactor and also #relativeUiScaleFactor."

	^ PlatformScaleFactor notNil! !

!DisplayScreen methodsFor: 'scale factor' stamp: 'mt 12/23/2021 14:40'!
relativeUiScaleFactor
	"Answers the scale factor as perceived by the user. Note that this concept might be platform-dependent. On Windows, for example, 100% means pixel-perfect while on macOS 100% means as-the-monitor-demands. So, Retina displays are effectively scaled even if the user sees 100% in a Choose-Your-Scale dialog."
	
	^ self class relativeScaleFactorEnabled
		ifTrue: [ "macOS" self uiScaleFactor / self platformScaleFactor ]
		ifFalse: [ "Windows" self uiScaleFactor ]! !

!DisplayScreen methodsFor: 'scale factor' stamp: 'mt 12/23/2021 14:39'!
relativeUiScaleFactor: aFloat
	
	^ self class relativeScaleFactorEnabled
		ifTrue: [ "macOS" self uiScaleFactor: aFloat * self platformScaleFactor ]
		ifFalse: [ "Windows" self uiScaleFactor: aFloat ]! !

!DisplayScreen methodsFor: 'scale factor' stamp: 'mt 12/30/2021 12:46'!
uiScaleFactor
	"Answers the current scale factor used to configure all widgets, tools, or windows to be prepared for the current rendering system, i.e., BitBlt. Note that 1.0 means 'pixel perfect'."
	
	^ UserInterfaceTheme current isTTCBased
		ifTrue: [TextStyle pixelsPerInch / 96.0 "Hide rounding errors in TTCFont >> #height."]
		ifFalse: [RealEstateAgent scaleFactor roundTo: 0.25 "Force 25% steps. See, e.g., #doScale150."].! !

!DisplayScreen methodsFor: 'scale factor' stamp: 'mt 12/29/2021 21:17'!
uiScaleFactor: aFloat
	"Sets the effective scale factor for the user interface, i.e., all widgets, tools, and windows. The user can override the CurrentScaleFactor recommended by the platform."

	| oldFactor newFactor |
	(UserInterfaceTheme current canFakeScaleFactor: aFloat) ifTrue: [
		self flag: #isTTCBased.
		^ UserInterfaceTheme current applyScaled: aFloat].
	
	oldFactor := RealEstateAgent scaleFactor. "Use effective, pixel-based factor to account for rounding errors. See #isTTCBased and #uiScaleFactor."
	newFactor := aFloat max: 1.0.
	newFactor = oldFactor ifTrue: [^ self].
	
	TextStyle pixelsPerInch: 96.0 * aFloat.
	newFactor := RealEstateAgent resetScaleFactor; scaleFactor. "Again, account for rounding errors."
	Project current ifNotNil: [:p | p displayScaleChangedFrom: oldFactor to: newFactor].! !


!DisplayScreen class methodsFor: 'display box access' stamp: 'mt 12/23/2021 15:00'!
checkForNewScreenScaleFactor
	"Check whether the platform's scale factor has changed and if so take appropriate actions"

	Display platformScaleFactor: DisplayScreen actualScreenScaleFactor.! !

!DisplayScreen class methodsFor: 'snapshots' stamp: 'mt 12/30/2021 12:48'!
actualScreenScaleFactor
	"<primitive: #primitiveScreenScaleFactor>"
	"Once the primitive is ready, you can simply uncomment it. The system is prepared for changes from 'nil' to actual factors and back."

	^ nil "unknown -- do not default to 1.0 here"! !

!DisplayScreen class methodsFor: 'preferences' stamp: 'mt 12/23/2021 15:08'!
relativeScaleFactorEnabled
	<preference: 'Show Relative Scale Factor'
		categoryList: #(Morphic Tools visuals)
		description: 'When true, 100% means as-the-platform/monitor-demands, which is typical for macOS. When false, 100% means pixel-perfect, which is typical for Windows.'
		type: #Boolean>

	"Note that we set the default to 'false' because pixels are very prominent in the Morphic programming model. So it makes sense to communcate this kind of pixel scaling openly and thus not hide the #platformScaleFactor from the user."
	^ RelativeScaleFactorEnabled ifNil: [false].! !

!DisplayScreen class methodsFor: 'preferences' stamp: 'mt 12/23/2021 14:32'!
relativeScaleFactorEnabled: aBoolean

	RelativeScaleFactorEnabled := aBoolean.! !


!PreferenceWizardMorph methodsFor: 'actions' stamp: 'mt 2/18/2020 09:04'!
installExtraPackages
	"Removes the buttons and adds the progress bar during installation."
	
	| steps page |
	self removeProperty: #checkInternet. "No frequent checks for connectivity from here."
	
	steps := #(
		InstallLatestUpdates
		InstallMetacello
		InstallRefactoringTools
		InstallAutoComplete
		InstallGitInfrastructure
		InstallFFI
		InstallOSProcess )
			select: [:ea | self perform: ('state', ea) asSymbol].
	
	page := controlMorph firstSubmorph.

	page submorphs second hide. "question"
	page submorphs last delete. "url"
	page submorphs last delete. "no button"
	page submorphs last delete. "yes button"
	page submorphs last delete. "package list"
	
	self refreshWorld.
	
	[
		PreferenceWizardProgressMorph install.
		page
			addMorphBack: PreferenceWizardProgressMorph uniqueInstance;
			addMorphBack: self createVerticalSpacer.
			
		steps
			do: [:step | self perform: step withFirstCharacterDownshifted asSymbol]
			displayingProgress: [:step | String streamContents: [:s |
				step findFeatureIndicesDo: [:start :end |
					s nextPutAll: (step copyFrom: start to: end); space].
				s nextPutAll: '...']].
	] ensure: [
		PreferenceWizardProgressMorph reset.
		self showSqueak].! !

!PreferenceWizardMorph methodsFor: 'actions' stamp: 'mt 12/29/2021 09:34'!
showPlayfield

	previewWorld ifNil: [self initializePlayfield].

	startButton hide.
	skipButton hide.
	lowPerformanceMorph hide.
	isFullScreen := true.
	self step.
	
	titleMorph layoutFrame: (LayoutFrame fractions: (0 @ 0 corner: 1 @ 0) offsets: (0@ 0 corner: 0 @ titleMorph height)).
	
	self refreshWorld.

	controlMorph show.
	previewWorld show.
	buttonRowMorph show.

	self next.
	self refreshWorld.
	
	! !

!PreferenceWizardMorph methodsFor: 'initialization - building' stamp: 'mt 12/27/2021 07:55'!
createButton

	^ PluggableButtonMorphPlus new
		setProperty: #noUserInterfaceTheme toValue: true;
		offColor: (self defaultColor adjustBrightness: 0.2);
		feedbackColor: (self defaultColor adjustBrightness: 0.4);
		model: self;
		font: (UserInterfaceTheme current get: #wizardButtonFont);
		textColor: self defaultTextColor;
		borderColor: self defaultTextColor;
		instVarNamed: #borderColor put: self defaultTextColor; "HACK!!"
		borderWidth: (2 * RealEstateAgent scaleFactor) truncated;
		cornerStyle: (self hasLowPerformance ifTrue: [#square] ifFalse: [#rounded]);
		vResizing: #shrinkWrap;
		hResizing: #shrinkWrap;
		layoutInset: self defaultButtonMargins;
		yourself! !

!PreferenceWizardMorph methodsFor: 'initialization - building' stamp: 'mt 12/29/2021 10:26'!
createCheckbox: label for: selector help: terms

	| box lbl btn |
	
	btn := self createButton
		layoutInset: 0;
		label: ' ';
		onColor: (self defaultColor adjustBrightness: 0.3) offColor: (self defaultColor adjustBrightness: 0.3);
		vResizing: #rigid;
		hResizing: #rigid;
		action: ('toggle', selector) asSymbol;
		getStateSelector: ('state', selector) asSymbol;
		getLabelSelector: ('label', selector) asSymbol;
		extent: (TextStyle defaultFont height * 1.75) asPoint.

	lbl := self createLabel: label color: self defaultTextColor.
	lbl hResizing: #spaceFill.
	
	box := Morph new
		setProperty: #isCheckbox toValue: true;
		color: Color transparent;
		changeTableLayout;
		listDirection: #leftToRight;
		cellPositioning: #topLeft;
		hResizing: #spaceFill;
		vResizing: #shrinkWrap;
		rubberBandCells: true;
		cellGap: (TextStyle defaultFont widthOf: $x);
		yourself.
		
	box addAllMorphs: {btn. lbl}.
	self
		setBalloonText: (terms isString ifTrue: [terms] ifFalse: [self findHelpStringFor: terms])
		for: box.
	^ box! !

!PreferenceWizardMorph methodsFor: 'initialization - building' stamp: 'mt 12/30/2021 10:40'!
createLabel: aString

	^ self createLabel: aString color: (self defaultTextColor adjustBrightness: -0.15)! !

!PreferenceWizardMorph methodsFor: 'initialization - building' stamp: 'mt 12/27/2021 07:46'!
createLabel: aString color: aColor

	| lbl |
	lbl := TextMorph new hResizing: #spaceFill; vResizing: #shrinkWrap.
	lbl newContents:aString.
	lbl text
		addAttribute: (TextColor color: aColor);
		addAttribute: (TextFontReference toFont: ((UserInterfaceTheme current get: #wizardStandardFont))).
	lbl margins: self defaultTextMargins.
	lbl lock.
	^ lbl! !

!PreferenceWizardMorph methodsFor: 'initialization - building' stamp: 'mt 12/27/2021 08:18'!
createPage

	^ Morph new
		color: Color transparent;
		hResizing: #spaceFill;
		vResizing: #spaceFill;
		changeTableLayout;
		listDirection: #topToBottom;
		cellPositioning: #topLeft;
		layoutInset: (self layoutInset asPoint corner: self cellGap@0);
		cellGap: self cellGap;
		yourself! !

!PreferenceWizardMorph methodsFor: 'initialization - building' stamp: 'mt 12/29/2021 08:45'!
createRadioButton: label for: selector argument: object

	^ self createRadioButton: label for: selector argument: object help: #()! !

!PreferenceWizardMorph methodsFor: 'initialization - building' stamp: 'mt 12/29/2021 10:26'!
createRadioButton: label for: selector argument: object help: terms

	| box lbl btn suffix |
	suffix := ((object respondsTo: #name)
		ifTrue: [object name]
		ifFalse: [object asString]) asLegalSelector.

	btn := self createButton
		layoutInset: 0;
		label: ' ';
		onColor: (self defaultColor adjustBrightness: 0.3) offColor: (self defaultColor adjustBrightness: 0.3);
		vResizing: #rigid;
		hResizing: #rigid;
		actionSelector: ('choose', selector, ':') asSymbol;
		arguments: {object};
		getStateSelector: ('state', selector, suffix) asSymbol;
		getLabelSelector: ('radio', selector, suffix) asSymbol;
		extent: (TextStyle defaultFont height * 1.75) asPoint.
		
	lbl := self createLabel: label color: self defaultTextColor.
	lbl hResizing: #spaceFill.
	
	box := Morph new
		setProperty: #isRadioButton toValue: true;
		color: Color transparent;
		changeTableLayout;
		listDirection: #leftToRight;
		cellPositioning: #topLeft;
		hResizing: #spaceFill;
		vResizing: #shrinkWrap;
		rubberBandCells: true;
		cellGap: (TextStyle defaultFont widthOf: $x);
		yourself.
		
	box addAllMorphs: {btn. lbl}.
	self
		setBalloonText: (terms isString ifTrue: [terms] ifFalse: [self findHelpStringFor: terms])
		for: box.
	^ box! !

!PreferenceWizardMorph methodsFor: 'initialization - building' stamp: 'mt 12/27/2021 08:19'!
createScrollPane

	| pane |
	pane := ScrollPane new
		setProperty: #noUserInterfaceTheme toValue: true;
		hScrollBarPolicy: #never;
		vScrollBarPolicy: #whenNeeded;
		borderWidth: 0;
		color: Color transparent;
		scrollBarThickness: self layoutInset;
		yourself.
		
	pane
		hResizing: #spaceFill;
		vResizing: #spaceFill.
	
	pane scroller changeTableLayout.
	pane scroller addMorph: (Morph new
		changeTableLayout;
		color: Color transparent;
		hResizing: #spaceFill;
		vResizing: #shrinkWrap;
		cellGap: self cellGap;
		layoutInset: (0@0 corner: self cellGap@0);
		yourself).
	
	pane vScrollBar
		setProperty: #noUserInterfaceTheme toValue: true;
		sliderColor: Color white.
	(pane vScrollBar instVarNamed: #slider) 
		cornerStyle: (self hasLowPerformance ifTrue: [#square] ifFalse: [#rounded]);
		borderWidth: (2 * RealEstateAgent scaleFactor) truncated.
	(pane vScrollBar instVarNamed: #pagingArea) 
		cornerStyle: (self hasLowPerformance ifTrue: [#square] ifFalse: [#rounded]).	
			
	^ pane! !

!PreferenceWizardMorph methodsFor: 'initialization - playfield' stamp: 'mt 12/29/2021 10:09'!
initializeButtons

	buttonRowMorph := Morph new
		color: Color transparent;
		changeTableLayout;
		listDirection: #leftToRight;
		cellGap: self cellGap;
		layoutInset: (0@self layoutInset corner: 0@0);
		vResizing: #shrinkWrap;
		hResizing: #spaceFill;
		yourself.
		
	buttonRowMorph addAllMorphs: {
		previousButton := self createButton action: #previous; label: 'Previous' translated.
		pagesLabel := (self createLabel: '0 / 0') hResizing: #shrinkWrap; margins: (self layoutInset@0 corner: self layoutInset@0); fullBounds; yourself.
		nextButton := self createButton action: #next; label: 'Next' translated.
		self createHorizontalSpacer.
		doneButton := self createButton action: #accept; label: 'Done' translated}.
	
	(previousButton width max: nextButton width) in: [:w |
		previousButton hResizing: #rigid; width: w.
		nextButton hResizing: #rigid; width: w].
	
	buttonRowMorph fullBounds.
	buttonRowMorph layoutFrame: (LayoutFrame fractions: (0 @ 1 corner: 1 @ 1) offsets: (0@ buttonRowMorph height negated corner: 0 @ 0)).! !

!PreferenceWizardMorph methodsFor: 'initialization - playfield' stamp: 'mt 12/29/2021 11:27'!
initializeControlMorph

	controlMorph := Morph new
		color: Color transparent;
		changeTableLayout;
		listDirection: #topToBottom;
		hResizing: #spaceFill;
		vResizing: #spaceFill;
		layoutInset: (0@0 corner: self cellGap@0);
		layoutFrame: (LayoutFrame fractions: (0.0 @ 0 corner: 0.35 @ 1.0) offsets: (0@ titleMorph height corner: 0 @ buttonRowMorph height negated));
		yourself.
	
	controlMorph addMorph: (self createLabel: 'Please take a few minutes and configure the look-and-feel of the environment. You can always adjust these settings later. You can see the effects of these settings in the live and editable windows to the right.' translated).! !

!PreferenceWizardMorph methodsFor: 'initialization - playfield' stamp: 'mt 12/29/2021 08:35'!
initializePages

	pages := OrderedCollection new.
	currentPageIndex := 0.

	self
		initializePage00ScaleFactor;
		initializePage01Themes;
		initializePage02Visuals;
		initializePage03Interaction;
		initializePage04InteractionMore;
		initializePage05Tools.! !

!PreferenceWizardMorph methodsFor: 'initialization - playfield' stamp: 'mt 12/29/2021 21:52'!
initializePreviewWorld

	Preferences enable: #systemWindowEmbedOK.

	previewWorld := PasteUpMorph new
		hResizing: #spaceFill;
		vResizing: #spaceFill;
		viewBox: (0@0 corner: 500@500);
		layoutFrame: (LayoutFrame fractions: (0.35 @ 0 corner: 1.0 @ 1.0) offsets: (0@ titleMorph height corner: 0 @ buttonRowMorph height negated));
		fillStyle: Project current world fillStyle;
		borderWidth: (2 * RealEstateAgent scaleFactor) truncated;
		borderColor: Color white;
		cornerStyle: (self hasLowPerformance ifTrue: [#square] ifFalse: [#rounded]);
		yourself.
	
	self
		addOrReplaceBrowser;
		addOrReplaceSenders;
		addOrReplaceWorkspace;
		updateWindowBounds.! !

!PreferenceWizardMorph methodsFor: 'initialization' stamp: 'mt 12/27/2021 07:40'!
checkmark

	^ checkmark ifNil: [checkmark := (((ToolIcons iconNamed: #checkmark) dyed: Color white) scaledToSize: (TextStyle defaultFont height * 1.25) asPoint) asMorph]! !

!PreferenceWizardMorph methodsFor: 'initialization' stamp: 'mt 12/28/2021 08:12'!
defaultButtonMargins

	| w h |
	w := (self defaultFont widthOf: $x) * 2.
	h := self defaultFont height // 2.
	^ w@h corner: w@h! !

!PreferenceWizardMorph methodsFor: 'initialization' stamp: 'mt 12/29/2021 10:38'!
defaultExtent

	^ 1024@768! !

!PreferenceWizardMorph methodsFor: 'initialization' stamp: 'mt 12/28/2021 07:36'!
defaultFont

	^ UserInterfaceTheme current get: #wizardStandardFont! !

!PreferenceWizardMorph methodsFor: 'initialization' stamp: 'mt 12/28/2021 07:41'!
defaultTextMargins

	| w h |
	w := self defaultFont widthOf: $x.
	h := self defaultFont height.
	^ 0@(h//8) corner: w@(h//4)! !

!PreferenceWizardMorph methodsFor: 'initialization' stamp: 'mt 12/28/2021 08:03'!
initialize

	super initialize.
	
	isFullScreen := false.

	self hasLowPerformance
		ifTrue: [self color: self defaultColor]
		ifFalse: [self color: (self defaultColor alpha: 0.75)].
		
	self setProperty: #indicateKeyboardFocus toValue: #never.
	
	self
		changeProportionalLayout;
		layoutInset: (self defaultFont widthOf: $x) * 2;
		cellGap: (self defaultFont widthOf: $x);
		cellPositioning: #center;
		disableLayout: true;
		morphicLayerNumber: self class dialogLayer + 1.
				
	self addKeyboardCaptureFilter: self.! !

!PreferenceWizardMorph methodsFor: 'initialization' stamp: 'mt 12/28/2021 08:06'!
initializeWelcome

	titleMorph := ('Welcome to Squeak' translated asText
		addAttribute: (TextColor color: self defaultTextColor);
		addAttribute: (TextFontReference toFont: (UserInterfaceTheme current get: #wizardTitleFont));
		yourself) asMorph lock.
	titleMorph margins: (self cellGap @ 0 corner: self cellGap @ self cellGap).
	titleMorph layoutFrame: (LayoutFrame fractions: (0 @ 0 corner: 1 @ 0) offsets: (0@ 0 corner: 0 @ titleMorph height)).

	startButton := (self createButton action: #showPlayfield; label: 'Configure' translated).
	skipButton := (self createButton action: #showSqueak; label: 'Skip' translated).
	
	(startButton width max: skipButton width) in: [:w |
		startButton hResizing: #rigid; width: w.
		skipButton hResizing: #rigid; width: w.
		
		startButton layoutFrame: (LayoutFrame fractions: (0.5 @ 0.6 corner: 0.5 @ 0.6) offsets: (2*w negated @ 0 corner: 0 @ 0)).
		skipButton layoutFrame: (LayoutFrame fractions: (0.5 @ 0.6 corner: 0.5 @ 0.6) offsets: (0@ 0 corner: 2*w @ 0))].
	
	lowPerformanceMorph := TextMorph new lock.
	
	self addAllMorphs: {titleMorph. startButton. skipButton. lowPerformanceMorph}.! !

!PreferenceWizardMorph methodsFor: 'initialization' stamp: 'mt 8/17/2016 21:05'!
openInWorld

	super openInWorld.
	
	self step.
	
	self world activeHand
		newKeyboardFocus: self;
		newMouseFocus: self.
		
	self showWelcome.! !

!PreferenceWizardMorph methodsFor: 'initialization' stamp: 'mt 12/29/2021 09:19'!
radiomark

	^ radiomark ifNil: [radiomark := Morph new color: Color white; extent: (TextStyle defaultFont height * 0.8) asPoint]! !

!PreferenceWizardMorph methodsFor: 'support' stamp: 'mt 12/29/2021 10:03'!
setBalloonText: string for: morph

	string ifEmpty: [^morph balloonText: nil].

	morph
		balloonColor: ((self defaultColor alpha: self color alpha) adjustBrightness: 0.2);
		balloonText: (string asText
			addAttribute: (TextFontReference toFont: (UserInterfaceTheme current get: #wizardHelpFont));
			addAttribute: (TextColor color: Color banana)).! !

!PreferenceWizardMorph methodsFor: 'initialization - pages' stamp: 'mt 12/30/2021 12:43'!
initializePage00ScaleFactor

	| currentPage pane helper |
	currentPage := pages add: self createPage.
	pane := self createScrollPane.
	
	currentPage addMorphBack: (self createLabel: 'Choose a scale factor' translated color: Color white).
	currentPage addMorphBack: pane.
	
	helper := MenuMorph new.
	TheWorldMainDockingBar instance scaleFactorsOn: helper.
	
	helper items allButLast do: [:item |
		pane scroller firstSubmorph addMorphBack: (self
			createRadioButton: item contents
			for: #ScaleFactor
			argument: item arguments first * 100)].

	Display platformScaleFactorKnown ifFalse: [
		currentPage addMorphBack: (self createLabel: 'Note that the recommended scale factor for your platform and display is unknown. Please adjust manually.' translated color: Color banana)].! !

!PreferenceWizardMorph methodsFor: 'initialization - pages' stamp: 'mt 12/30/2021 11:04'!
initializePage01Themes

	| currentPage pane |
	currentPage := pages add: self createPage.
	pane := self createScrollPane.
	
	currentPage addMorphBack: (self createLabel: 'Choose a theme' color: Color white).
	currentPage addMorphBack: pane.
	
	((UserInterfaceTheme allThemes
		select: [:uit | uit isGenuine])
		sorted: [:a :b | a name <= b name])
			do: [:ea |
			pane scroller firstSubmorph addMorphBack: (self
				createRadioButton: ea name
				for: #Theme
				argument: ea)].

	currentPage addMorphBack: (self createLabel: 'Note that "Colorful windows" show colors that fit the current theme. See next page.' translated color: Color banana)! !

!PreferenceWizardMorph methodsFor: 'initialization - pages' stamp: 'mt 12/29/2021 09:36'!
initializePage99ExtraPackages
	"Let the user install extra packages."

	| currentPage packagesList installButton |
	currentPage := self createPage.
	currentPage
		cellPositioning: #topCenter;
		addMorphBack: self createHorizontalSpacer;
		addMorphBack: ((self createLabel: 'Do you want to install extra packages?' color: Color white)
			hResizing: #shrinkWrap;
			yourself);
		addMorphBack: ((self createLabel: 'Note that the installation process requires a network connection with Internet access and might take several minutes.' color: (Color gray: 0.9))
			hResizing: #rigid;
			vResizing: #shrinkWrap;
			width: (self defaultFont widthOf: $x) * 55;
			yourself).
	
	currentPage submorphs last text addAttribute: TextAlignment centered.
	currentPage submorphs last layoutChanged.
	
	currentPage addMorphBack: (self createVerticalSpace height: self layoutInset).
	
	packagesList := self createScrollPane.
	packagesList
		width: (self defaultFont widthOf: $x) * 40;
		hResizing: #rigid;
		vResizing: #spaceFill.

	packagesList scroller firstSubmorph addAllMorphsBack: {
		self createCheckbox: 'Latest system updates' translated for: #InstallLatestUpdates help: 'Install the latest patches for ' translated, SystemVersion current version.
		self createCheckbox: 'Refactoring support in code browsers' translated for: #InstallRefactoringTools help: 'Refactoring is a process of re-writing or re-organizing text or code. The purpose of a refactor is to make the code or text more understandable and readable while exactly preserving its meaning and behavior.' translated.
		self createCheckbox: 'Autocomplete in code editors' translated for: #InstallAutoComplete help: 'Package that provides interactive, context-sensitive auto-completion for Squeak.' translated.
		self createCheckbox: 'Git support and browser' translated for: #InstallGitInfrastructure help: 'From the Git Browser, you can create new commits, synchronize with remote repositories (fetch, pull, push), manage and merge branches, switch between them, and compare different versions.' translated.
		self createCheckbox: 'Foreign function interface (FFI)' translated for: #InstallFFI help: 'FFI, the Squeak Foreign Function Interface, is used to call functions located in shared libraries that are not part of the Squeak VM nor its plugins' translated.
		self createCheckbox: 'Access OS functions' translated for: #InstallOSProcess help: 'OSProcess provides access to operating system functions, including pipes and child process creation.' translated.
	}.
		
	currentPage addMorphBack: packagesList.

	currentPage addMorphBack: ((self createLabel: 'Find more on www.squeak.org/projects' color: (Color gray: 0.9))
		hResizing: #shrinkWrap; yourself).
	
	installButton := (self createButton action: #installExtraPackages).
	currentPage addMorphBack: installButton.
	currentPage addMorphBack: (self createButton action: #showSqueak; label: 'No, maybe later.' translated).
	
	self setProperty: #checkInternet toValue: true.
	self checkInternetOn: installButton.
	
	^ currentPage! !

!PreferenceWizardMorph methodsFor: 'display scale' stamp: 'mt 12/30/2021 11:00'!
updateFromChangedScaleFactor

	previewWorld delete.
	previewWorld := nil.
	DisplayScreen displayIsFullScreen ifFalse: [
		DisplayScreen setNewScreenSize: (self defaultExtent * RealEstateAgent scaleFactor) rounded].

	checkmark := nil.
	radiomark := nil.
	
	self
		layoutInset: (self defaultFont widthOf: $x) * 2;
		cellGap: (self defaultFont widthOf: $x).
		
	titleMorph
		font: (UserInterfaceTheme current get: #wizardTitleFont);
		margins: (self cellGap @ 0 corner: self cellGap @ self cellGap).
	titleMorph layoutFrame
		bottomOffset: titleMorph height.
	
	self updateLowPerformanceLabel: lowPerformanceMorph contents.
	
	"buttons"
	{startButton. skipButton. previousButton. nextButton. doneButton},
		(pages gather: [:page | page allMorphs select: [:ea | ea isButton]])
			do: [:button |
				((button owner hasProperty: #isRadioButton)
					or: [button owner hasProperty: #isCheckbox])
						ifTrue: [
							button
								"layoutInset: 0;"
								extent: (TextStyle defaultFont height * 1.75) asPoint;
								update: button getLabelSelector.
							button owner cellGap: (TextStyle defaultFont widthOf: $x)]
						ifFalse: [
							button
								layoutInset: self defaultButtonMargins].
				button
					borderWidth: (2 * RealEstateAgent scaleFactor) truncated;
					font: (UserInterfaceTheme current get: #wizardButtonFont);
					updateMinimumExtent "Font might not change but PPI did."].
		
	self fullBounds.
		
	(startButton minimumWidth max: skipButton minimumWidth) in: [:w |
		startButton hResizing: #rigid; width: w.
		skipButton hResizing: #rigid; width: w.
		startButton layoutFrame leftOffset: 2*w negated.
		skipButton layoutFrame rightOffset: 2*w].

	(previousButton minimumWidth max: nextButton minimumWidth) in: [:w |
		previousButton hResizing: #rigid; width: w.
		nextButton hResizing: #rigid; width: w].
	pagesLabel
		margins: (self layoutInset@0 corner: self layoutInset@0);
		font: (UserInterfaceTheme current get: #wizardStandardFont).
	buttonRowMorph
		cellGap: self cellGap;
		layoutInset: (0@self layoutInset corner: 0@0).
	buttonRowMorph layoutFrame
		topOffset: buttonRowMorph fullBounds height negated.
	
	"labels"
	{controlMorph firstSubmorph}, (pages gather: [:page | page allMorphs select: [:ea | ea isTextMorph]])
		do: [:label |
			label
				font: (UserInterfaceTheme current get: #wizardStandardFont);
				margins: self defaultTextMargins
			"No need for #releaseParagraph because window resizing will happen anyway."].
	
	"controlMorph"
	controlMorph layoutInset: (0@0 corner: self cellGap@0).
	controlMorph layoutFrame
		topOffset: titleMorph height;
		bottomOffset: buttonRowMorph height negated.
	
	"scroll panes in pages"
	pages do: [:page | | scrollPane |
		page
			layoutInset: (self layoutInset asPoint corner: self cellGap@0);
			cellGap: self cellGap.
		scrollPane := page submorphs second.
		scrollPane scrollBarThickness: self layoutInset.
		scrollPane scroller firstSubmorph
			cellGap: self cellGap;
			layoutInset: (0@0 corner: self cellGap@0).
		(scrollPane vScrollBar instVarNamed: #slider)
			borderWidth: (2 * RealEstateAgent scaleFactor) truncated].
	
	"previewWorld"
	self initializePreviewWorld.
	self addMorph: previewWorld.
	self step.
"	previewWorld borderWidth: (2 * RealEstateAgent scaleFactor) truncated.
	previewWorld layoutFrame
		topOffset: titleMorph height;
		bottomOffset: buttonRowMorph height negated.
"	! !

!PreferenceWizardMorph methodsFor: 'updating' stamp: 'mt 12/29/2021 09:10'!
changedRadio

	self dependents
		select: [:dep | dep respondsTo: #getLabelSelector]
		thenDo: [:button |
			button update: button getStateSelector.
			button update: button getLabelSelector].! !

!PreferenceWizardMorph methodsFor: 'layout' stamp: 'mt 12/29/2021 10:14'!
updateLowPerformanceLabel: string

	lowPerformanceMorph contentsAsIs: (string asText
		addAttribute: (TextColor color: (Color gray: 0.7));
		addAttribute: (TextFontReference toFont: (UserInterfaceTheme current get: #wizardHelpFont))).
		
	lowPerformanceMorph layoutFrame: (LayoutFrame fractions: (1 @ 1 corner: 1 @ 1) offsets: (lowPerformanceMorph fullBounds width negated @ lowPerformanceMorph fullBounds height negated corner: self layoutInset @ self layoutInset "Into margins")).
	
	self layoutChanged.! !

!PreferenceWizardMorph methodsFor: 'layout' stamp: 'mt 12/26/2021 15:36'!
updatePageLabel

	pagesLabel contentsAsIs: (('{1} / {2}' format: {currentPageIndex. pages size}) asText
		addAttribute: (TextColor color: (Color gray: 0.8));
		addAttribute: (TextFontReference toFont: (UserInterfaceTheme current get: #wizardStandardFont))).! !

!PreferenceWizardMorph methodsFor: 'layout' stamp: 'mt 12/29/2021 07:46'!
updateWindowBounds

	| area extentToUse pointsToUse |
	isFullScreen == false ifTrue: [^ self].
	previewWorld ifNil: [^ self].
	
	self fullBounds.

	area := previewWorld layoutBounds insetBy: self layoutInset.
	extentToUse := area extent * (0.8 @ 0.45).
	pointsToUse := {
		area topLeft.
		area rightCenter.
		area bottomCenter}.

	previewWorld submorphs reversed withIndexDo: [:window :i |
		window
			extent: extentToUse;
			center: (pointsToUse atWrap: i);
			bounds: (window bounds translatedToBeWithin: area)].! !

!PreferenceWizardMorph methodsFor: 'actions - radio' stamp: 'mt 12/29/2021 21:53'!
chooseScaleFactor: inPercent

	Display relativeUiScaleFactor: inPercent / 100.
	self changedRadio.
	Project current world
		noDisplayDuring: [self updateFromChangedScaleFactor].! !

!PreferenceWizardMorph methodsFor: 'actions - radio' stamp: 'mt 12/29/2021 09:11'!
chooseTheme: aTheme

	aTheme applyScaled.

	"The theme does not theme this fake world."
	previewWorld fillStyle: self world fillStyle.
	
	self changedRadio.! !

!PreferenceWizardMorph methodsFor: 'actions - radio' stamp: 'mt 12/29/2021 09:15'!
stateScaleFactor: key

	^ (Display relativeUiScaleFactor * 100) rounded asString asLegalSelector = key! !

!PreferenceWizardMorph methodsFor: 'actions - radio' stamp: 'mt 12/29/2021 09:04'!
stateTheme: key

	^ UserInterfaceTheme current name asLegalSelector = key! !

!PreferenceWizardMorph methodsFor: 'actions - buttons' stamp: 'mt 12/29/2021 09:03'!
doesNotUnderstand: msg

	(msg selector numArgs = 0 and: [msg selector beginsWith: 'label'])
		ifTrue: [^ (self perform: ('state', (msg selector allButFirst: 5)) asSymbol)
			ifTrue: [self checkmark]
			ifFalse: [' '] ].

	(msg selector numArgs = 0 and: [msg selector beginsWith: 'radio'])
		ifTrue: [^ (self perform: ('state', (msg selector allButFirst: 5)) asSymbol)
			ifTrue: [self radiomark]
			ifFalse: [' '] ].

	(msg selector numArgs = 0 and: [msg selector beginsWith: 'stateTheme'])
		ifTrue: [^ self stateTheme: (msg selector allButFirst: 10)].

	(msg selector numArgs = 0 and: [msg selector beginsWith: 'stateScaleFactor'])
		ifTrue: [^ self stateScaleFactor: (msg selector allButFirst: 16)].
		
	^ super doesNotUnderstand: msg! !

!PreferenceWizardMorph methodsFor: 'actions - buttons' stamp: 'mt 12/29/2021 07:59'!
toggleUseBiggerCursors

	Cursor useBiggerCursors: self stateUseBiggerCursors not.	
	self changed: #stateUseBiggerCursors.! !


!PreferenceWizardProgressMorph methodsFor: 'as yet unclassified' stamp: 'mt 12/28/2021 08:28'!
createProgressBar
	
	^ SystemProgressBarMorph new 
		extent: ((self defaultFont widthOf: $x) * 35) @ ((self defaultFont widthOf: $x) * 2);
		color: Color transparent;
		barColor: Color white;
		borderColor: Color white;
		borderWidth: (2 * RealEstateAgent scaleFactor) truncated;
		yourself
		! !

!PreferenceWizardProgressMorph methodsFor: 'as yet unclassified' stamp: 'mt 12/28/2021 08:26'!
defaultFont

	^ UserInterfaceTheme current get: #wizardStandardFont! !

!PreferenceWizardProgressMorph methodsFor: 'as yet unclassified' stamp: 'mt 12/28/2021 08:26'!
setDefaultParameters
	"change the receiver's appareance parameters"

	self
		color: Color transparent;
		borderWidth: 0;
		font: self defaultFont;
		textColor: Color white.! !


!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/23/2021 14:21'!
decreaseFontSize

	Display uiScaleFactor: Display uiScaleFactor - 0.25.! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/30/2021 14:23'!
fontConfigurationMenu: aMenu

	aMenu removeAllMorphs.
	aMenu defaultTarget: self.
	aMenu addTitle: 'Fonts' translated.
	aMenu addStayUpIcons.
	
	aMenu add: 'default text font...' translated action: #chooseSystemFont.
	aMenu lastItem font: Preferences standardSystemFont.
	aMenu balloonTextForLastItem: 'Choose the default font to be used for code and  in workspaces, transcripts, etc.' translated.
	
	aMenu add: 'default fixed font...' translated action: #chooseFixedFont.
	aMenu lastItem font: Preferences standardFixedFont.
	aMenu balloonTextForLastItem: 'Choose the default font to be used for text that needs fixed width characters for layouting etc.' translated.
	
	aMenu addLine.

	aMenu add: 'code font...' translated action: #chooseCodeFont. 
	aMenu lastItem font: Preferences standardCodeFont. 
	aMenu balloonTextForLastItem: 'Choose the font to be used in code panes.' translated.

	aMenu add: 'list font...' translated action: #chooseListFont.
	aMenu lastItem font: Preferences standardListFont.
	aMenu balloonTextForLastItem: 'Choose the font to be used in list panes' translated.

	aMenu add: 'menu font...' translated action: #chooseMenuFont.
	aMenu lastItem font: Preferences standardMenuFont.
	aMenu balloonTextForLastItem: 'Choose the font to be used in menus' translated.

	aMenu add: 'button font...' translated action: #chooseStandardButtonFont.
	aMenu lastItem font: Preferences standardButtonFont.
	aMenu balloonTextForLastItem: 'Choose the font to be used in buttons.' translated.

	aMenu add: 'balloon-help font...' translated action: #chooseBalloonHelpFont.
	aMenu lastItem font: Preferences standardBalloonHelpFont.
	aMenu balloonTextForLastItem: 'choose the font to be used when presenting balloon help.' translated.

	aMenu addLine.	

"	aMenu add: 'eToys font...' translated action: #chooseEToysFont.
	aMenu lastItem font: Preferences standardEToysFont.
	aMenu balloonTextForLastItem: 'Choose the font to be used on eToys environment' translated.

	aMenu add: 'eToys title font...' translated action: #chooseEToysTitleFont.
	aMenu lastItem font: Preferences standardEToysTitleFont.
	aMenu balloonTextForLastItem: 'Choose the font to be used in titles on eToys environment' translated.
"
	aMenu add: 'window-title font...' translated action: #chooseWindowTitleFont.
	aMenu lastItem font: Preferences windowTitleFont.
	aMenu balloonTextForLastItem: 'Choose the font to be used in window titles.' translated.

	aMenu add: 'halo-label font...' translated action: #chooseHaloLabelFont.
	aMenu lastItem font: Preferences standardHaloLabelFont.
	aMenu balloonTextForLastItem: 'Choose the font to be used on labels ih halo' translated.	

	aMenu add: 'flaps font...' translated action: #chooseFlapsFont.
	aMenu lastItem font: Preferences standardFlapFont.
	aMenu balloonTextForLastItem: 'Choose the font to be used on textual flap tabs' translated.


	aMenu addLine.
	aMenu addItem: [:item |
		item
			contents: 'set scale factor' translated;
			subMenuUpdater: TheWorldMainDockingBar instance
			selector: #scaleFactorsOn:].
	aMenu add: 'decrease font size (-)' translated action: #decreaseFontSize.
	aMenu balloonTextForLastItem: 'Decrease the current scale factor by 25% to make fonts look smaller' translated.
	aMenu add: 'increase font size (+)' translated action: #increaseFontSize.
	aMenu balloonTextForLastItem: 'Increase the current scale factor by 25% to make fonts look bigger' translated.

	aMenu addLine.
	aMenu add: 'restore default font choices' translated action: #restoreDefaultFonts.
	aMenu balloonTextForLastItem: 'Use the standard system font defaults' translated.
	
	aMenu add: 'print current font choices' translated action: #printStandardSystemFonts.
	aMenu balloonTextForLastItem: 'Print the standard system font defaults to the Transcript' translated.
	
	aMenu addLine.
	aMenu add: 'refresh this menu' translated target: self selector: #fontConfigurationMenu:  argument: aMenu.
	aMenu balloonTextForLastItem: 'Update this menu to reflect the current fonts' translated.
	MenuIcons decorateMenu: aMenu.
	^ aMenu! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/23/2021 14:20'!
increaseFontSize

	Display uiScaleFactor: Display uiScaleFactor + 0.25.! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/30/2021 11:35'!
restoreDefaultFonts
	"
	Preferences restoreDefaultFonts
	"
	
	TheWorldMainDockingBar instance resetAllThemes.! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/30/2021 13:13'!
setBalloonHelpFontTo: aFont

	UserInterfaceTheme setFont: #balloonHelpFont to: aFont.! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/29/2021 20:40'!
setButtonFontTo: aFont

	UserInterfaceTheme setFont: #standardButtonFont to: aFont.! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/29/2021 20:40'!
setCodeFontTo: aFont
	"Establish the code font."

	UserInterfaceTheme setFont: #standardCodeFont to: aFont.! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/30/2021 13:15'!
setDemoFonts
	"Originally, demo fonts where just bigger fonts to be used on a larger display such as a projector. By now, we treat demo fonts as being 50% larger than what the platform*s scale factor suggests.
	Preferences setDemoFonts
	"

	Display uiScaleFactor: Display platformScaleFactor * 1.5.! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/30/2021 13:16'!
setEToysFontTo: aFont 
	"change the font used in eToys environment"

	UserInterfaceTheme setFont: #eToysFont to: aFont.! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/30/2021 13:16'!
setEToysTitleFontTo: aFont 
	"change the font used in eToys environment"

	UserInterfaceTheme setFont: #eToysTitleFont to: aFont.! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/29/2021 20:40'!
setFixedFontTo: aFont

	UserInterfaceTheme setFixedFontTo: aFont.! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/29/2021 20:39'!
setFlapFontTo: aFont

	UserInterfaceTheme setFont: #standardFlapFont to: aFont.
	
	"FlapTab allSubInstancesDo:
		[:aFlapTab | aFlapTab reformatTextualTab]"! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/29/2021 16:09'!
setFlapsFontTo: aFont

	self setFlapFontTo: aFont.! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/29/2021 20:38'!
setHaloLabelFontTo: aFont 
	"change the font used in eToys environment"

	UserInterfaceTheme setFont: #haloLabelFont to: aFont.! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/29/2021 20:38'!
setListFontTo: aFont
	"Set the list font as indicated"

	UserInterfaceTheme setFont: #standardListFont to: aFont.
			
	"Smalltalk at: #ListParagraph ifPresent: [:lp | lp initialize].
	Smalltalk at: #Flaps ifPresent: [:flaps | flaps replaceToolsFlap]"! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/29/2021 20:38'!
setMenuFontTo: aFont

	UserInterfaceTheme setFont: #standardMenuFont to: aFont.
		
	"Smalltalk at: #PopUpMenu ifPresent:[:aClass| aClass setMenuFontTo: aFont].
	TheWorldMainDockingBar updateInstances."! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/30/2021 13:17'!
setPaintBoxButtonFontTo: aFont 
	"change the font used in the buttons in PaintBox. Etoys."

	UserInterfaceTheme setFont: #paintBoxButtonFont to: aFont.! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/29/2021 20:37'!
setSystemFontTo: aFont

	UserInterfaceTheme setSystemFontTo: aFont.! !

!Preferences class methodsFor: 'prefs - fonts' stamp: 'mt 12/29/2021 20:36'!
setWindowTitleFontTo: aFont
	"Set the window-title font to be as indicated"

	UserInterfaceTheme setFont: #windowTitleFont to: aFont.
	
	"(Smalltalk hasClassNamed: #StandardSystemView)
		ifTrue: [(Smalltalk at: #StandardSystemView) setLabelStyle].
	(Smalltalk hasClassNamed: #Flaps)
		ifTrue: [(Smalltalk at: #Flaps) replaceToolsFlap]"
! !

!Preferences class methodsFor: 'updating - system' stamp: 'mt 12/30/2021 12:56'!
displaySizeChanged

	self tinyDisplay
		ifTrue: [self enable: #scrollBarsNarrow]
		ifFalse: [self disable: #scrollBarsNarrow].
	self tinyDisplay 
		ifTrue:[self disable: #biggerHandles] 
		ifFalse:[self enable: #biggerHandles].
	UserInterfaceTheme current apply.! !


!Project methodsFor: 'displaying' stamp: 'mt 12/30/2021 13:27'!
displayScaleChangedFrom: oldFactor to: newFactor

	RealEstateAgent resetScaleFactor. "Reset cached (pixel-based) scale factor used in initialization and rendering code. See senders of #scaleFactor."! !


!MorphicProject methodsFor: 'display' stamp: 'mt 12/29/2021 21:43'!
displayScaleChangedFrom: oldFactor to: newFactor
	"Update Morphic-specific geometry. Try to be more efficient than UI theme's #applyUserInterfaceTheme."
	
	super displayScaleChangedFrom: oldFactor to: newFactor.
	
	"Switching UI themes involves updating geometry for different fonts anyway. Maybe we can speed up this at some point by avoiding to refresh non-geometry properties such as colors."
	UserInterfaceTheme current
		basicApply;
		scaleMorphicToolsBy: newFactor / oldFactor.
! !


!RealEstateAgent class methodsFor: 'display scale' stamp: 'mt 12/21/2021 11:10'!
resetScaleFactor
	
	ScaleFactor := nil.! !

!RealEstateAgent class methodsFor: 'display scale' stamp: 'mt 12/30/2021 13:28'!
scaleFactor
	"Use the default font height to calculate some factor. Note that, in a distant future, we will be able to use a method that is not based on pixels once we only use TrueType fonts all over the image and have a rendering system other than BitBlt. Then, TextStyle class >> #pixelsPerInch will suffice, considering that 96 PPI represents a scale factor of 1.0. Until then, rendering is based on pixel geometry."
	
	^ ScaleFactor ifNil: [ScaleFactor := (TextStyle defaultFont height / StrikeFont referenceHeight)]! !


!StrikeFont class methodsFor: '*System-constants' stamp: 'mt 12/21/2021 08:58'!
referenceHeight
	"Since Squeak 4.1, the standard system/text font has been pre-rendered to a height of 14 pixels, which are about 10.5 point in 96 PPI. We can use this value to compute the effective in-image scale factor using the current system font's height (in pixels). If that font happens to be a TTCFont, the same #pointSize can result in a different #pixelSize once PPI changes.
	
	StrikeFont ... 10.5 pt = 14 px in 96 ppi = 1.0 or 100%
	TTCFont ... 96 ppi = 1.0 or 100%
	"

	^ 14 "pixels"! !


!TTCFont class methodsFor: '*System-constants' stamp: 'mt 12/21/2021 13:15'!
referencePointSize
	"See commentary in StrikeFont class >> #referenceHeight."

	^ 10.5! !


!TextStyle class methodsFor: 'utilities' stamp: 'mt 12/21/2021 11:05'!
pixelsPerInch: aNumber
	"Set the nominal number of pixels per inch to aNumber."

	self pixelsPerInch = aNumber ifTrue: [^ self].
	TextConstants at: #pixelsPerInch put: aNumber.
	AbstractFont allSubInstancesDo: [ :font | font pixelsPerInchChanged ].! !


!TheWorldMainDockingBar methodsFor: 'submenu - extras' stamp: 'mt 12/23/2021 14:42'!
chooseCustomScaleFactor

	| result |
	result := Project uiManager request: 'Please enter a scale factor in %' translated initialAnswer: '350'.
	result ifEmpty: [^ self].
	[result := result asInteger abs] ifError: [^ self].
	result < 100 ifTrue: [^ self].
	Display relativeUiScaleFactor: result / 100.! !

!TheWorldMainDockingBar methodsFor: 'submenu - extras' stamp: 'mt 12/19/2021 09:11'!
extrasMenuOn: aDockingBar 

	aDockingBar addItem: [ :it|
		it 	contents: 'Extras' translated;
			addSubMenu: [:menu|
				menu addItem:[:item|
					item
						contents: 'Recover Changes' translated;
						help: 'Recover changes after a crash' translated;
						icon: MenuIcons smallDocumentClockIcon;
						target: ChangeList;
						selector: #browseRecentLog].
				menu addItem:[:item|
					item
						contents: 'Recover Method Versions' translated;
						help: 'Recover versions of deleted methods' translated;
						target: ChangeList;
						selector: #browseMethodVersions].				
				menu addLine.
				menu addItem:[:item|
					item
						contents: 'Themes & Colors' translated;
						subMenuUpdater: self
						selector: #themesAndWindowColorsOn: ].
				menu addItem:[:item|
					item
						contents: 'Scale Factor' translated;
						subMenuUpdater: self
						selector: #scaleFactorsOn:].
				menu addItem:[:item|
					item
						contents: 'Language' translated;
						subMenuUpdater: self
						selector: #languageTranslatorsOn: ].
				menu addItem:[:item|
					item
						contents: 'Set Author Initials' translated;
						help: 'Sets the author initials' translated;
						icon: MenuIcons smallUserQuestionIcon;
						target: Utilities;
						selector: #setAuthorInitials].
				menu addItem:[:item|
					item
						contents: 'Restore Display (r)' translated;
						help: 'Redraws the entire display' translated;
						target: Project current;
						selector: #restoreDisplay].
				menu addItem:[:item|
					item
						contents: 'Rebuild Menus' translated;
						help: 'Rebuilds the menu bar' translated;
						target: TheWorldMainDockingBar;
						selector: #updateInstances].
				menu addLine.
				menu addItem:[:item|
					item
						contents: 'Start Profiler' translated;
						help: 'Starts the profiler' translated;
						icon: MenuIcons smallTimerIcon;
						target: self;
						selector: #startMessageTally].
				menu addItem:[:item|
					item
						contents: 'Collect Garbage' translated;
						help: 'Run the garbage collector and report space usage' translated;
						target: Utilities;
						selector: #garbageCollectAndReport].
				menu addItem:[:item|
					item
						contents: 'Purge Undo Records' translated;
						help: 'Save space by removing all the undo information remembered in all projects' translated;
						target: CommandHistory;
						selector: #resetAllHistory].
				menu addItem:[:item|
					item
						contents: 'VM statistics' translated;
						help: 'Virtual Machine information' translated;
						target: self;
						selector: #vmStatistics].
				menu addLine.
				menu addItem:[:item|
					item
						contents: 'Graphical Imports' translated;
						help: 'View the global repository called ImageImports; you can easily import external graphics into ImageImports via the FileList' translated;
						target: (Imports default);
						selector: #viewImages].
				menu addItem:[:item|
					item
						contents: 'Standard Graphics Library' translated;
						help: 'Lets you view and change the system''s standard library of graphics' translated;
						target: ScriptingSystem;
						selector: #inspectFormDictionary].
				menu addItem:[:item|
					item
						contents: 'Annotation Setup' translated;
						help: 'Click here to get a little window that will allow you to specify which types of annotations, in which order, you wish to see in the annotation panes of browsers and other tools' translated;
						target: Preferences;
						selector: #editAnnotations].
				menu addItem:[:item|
					item
						contents: 'Browse My Changes' translated;
						help: 'Browse all of my changes since the last time #condenseSources was run.' translated;
						target: SystemNavigation new;
						selector: #browseMyChanges].
			] ]! !

!TheWorldMainDockingBar methodsFor: 'submenu - extras' stamp: 'mt 12/30/2021 11:18'!
resetAllThemes

	(Project uiManager confirm: 'Do you want to reset all UI themes\to their original state?\\(The current theme and scale factor\will be restored if possible.)' withCRs translated title: 'Reset All Themes')
		ifTrue: [UserInterfaceTheme cleanUpAndReset].! !

!TheWorldMainDockingBar methodsFor: 'submenu - extras' stamp: 'mt 12/30/2021 12:42'!
scaleFactorsOn: menu

	| presets currentScaleFactor currentPlatformScaleFactor |
	currentScaleFactor := (Display relativeUiScaleFactor * 100) rounded.
	currentPlatformScaleFactor := Display platformScaleFactorKnown
		ifTrue: [(Display platformScaleFactor * 100) rounded].
	presets := 100 to: 300 by: 25.
	
	presets do: [:scale |
		scale = 175 ifTrue: [menu addLine]. "TTCFont used after this line..."
		menu addItem: [:item|
			item
				contents: ('{1}{2}%{3}' format: {
					currentScaleFactor = scale ifTrue: ['<yes>'] ifFalse: ['<no>'].
					scale.
					DisplayScreen relativeScaleFactorEnabled
						ifTrue: ['' "macOS"] ifFalse: [
							scale = currentPlatformScaleFactor
								ifTrue: [' (recommended)'] ifFalse: ['']]
					});
				target: Display;
				selector: #relativeUiScaleFactor:;
				arguments: {scale / 100}]].
		
	menu addLine.
	menu addItem: [:item |
		item
			contents: ((presets includes: currentScaleFactor) not ifTrue: ['<yes> Custom: ', currentScaleFactor, '% ...'] ifFalse: ['<no>Other scale factor...']);
			target: self;
			selector: #chooseCustomScaleFactor].! !

!TheWorldMainDockingBar methodsFor: 'submenu - extras' stamp: 'mt 12/30/2021 11:45'!
themesAndWindowColorsOn: menu
	| themes |
	menu addItem:[:item|
		item
			contents: 'Fonts' translated;
			subMenuUpdater: Preferences
			selector: #fontConfigurationMenu:;
			icon: MenuIcons smallFontsIcon].
	menu addLine.
	menu addItem:[:item|
		item
			contents: (Model useColorfulWindows ifTrue: ['<yes>'] ifFalse: ['<no>']), 'Colorful Windows' translated;
			target: self;
			selector: #toggleColorfulWindows].
	menu addItem:[:item|
		item
			contents: (SystemWindow gradientWindow not ifTrue: ['<yes>'] ifFalse: ['<no>']), 'Flat Widget Look' translated;
			target: self;
			selector: #toggleGradients].
	menu addLine.
	menu addItem:[:item |
		item
			contents: (((Preferences valueOfFlag: #menuAppearance3d ifAbsent: [false]) and: [Morph useSoftDropShadow]) ifTrue: ['<yes>'] ifFalse: ['<no>']), 'Soft Shadows' translated;
			target: self;
			selector: #toggleSoftShadows].
	menu addItem:[:item |
		item
			contents: (((Preferences valueOfFlag: #menuAppearance3d ifAbsent: [false]) and: [Morph useSoftDropShadow not]) ifTrue: ['<yes>'] ifFalse: ['<no>']), 'Hard Shadows' translated;
			target: self;
			selector: #toggleHardShadows].
	menu addLine.
	menu addItem:[:item |
		item
			contents: (SystemWindow roundedWindowCorners ifTrue: ['<yes>'] ifFalse: ['<no>']), 'Rounded Window/Dialog/Menu Look' translated;
			target: self;
			selector: #toggleRoundedWindowLook].
	menu addItem:[:item |
		item
			contents: (PluggableButtonMorph roundedButtonCorners ifTrue: ['<yes>'] ifFalse: ['<no>']), 'Rounded Button/Scrollbar Look' translated;
			target: self;
			selector: #toggleRoundedButtonLook].
	menu addLine.
	themes := UserInterfaceTheme allThemes asArray sort: #name ascending.
	themes := themes select: [ :each | each isGenuine].
	themes ifEmpty: [ 
		menu addItem: [ :item | 
			item
				contents: '(No UI themes found.)' translated;
				isEnabled: false ] ].
	themes do: [ :each |
		menu addItem: [ :item |
			item 
				contents: (UserInterfaceTheme current name = each name ifTrue: ['<yes>'] ifFalse: ['<no>']), each name;
				target: each;
				selector: #applyScaled ] ].
	menu	
		addLine;
		add: 'Set Etoys Mode' translated target: ReleaseBuilderSqueakland selector: #setEtoysMode.
	menu
		addLine;
		add: 'Restore UI theme background' translated target: self selector: #restoreThemeBackground;
		add: 'Reset all UI themes' translated target: self selector: #resetAllThemes;
		add: 'Edit current UI theme...' translated target: self selector: #editCurrentTheme.! !


!ToolIcons class methodsFor: 'private' stamp: 'mt 12/30/2021 14:21'!
font

	| icon f1 f2 |
	icon := Form extent: 16@16 depth: 32.
	f1 := StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 7.5.
	f2 := StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5.
	icon getCanvas
		drawString: 'A' at: 0@ (15 - f1 height) font: f1 color: Color black;
		drawString: 'A' at: (f1 widthOf: $A) @ (15 - f2 height) font: f2 color: Color black.
	^ icon! !


!UserInterfaceTheme methodsFor: 'actions' stamp: 'mt 12/30/2021 11:12'!
apply
	"Apply this theme to all affected objects. Let classes decide on how to iterate and call their instances."

	ignoreApply == true ifTrue: [^ self].
	UserInterfaceTheme current: self.
	self fixFontsAndScaleAround: [self basicApply	].

	"Project current restoreDisplay. -- not needed. Rather fix occasional draw-only issues in the respective morphs via #applyUserInterfaceTheme and #changed."! !

!UserInterfaceTheme methodsFor: 'actions' stamp: 'mt 12/23/2021 14:17'!
applyAfter: aBlock

	lastScaleFactor := RealEstateAgent scaleFactor.
	self class current: self. "Font callbacks from Preferences to here."
	self ignoreApplyDuring: aBlock.
	self apply.! !

!UserInterfaceTheme methodsFor: 'actions' stamp: 'mt 12/21/2021 15:29'!
ignoreApplyDuring: aBlock

	ignoreApply := true.
	^ aBlock ensure: [ignoreApply := false]! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/23/2021 14:19'!
applyScaled
	"Apply the receiver but keep the current #uiScaleFactor."
	
	self applyScaled: Display uiScaleFactor.! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/21/2021 11:31'!
applyScaled: aFloat
	"Apply the receiver with the given scale factor aFloat."
	
	self setScaleFactor: aFloat.! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/21/2021 13:49'!
canFakeScaleFactor: aFloat
	"Answer whether we can fake the given scale factor with pre-rendered fonts."

	self isTTCBased ifFalse: [^ true "Need to #makeTTCBased anyway."].
	(self lookupScaleFactor: 1.0) ifNil: [^ false "Without a fake 100%, we go all-in with TrueType fonts."].

	aFloat = 1.0 ifTrue: [^ true].
	aFloat = 1.25 ifTrue: [^ true].
	aFloat = 1.5 ifTrue: [^ true].
	
	^ false! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/21/2021 14:11'!
checkTheme100

	| theme100 |
	self flag: #isTTCBased.
	theme100 := self lookupScaleFactor: 1.0.
	self
		assert: [theme100 notNil]
		description: 'Reference theme not found!! Please reset all themes.'.
	^ theme100! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/21/2021 16:31'!
copyWithScaleFactor: aFloat
	"Duplicate the receiver and reconfigure the copy to have its #scaleFactor match factorInPercent. This method is used for preserving the reference theme, which has a 100% scale factor."

	| copy |
	self
		assert: [self isTTCBased not]
		description: 'There is no need to duplicate themes that are already based on TrueType fonts!!'.
	
	copy := UserInterfaceTheme named: 'Demo'.
	copy merge: self overwrite: true.
	
	copy name: self name.
	copy set: #standardSystemFont to: nil. "We are not theme100 for the moment."
	self assert: [copy localScaleFactor isNil].

	copy setScaleFactorPreApply: aFloat.
	
	^ copy! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/29/2021 14:57'!
doScale100
	"Private. Use #applyScaled:. The reference theme, which has a 100% scale factor, must already be there. Look it up and apply it."
	
	self checkTheme100 apply.
	TextStyle pixelsPerInch: 96.0. "Restore Squeak's default PPI for 100%."! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/26/2021 11:52'!
doScale125
	"Private. Use #applyScaled:. This is actually about 135% because of which font sizes we have available."
	
	self flag: #hack. "mt: A different scale factor should not result in different point sizes being selected BUT the same point size resulting in a different pixel height."
	
	self setFonts: #(
		standardSystemFont 14.5
		standardFixedFont 14.5

		standardCodeFont 14.5
		standardListFont 14.5
		standardButtonFont 10.5
		standardMenuFont 14.5
		standardFlapFont 10.5
			
		windowTitleFont 14.5
		balloonHelpFont 10.5
		haloLabelFont 14.5
		
		wizardStandardFont 20.0
		wizardButtonFont 20.0
		wizardHelpFont 14.5
		wizardTitleFont 32.5) forceTTC: false.

	self apply.
	TextStyle pixelsPerInch: 96.0. "Restore Squeak's default PPI for 100%."! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/26/2021 11:54'!
doScale150
	"Private. Use #applyScaled:. Traditional 'Demo Mode'. Optimized for existing pre-rendered fonts. Does not fall back on TTC font. See #doScale:. This is actually about 157% because of which font sizes we have available."
	
	self flag: #hack. "mt: A different scale factor should not result in different point sizes being selected BUT the same point size resulting in a different pixel height."
	
	self setFonts: #(
		standardSystemFont 16.5
		standardFixedFont 16.5

		standardCodeFont 16.5
		standardListFont 16.5
		standardButtonFont 14.5
		standardMenuFont 16.5
		standardFlapFont 14.5
			
		windowTitleFont 16.5
		balloonHelpFont 14.5
		haloLabelFont 16.5
		
		wizardStandardFont 22.5
		wizardButtonFont 22.5
		wizardHelpFont 16.5
		wizardTitleFont 36.5) forceTTC: false.

	self apply.
	TextStyle pixelsPerInch: 96.0. "Restore Squeak's default PPI for 100%."! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/22/2021 09:34'!
isGenuine

	self isTTCBased ifTrue: [
		"The receiver is only genuine if there is no other theme with the same same, probably one with pre-rendered fonts."
		^ (self class allThemes anySatisfy: [:theme |
			theme ~~ self and: [theme name = self name]]) not].

	^ self localScaleFactor = 1.0! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/21/2021 14:04'!
isTTCBased
	"Answer whether the receiver uses only TrueType fonts, which can flexibly adapt to changing scale factors."

	^ (self get: #standardSystemFont) ifNil: [false] ifNotNil: [:font | font isTTCFont]
	
	"properties keysDo: [:key |
		(key isSymbol and: [key endsWith: #Font])
			ifTrue: [(self get: key) isTTCFont ifFalse: [^ false]]].
	^ true"! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/21/2021 14:42'!
localScaleFactor
	"Answers the scale factor that the receiver supports, which is arbitrary for themes that only use TTCFonts."

	self
		assert: [self isTTCBased not]
		description: 'The local scale factor is undefined for TrueType-based themes!!'.

	^ (self get: #standardSystemFont)
		ifNil: ["Not yet initialized."]
		ifNotNil: [:font | (font height / StrikeFont referenceHeight) roundTo: 0.25]! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/21/2021 17:05'!
lookupScaleFactor: aFloat
	"Answer a theme that fakes the given scale factor with pre-rendered fonts."

	^ self class allThemes
		detect: [:ea | ea name = self name and: [ea isTTCBased not and: [ea localScaleFactor = aFloat]]]
		ifNone: ["Not found."]! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/21/2021 16:26'!
lookupSimilar
	"Answer a theme that is similar to the receiver but not the reference theme for pre-rendered fonts."

	^ self class allThemes
		detect: [:ea | ea name = self name and: [ea isTTCBased or: [ea localScaleFactor ~= 1.0]]]
		ifNone: ["Not found."]! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/26/2021 11:54'!
makeTTCBased
	"100%"
	
	self isTTCBased ifTrue: [^ self].
	
	self setFonts: #(
		standardSystemFont 10.5
		standardFixedFont 10.5
	
		standardCodeFont 10.5
		standardListFont 10.5
		standardButtonFont 7.5
		standardMenuFont 10.5
		standardFlapFont 7.5
			
		windowTitleFont 10.5
		balloonHelpFont 7.5
		haloLabelFont 10.5
		
		wizardStandardFont 14.5 
		wizardButtonFont 14.5
		wizardHelpFont 10.5
		wizardTitleFont 23.5) forceTTC: true.
		
	self assert: [self isTTCBased].! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/29/2021 21:13'!
setFonts: specs forceTTC: forceTTC
	"Change fonts. Do not apply the receiver. Replace StrikeFont with TTCFont if forceTTC or target pointSize not available."
		
	| theme100 |
	theme100 := self checkTheme100.
	
	specs groupsDo: [:symbolicFontName :newPointSize | | font100 fontScaled |
		font100 := theme100 get: symbolicFontName.
		fontScaled := font100 isTTCFont
			ifTrue: [TTCFont familyName: font100 familyName pointSize: newPointSize emphasis: font100 emphasis]
			ifFalse: [StrikeFont familyName: font100 familyName pointSize: newPointSize emphasized: font100 emphasis].
		(fontScaled pointSize ~= newPointSize or: [forceTTC and: [fontScaled isTTCFont not]])
			ifTrue: [fontScaled := TTCFont familyName: self ttcFallbackName pointSize: newPointSize emphasis: font100 emphasis].
		self assert: [fontScaled pointSize = newPointSize].
		self set: symbolicFontName to: fontScaled].! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/29/2021 14:58'!
setScaleFactor: aFloat
	"Private. Use #applyScaled:. In the receiver, change the fonts to have a scale of aFloat. Change all fonts to be TrueType fonts if no pre-rendered fonts exist. Never change the 100% reference theme but make a copy. Apply the receiver to the system."

	(self isTTCBased not and: [aFloat = self localScaleFactor])
		ifTrue: [self isCurrent ifFalse: [self apply]. ^ self].

	(self isTTCBased not and: [self localScaleFactor = 1.0]) "!!!! Never change the reference theme !!!!"
		ifTrue: [^ self lookupSimilar ifNil: [self copyWithScaleFactor: aFloat] ifNotNil: [:other | other setScaleFactorPreApply: aFloat]].
	
	aFloat = 1.0 ifTrue: [^ self doScale100].
	aFloat = 1.25 ifTrue: [^ self doScale125].
	aFloat = 1.5 ifTrue: [^ self doScale150].

	"And now transition from the pre-rendered world into the TrueType world. Or re-use an existing TrueType-based theme with new values. See #lookupSimilar above."
	TextStyle pixelsPerInch: 96.0 * RealEstateAgent scaleFactor "current, based on pixels".
	self makeTTCBased.
	self applyAfter: [TextStyle pixelsPerInch: 96.0 * aFloat "new, not rounded"].! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/21/2021 16:33'!
setScaleFactorPreApply: aFloat

	| last |
	last := Current.
	[Current := self.  "Manage side-effects in #setDefaultFonts: ..."
	self setScaleFactor: aFloat]
		on: Error do: [:ex | Current := last. ex pass].! !

!UserInterfaceTheme methodsFor: 'private - display scale' stamp: 'mt 12/30/2021 13:35'!
ttcFallbackName
	"Answer the name of the TTCFont that should be used as a fallback for pre-rendered StrikeFonts that do not have the requested #pointSize available."
	
	^ 'BitstreamVeraSans'! !

!UserInterfaceTheme methodsFor: 'testing' stamp: 'mt 12/19/2021 10:03'!
isCurrent
	"Note that changes to the receiver's properties without calling #apply can result in visual differences even though the answer might be 'true'."
	
	^ self class current == self! !

!UserInterfaceTheme methodsFor: 'private - fonts' stamp: 'mt 12/22/2021 08:22'!
fixFontsAndScaleAround: applyThemeBlock
	"Given that the receiver is the current UI theme, set the system's default fonts, which define RealEstateAgent's #scaleFactor. If the factor changes, resize open windows to make them fit the scaled contents. Note that themes can have arbitrary point sizes for their system font, even though it is not recommended. See TTCFont class >> #referencePointSize."

	lastScaleFactor ifNil: [lastScaleFactor := RealEstateAgent scaleFactor].

	"Due to the current font situation, update TextConstants."
	(self get: #standardSystemFont) ifNotNil: [:font | self installSystemFont: font].
	(self get: #standardFixedFont) ifNotNil: [:font | self installFixedFont: font].	

	"Propagate the receiver's properties across the system."
	applyThemeBlock value.

	"Due to the current real-estate manager situation, resize all windows. Works only for Morphic projects."
	self scaleMorphicToolsBy: RealEstateAgent scaleFactor / lastScaleFactor.
		
	lastScaleFactor := nil.! !

!UserInterfaceTheme methodsFor: 'private - fonts' stamp: 'mt 12/22/2021 08:12'!
installFixedFont: aFont
	"Establish the default fixed text font and style"

	| aStyle |
	self flag: #todo. "mt: Support derivatives such as bold and italic."
	aStyle := aFont textStyle.
	aStyle defaultFontIndex: (aStyle fontIndexOf: aFont).
	TextStyle setDefaultFixed: aStyle.! !

!UserInterfaceTheme methodsFor: 'private - fonts' stamp: 'mt 12/22/2021 08:17'!
installSystemFont: aFont
	"Establish the default text font and style"

	| aStyle |
	self flag: #todo. "mt: Support derivatives such as bold and italic."
	aStyle := aFont textStyle.
	aStyle defaultFontIndex: (aStyle fontIndexOf: aFont).

	TextStyle setDefault: aStyle.
	RealEstateAgent resetScaleFactor.
	
	Flaps replaceToolsFlap.
	ScriptingSystem resetStandardPartsBin.! !

!UserInterfaceTheme methodsFor: 'private - fonts' stamp: 'mt 12/22/2021 08:22'!
scaleMorphicToolsBy: factor

	Project current isMorphic ifFalse: [^ self].
	(factor closeTo: 1) ifTrue: [^ self].
	
	Project current world submorphs
		select: [:morph | morph isSystemWindow]
		thenDo: [:window |
			window extent: window extent * factor.
			window layoutChanged.
			window setFramesForLabelArea].! !

!UserInterfaceTheme methodsFor: 'private - fonts' stamp: 'mt 12/29/2021 20:33'!
setFixedFontTo: aFont
	"Establish the default fixed text font and style"

	self setFont: #standardFixedFont to: aFont.! !

!UserInterfaceTheme methodsFor: 'private - fonts' stamp: 'mt 12/29/2021 20:33'!
setFont: symbolicName to: aFont
	"Establish the default text font and style"

	self set: symbolicName to: aFont.
	self isCurrent ifTrue: [self apply].! !

!UserInterfaceTheme methodsFor: 'private' stamp: 'mt 12/29/2021 20:08'!
basicApply
	"Private. See #apply."

	self class clientClassesToReapply in: [:cc |
		cc do: [:eachClass | eachClass applyUserInterfaceTheme].
		Cursor wait showWhile: [
			SystemNavigation default allObjectsDo: [:o |
				((cc includes: o class)
					and: [o canApplyUserInterfaceTheme])
						ifTrue: [o applyUserInterfaceTheme]]]].! !

!UserInterfaceTheme methodsFor: 'printing' stamp: 'mt 12/21/2021 13:48'!
printOn: aStream

	super printOn: aStream.

	aStream space; print: name.
	self isTTCBased ifFalse: [
		aStream space; nextPutAll: ('({1}%)' format: {self localScaleFactor * 100})].! !


!UserInterfaceTheme class methodsFor: 'tools - fonts' stamp: 'mt 12/29/2021 20:39'!
setFixedFontTo: aFont
	"Establish the default fixed text font and style"

	self setFont: #standardFixedFont to: aFont.! !

!UserInterfaceTheme class methodsFor: 'tools - fonts' stamp: 'mt 12/30/2021 11:14'!
setFont: symbolicName to: aFont
	"Set symbolicName to aFont in all known UI themes. If aFont is a TrueType font, transform all themes into TTC-based ones and re-apply the current theme by name."

	aFont isTTCFont ifTrue: [
		self flag: #discuss. "mt: Should we issue a warning here?"
		(self allThemes anySatisfy: [:uit | uit isTTCBased not])
			ifTrue: [self resetAfter: [
				self allThemes copy do: [:uit | uit isGenuine ifFalse: [uit unregister]].
				self allThemes do: [:uit | uit makeTTCBased]] ]].

	self allThemes do: [:uit |
		uit setFont: symbolicName to: aFont].! !

!UserInterfaceTheme class methodsFor: 'tools - fonts' stamp: 'mt 12/30/2021 13:24'!
setSystemFontTo: aFont
	"Establish the default text font and style"

	aFont isTTCFont not ifTrue: [
		Display uiScaleFactor = 1.0
			ifFalse: [^ self error: 'Can only set pre-rendered font for 100% scale factor'].
		aFont height = StrikeFont referenceHeight
			ifFalse: [^ self error: ('Incompatible pre-rendered font for 100% scale factor. Height must be {1} px' format: {StrikeFont referenceHeight})]].

"Documentation only. Users can increase the default font size to any value. Yet, RealEstateAgent class >> #scaleFactor will change and the system effectively render stuff larger. So, it would be a good idea to keep #pixelSize/#height of system font, list font, and menu font similar.

	(aFont isTTCFont and: [aFont pointSize ~= TTCFont referencePointSize])
		ifTrue: [self notify: ('The standard system/text font should be {1} pt. If you want to increase the overall font size, please change the screen scale factor instead. You may proceed without harm.' format: {TTCFont referencePointSize})].
"
	self setFont: #standardSystemFont to: aFont.! !

!UserInterfaceTheme class methodsFor: 'accessing' stamp: 'mt 12/30/2021 13:39'!
current

	^ Current ifNil: [Current := self default]! !

!UserInterfaceTheme class methodsFor: 'accessing' stamp: 'mt 12/29/2021 20:56'!
default
	^ Default ifNil: [
		Default := self new.
		Default name: 'Autogenerated Default'.
		self addDefaultFonts: Default.
		Default]! !

!UserInterfaceTheme class methodsFor: 'initialize-release' stamp: 'mt 12/30/2021 13:37'!
addDefaultFonts: theme
	"There must be fonts installed in the default theme. Unlike all other theme properties, there are no defaults encoded throughout the system for these properties. That is, there are no #ifNil: checks when requesting a font from the current theme."
	
	| defaultBuilder |
	defaultBuilder := TTCFont familyName: 'BitstreamVeraSans' pointSize: TTCFont referencePointSize.
	#(
		standardSystemFont
		standardFixedFont

		standardCodeFont
		standardListFont
		standardButtonFont
		standardMenuFont
		standardFlapFont
			
		windowTitleFont
		balloonHelpFont
		haloLabelFont
		
		wizardStandardFont
		wizardButtonFont
		wizardHelpFont
		wizardTitleFont
	)
		do: [:symbolicName | theme set: symbolicName to: defaultBuilder].! !

!UserInterfaceTheme class methodsFor: 'initialize-release' stamp: 'mt 12/29/2021 20:57'!
cleanUp: aggressive

	aggressive ifTrue: [
		All := Default := nil.
		SqueakTheme
			create;
			createDuller.
		SolarizedTheme
			createDark;
			createLight.
		MonokaiTheme createDark.
		CommunityTheme createDark.
		TrimTheme create].! !

!UserInterfaceTheme class methodsFor: 'initialize-release' stamp: 'mt 12/29/2021 20:58'!
cleanUpAndReset
	"Rebuild all themes and re-apply the current one by name."

	self resetAfter: [self cleanUp: true].! !

!UserInterfaceTheme class methodsFor: 'initialize-release' stamp: 'mt 12/30/2021 13:39'!
reset
	self current apply.! !

!UserInterfaceTheme class methodsFor: 'initialize-release' stamp: 'mt 12/29/2021 20:49'!
resetAfter: aBlock
	"Evaluate aBlock and re-apply the current one by name."
	
	| nameToReset scaleFactorToReset |
	nameToReset := self current name.
	scaleFactorToReset := Display uiScaleFactor.
	aBlock value.
	(self named: nameToReset) applyScaled: scaleFactorToReset.! !


!CommunityTheme class methodsFor: 'instance creation' stamp: 'mt 12/20/2021 17:13'!
addDarkFonts: aUserInterfaceTheme
	"Set-up fonts."
	aUserInterfaceTheme
		set: #balloonHelpFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 7.5 emphasized: TextEmphasis italic emphasisCode];
		set: #standardButtonFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 7.5];
		set: #standardCodeFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5];
		set: #standardFlapFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 7.5 emphasized: TextEmphasis bold emphasisCode];
		set: #haloLabelFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5];
		set: #standardListFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5];
		set: #standardMenuFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5];
		set: #standardSystemFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5];
		set: #windowTitleFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5 emphasized: TextEmphasis bold emphasisCode]! !


!MonokaiTheme class methodsFor: 'instance creation' stamp: 'mt 12/20/2021 17:12'!
addDarkFonts: theme

	"Set-up fonts."
	theme
		set: #balloonHelpFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 7.5];
		set: #standardButtonFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 7.5];
		set: #standardCodeFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5];
		set: #standardFlapFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 7.5 emphasized: TextEmphasis bold emphasisCode];
		set: #haloLabelFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5];
		set: #standardListFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5];
		set: #standardMenuFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5];
		set: #standardSystemFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5];
		set: #windowTitleFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5].! !


!SolarizedTheme class methodsFor: 'instance creation' stamp: 'mt 12/20/2021 17:12'!
addDarkFonts: theme

	"Set-up fonts."
	theme
		set: #balloonHelpFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 7.5];
		set: #standardButtonFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 7.5];
		set: #standardCodeFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5];
		set: #standardFlapFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 7.5 emphasized: TextEmphasis bold emphasisCode];
		set: #haloLabelFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5];
		set: #standardListFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5];
		set: #standardMenuFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5];
		set: #standardSystemFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5];
		set: #windowTitleFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5].! !

!SolarizedTheme class methodsFor: 'instance creation' stamp: 'mt 12/20/2021 17:12'!
addLightFonts: theme

	"Set-up fonts."
	theme
		set: #balloonHelpFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 7.5];
		set: #standardButtonFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 7.5];
		set: #standardCodeFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5];
		set: #standardFlapFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 7.5 emphasized: TextEmphasis bold emphasisCode];
		set: #haloLabelFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5];
		set: #standardListFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5];
		set: #standardMenuFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5];
		set: #standardSystemFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5];
		set: #windowTitleFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5 emphasized: TextEmphasis bold emphasisCode].! !


!SqueakTheme class methodsFor: 'instance creation' stamp: 'mt 12/26/2021 11:40'!
addFonts: theme

	theme
		set: #standardSystemFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5];
		set: #standardFixedFont to: [TTCFont familyName: 'BitstreamVeraSansMono' pointSize: 10.5];

		set: #standardCodeFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5];
		set: #standardListFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5];
		set: #standardButtonFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 7.5];
		set: #standardMenuFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5];
		set: #standardFlapFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 7.5 emphasized: TextEmphasis bold emphasisCode];

		set: #windowTitleFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5 emphasized: TextEmphasis bold emphasisCode];
		set: #balloonHelpFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 7.5];
		set: #haloLabelFont to: [StrikeFont familyName: 'Bitmap DejaVu Sans' pointSize: 10.5];

		set: #wizardStandardFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 14.5];
		set: #wizardButtonFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 14.5];
		set: #wizardHelpFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5];
		set: #wizardTitleFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 23.5].! !


!TrimTheme class methodsFor: 'instance creation' stamp: 'mt 12/20/2021 17:12'!
addFonts: theme

	"Set-up fonts."
	theme
		set: #balloonHelpFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 7.5];
		set: #standardButtonFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 7.5];
		set: #standardCodeFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5];
		set: #standardFlapFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 7.5 emphasized: TextEmphasis bold emphasisCode];
		set: #haloLabelFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5];
		set: #standardListFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5];
		set: #standardMenuFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5];
		set: #standardSystemFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5];
		set: #windowTitleFont to: [StrikeFont familyName: 'Darkmap DejaVu Sans' pointSize: 10.5].! !


!WorldState methodsFor: 'update cycle' stamp: 'mt 12/23/2021 11:18'!
doOneCycleNowFor: aWorld
	"Immediately do one cycle of the interaction loop.
	This should not be called directly, but only via doOneCycleFor:"

	| capturingGesture |
	DisplayScreen checkForNewScreenScaleFactor; checkForNewScreenSize.
	capturingGesture := false.
	"self flag: #bob.	"	"need to consider remote hands in lower worlds"
	
	"process user input events"
	LastCycleTime := Time millisecondClockValue.
	self handsDo: [:hand |
		hand becomeActiveDuring: [
			hand processEvents.
			capturingGesture := capturingGesture or: [hand isCapturingGesturePoints]]].
	
	"The gesture recognizer needs enough points to be accurate.
	Therefore morph stepping is disabled while capturing points for the recognizer"
	capturingGesture ifFalse: [
		aWorld runStepMethods.		"there are currently some variations here"
		self displayWorldSafely: aWorld].! !

UserInterfaceTheme class removeSelector: #default:!

!UserInterfaceTheme class reorganize!
('tools - fonts' setFixedFontTo: setFont:to: setSystemFontTo:)
('tools' allThemeProperties allThemePropertiesDo: categories propertiesForCategory: propertiesForClass:)
('accessing' allThemes current current: default)
('private' clientClasses clientClassesToReapply)
('initialize-release' addDefaultFonts: cleanUp: cleanUpAndReset initialize named: reset resetAfter:)
!


!UserInterfaceTheme reorganize!
('actions' apply applyAfter: applyTo: ignoreApplyDuring:)
('private - display scale' applyScaled applyScaled: canFakeScaleFactor: checkTheme100 copyWithScaleFactor: doScale100 doScale125 doScale150 isGenuine isTTCBased localScaleFactor lookupScaleFactor: lookupSimilar makeTTCBased setFonts:forceTTC: setScaleFactor: setScaleFactorPreApply: ttcFallbackName)
('testing' isCurrent)
('private - fonts' fixFontsAndScaleAround: installFixedFont: installSystemFont: scaleMorphicToolsBy: setFixedFontTo: setFont:to:)
('private' atomicUpdate: basicApply get: get:for: get:for:do: getViaLink: getViaSuperclasses: preMerge: properties validateCanMerge:)
('building' clear: clear:for: derive:for:from: derive:for:from:at: derive:for:from:at:do: derive:for:from:do: link: merge: merge:overwrite: set:for:to: set:to:)
('initialization' initialize register unregister)
('accessing' name name: next unsetProperties)
('copying' postCopy)
('printing' printOn:)
!


!TextStyle class reorganize!
('class initialization' initialize initializeStyleDecoder styleDecoder)
('constants' default defaultFixed defaultFixedFont defaultFont named: setDefault: setDefaultFixed:)
('instance creation' changeDefaultFontSizeBy: fontArray: initDefaultFontsAndStyle new)
('mime file in/out' collectionFromCompressedMIMEString: looseFontsFromFamily: replaceFontsIn:with: replaceStyle:with:)
('TextConstants access' actualTextStyles defaultFamilyNames fontArrayForStyle: fontPointSizesFor: fontSizesFor: fontWidthsFor: knownTextStyles knownTextStylesWithoutDefault pointSizesFor:)
('user interface' importFontsFromStyleFiles)
('utilities' decodeStyleName: fontSizeSummary fontSizeSummaryContents pixelsPerInch pixelsPerInch: pixelsToPoints: pointsToPixels:)
('*System-Fonts' chooseTTCFontSize:)
('*Morphic-user interface' emphasisMenuForFont:target:selector:highlight: fontMenuForStyle:target:selector: fontMenuForStyle:target:selector:highlight: promptForFont:andSendTo:withSelector: promptForFont:andSendTo:withSelector:highlight:)
('*System-Changes-mime file in/out' writeSF2FamilyNamed:inDirectory:toChangeSet: writeStyle:named:toChangeSet:)
('*Etoys-Squeakland-instance creation' addNewStyle:)
!


!TTCFont class reorganize!
('class initialization' initialize shutDown unload)
('file list services' fileReaderServicesForFile:suffix: serviceInstallTrueTypeFontStyle services)
('instance creation' familyName:pointSize: familyName:pointSize:emphasis: family:size: familyName:pointSize:emphasized: getExistings: newTextStyleFromTT: newTextStyleFromTTFile: newTextStyleFromTTStream:)
('objects from disk' classVersion)
('*System-constants' referencePointSize)
('other' indexOfSubfamilyName: isCacheAllNil pointSizes recreateCache registerAll register:at: registry removeAllDerivatives removeStyleName: reorganizeForNewFontArray:name: repairDerivativeFonts unregister: version)
!

RealEstateAgent class removeSelector: #applyUserInterfaceTheme!
RealEstateAgent class removeSelector: #themeProperties!
RealEstateAgent removeSelector: #applyUserInterfaceTheme!
RealEstateAgent removeSelector: #canApplyUserInterfaceTheme!

!RealEstateAgent reorganize!
('as yet unclassified')
!

Preferences class removeSelector: #changeFontSize:!
Preferences class removeSelector: #setDefaultFonts:!
PreferenceWizardMorph removeSelector: #createLabel:color:pointSize:!
PreferenceWizardMorph removeSelector: #initializePage02bVisualsMore!
PreferenceWizardMorph removeSelector: #stateUseBiggerFonts!
PreferenceWizardMorph removeSelector: #toggleUseBiggerFonts!
Morph subclass: #PreferenceWizardMorph
	instanceVariableNames: 'previewWorld titleMorph buttonRowMorph controlMorph startButton previousButton nextButton doneButton pages currentPageIndex pagesLabel skipButton isFullScreen lowPerformanceMorph checkmark radiomark'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'PreferenceBrowser'!

!PreferenceWizardMorph reorganize!
('actions' accept installExtraPackages next previous showInstallPage showPlayfield showSqueak showWelcome)
('initialization - building' createButton createCheckbox:for: createCheckbox:for:help: createHorizontalSpacer createLabel: createLabel:color: createPage createRadioButton:for:argument: createRadioButton:for:argument:help: createScrollPane createVerticalSpace createVerticalSpacer)
('initialization - playfield' addOrReplaceBrowser addOrReplaceSenders addOrReplaceTool:named: addOrReplaceWorkspace initializeButtons initializeControlMorph initializePages initializePreviewWorld)
('initialization' checkmark defaultButtonMargins defaultColor defaultExtent defaultFont defaultTextColor defaultTextMargins initialize initializePlayfield initializeWelcome openInWorld radiomark)
('support' adjustSettingsForLowPerformance findHelpStringFor: setBalloonText:for:)
('initialization - pages' initializePage00ScaleFactor initializePage01Themes initializePage02Visuals initializePage03Interaction initializePage04InteractionMore initializePage05Tools initializePage99ExtraPackages)
('display scale' updateFromChangedScaleFactor)
('updating' changed: changedRadio checkInternetOn: refreshWorld)
('event handling' filterEvent:for: handlesMouseDown: mouseDown: mouseUp: processFocusEvent:using:)
('testing' hasInternetConnection hasLowPerformance isInPlayfield isInWelcome)
('layout' updateLowPerformanceLabel: updatePageLabel updateWindowBounds)
('actions - radio' chooseScaleFactor: chooseTheme: stateScaleFactor: stateTheme:)
('actions - packages' installAutoComplete installFFI installGitInfrastructure installLatestUpdates installMetacello installOSProcess installRefactoringTools stateInstallAutoComplete stateInstallFFI stateInstallGitInfrastructure stateInstallLatestUpdates stateInstallMetacello stateInstallOSProcess stateInstallRefactoringTools toggleInstallAutoComplete toggleInstallFFI toggleInstallGitInfrastructure toggleInstallLatestUpdates toggleInstallOSProcess toggleInstallRefactoringTools)
('actions - buttons' doesNotUnderstand: stateAlternativeBrowseIt stateAttachToolsToMouse stateAutoEnclose stateAutoIndent stateBlinkingCursor stateClearFilterAutomatically stateEncloseSelection stateFastDrag stateFilterableLists stateFocusFollowsMouse stateGradients stateHardShadows stateLegacyShortcuts stateReuseWindows stateRoundedButtonLook stateRoundedWindowLook stateScrollBarsNarrow stateScrollBarsOnRight stateScrollBarsWithoutArrowButtons stateScrollBarsWithoutMenuButton stateSendMouseWheelToKeyboardFocus stateShowKeyboardFocus stateSimpleFrameAdornments stateSmartHorizontalSplitters stateSmartVerticalSplitters stateSoftShadows stateSwapMouseButtons stateToolAndMenuIcons stateTraceMessages stateUseBiggerCursors stateUseColorfulWindows stateUseRetractableScrollBars stateWindowButtonsAlwaysActive stateWindowsAlwaysActive stateWindowsRaiseOnClick stateWorkspaceEmbedTranscript stateWorkspaceFileOutOnAccept toggleAlternativeBrowseIt toggleAttachToolsToMouse toggleAutoEnclose toggleAutoIndent toggleBlinkingCursor toggleClearFilterAutomatically toggleEncloseSelection toggleFastDrag toggleFilterableLists toggleFocusFollowsMouse toggleGradients toggleHardShadows toggleLegacyShortcuts toggleReuseWindows toggleRoundedButtonLook toggleRoundedWindowLook toggleScrollBarsNarrow toggleScrollBarsOnRight toggleScrollBarsWithoutArrowButtons toggleScrollBarsWithoutMenuButton toggleSendMouseWheelToKeyboardFocus toggleShowKeyboardFocus toggleSimpleFrameAdornments toggleSmartHorizontalSplitters toggleSmartVerticalSplitters toggleSoftShadows toggleSwapMouseButtons toggleToolAndMenuIcons toggleTraceMessages toggleUseBiggerCursors toggleUseColorfulWindows toggleUseRetractableScrollBars toggleWindowButtonsAlwaysActive toggleWindowsAlwaysActive toggleWindowsRaiseOnClick toggleWorkspaceEmbedTranscript toggleWorkspaceFileOutOnAccept)
('stepping' step stepTime)
!

Form subclass: #DisplayScreen
	instanceVariableNames: 'clippingBox extraRegions'
	classVariableNames: 'DeferringUpdates DisplayChangeSignature DisplayIsFullScreen PlatformScaleFactor RelativeScaleFactorEnabled'
	poolDictionaries: ''
	category: 'Graphics-Display Objects'!
UserInterfaceTheme allThemes do: [:each | 
	"Convert 'Demo + Squeak' to 'Squeak'. Not needed anymore because of #scaleFactor in each theme."
	each name: (each name findTokens: '+') last withBlanksTrimmed].

"Unpack unnecessary StrikeFontSet in Accuny."
(TextStyle named: 'Accuny') ifNotNil: [:style |
	style fontArray withIndexDo: [:fontSet :index |
		((fontSet isKindOf: StrikeFontSet) and: [fontSet fontArray size = 1])
			ifTrue: [style fontArray at: index put: fontSet fontArray first]]].
	
"Fix font names for Atlanta."
(TextStyle named: 'Atlanta') fontArray do: [:font |
	font name last isDigit ifFalse: [font name: font name, font pointSize]].

"Fix PPI to be around 96 in all pre-rendered fonts."
(TextStyle knownTextStylesWithoutDefault
	collect: [:ea | TextStyle named: ea]
	thenSelect: [:style | style defaultFont isTTCFont not])
		do: [:style | style fontArray do: [:font |
			font pointSize: ((72 * font height / 96) roundTo: 0.5).
			font derivativeFonts do: [:derivate |
				derivate pointSize: font pointSize]]].
ToolIcons icons removeKey: #font.

"Fix missing command key shortcuts such as [cmd]+[+/-] for scale changes."
Project allMorphicProjects do: [:p | p world initializeDesktopCommandKeySelectors].

"New 'scale factor' menu"
TheWorldMainDockingBar updateInstances.

"Font definitions changed in all UI themes due to PPI conversion above. Wizard fonts have been added."	
UserInterfaceTheme cleanUpAndReset.!

