Christoph Thiede uploaded a new version of Morphic to project The Trunk: http://source.squeak.org/trunk/Morphic-ct.1841.mcz
==================== Summary ====================
Name: Morphic-ct.1841 Author: ct Time: 3 January 2022, 10:12:56.140397 pm UUID: 13c07ce7-f89f-7b48-b5e8-baa520ea1951 Ancestors: Morphic-ct.1840
Improves multilingual support at various places.
=============== Diff against Morphic-ct.1840 ===============
Item was changed: ----- Method: FontImporterTool>>buildButtonBarWith: (in category 'toolbuilder') ----- buildButtonBarWith: builder "Build the button bar" | panelSpec buttonSpec | panelSpec := builder pluggablePanelSpec new. panelSpec layout: #horizontal; children: OrderedCollection new.
buttonSpec := builder pluggableButtonSpec new model: self; label: 'Import' translated; + help: 'Include the font data in the image and provide a TextStyle for the font' translated; - help: 'Include the font data in the image and provide a TextStyle for the font'; action: #import; yourself. panelSpec children addLast: buttonSpec.
buttonSpec := builder pluggableButtonSpec new model: self; label: 'Close' translated; action: #close; yourself. panelSpec children addLast: buttonSpec.
^panelSpec!
Item was changed: ----- Method: FontImporterTool>>import (in category 'actions') ----- import | megaSize filenames fonts | fonts := self currentSelection. filenames := fonts allFilenames. megaSize := ((filenames inject: 0 into: [ :sum :fn | sum + (FileStream readOnlyFileNamed: fn do: [:file | file size])]) / (1024 * 1024)) asFloat. (UIManager default confirm: ( 'About to import {1}{2}.\This is at least {3} MB of space required in the image.\ Please respect the copyright and embedding restrictions of the font.\ Proceed?' + withCRs translated format: { - withCRs format: { self currentParent ifNotNil: [:p| p fontname, ' ', self currentSelection fontname] ifNil: [self currentSelection fontname]. + filenames size > 1 ifTrue: [' ({1} font files)' translated format: {filenames size}] ifFalse: ['']. - filenames size > 1 ifTrue: [' (', filenames size, ' font files)'] ifFalse: ['']. megaSize printShowingDecimalPlaces: 2})) ifTrue: [ filenames do: [:filename | | readFonts | readFonts := TTCFontDescription addFromTTFile: filename. readFonts isCollection ifFalse: [TTCFont newTextStyleFromTT: readFonts] ifTrue: [self importFontFamily: readFonts]]]. self allFonts: nil. "force redraw" TTCFont registerAll.!
Item was changed: ----- Method: FontImporterTool>>link (in category 'actions') ----- link | filenames fonts | fonts := self currentSelection. self warningSeen ifFalse: [ + (Project uiManager confirm: ( - (UIManager default confirm: ( 'Note that linking a font instead of importing may make the image un-portable, since the linked font must be present on the system the next time the image is run.
+ This warning is only shown once per session.' translated) trueChoice: 'Proceed' translated falseChoice: 'Cancel' translated) - This warning is only shown once per session.' ) trueChoice: 'Proceed' falseChoice: 'Cancel') ifFalse: [^ self]. self warningSeen: true].. filenames := fonts allFilenames. filenames do: [:filename | | readFonts | readFonts := TTFileDescription readFontsFrom: filename. readFonts isCollection ifFalse: [TTCFont newTextStyleFromTT: readFonts] ifTrue: [self importFontFamily: readFonts]]. self allFonts: nil. "force redraw" TTCFont registerAll.!
Item was changed: ----- Method: KeyboardExerciser>>drawOn: (in category 'drawing') ----- drawOn: aCanvas
super drawOn: aCanvas. aCanvas + drawString: 'Move your mouse cursor to here and start typing. Try modifiers, too.' translated - drawString: 'Move your mouse cursor to here and start typing. Try modifiers, too.' at: self topLeft font: Preferences standardButtonFont color: Color gray.!
Item was changed: ----- Method: KeyboardExerciser>>logEvent: (in category 'event handling') ----- logEvent: evt
| eventMorph | evt = self lastEvent ifTrue: [^ self logEventRepetition: evt].
eventMorph := evt asMorph. eventMorph setProperty: #event toValue: evt copy; + balloonText: ('Click to inspect. Shift+click to explore.\Virtual key: {8}\Virtual modifiers: {5}\Physical key: {9}\Physical modifiers: {6}\Key value: 0x{1} ({2}) \Key character: {3}\Key string: {4}\{7}' withCRs translated format: { - balloonText: ('Click to inspect. Shift+click to explore.\Virtual key: {8}\Virtual modifiers: {5}\Physical key: {9}\Physical modifiers: {6}\Key value: 0x{1} ({2}) \Key character: {3}\Key string: {4}\{7}' withCRs format: { evt keyValue printPaddedWith: $0 to: 2 base: 16. evt keyValue. evt isKeystroke ifTrue: [evt keyCharacter printString] ifFalse: ['-']. evt isKeystroke ifTrue: [evt keyString printString] ifFalse: ['-']. (evt virtualModifiers joinSeparatedBy: ' ') asUppercase. (evt physicalModifiers joinSeparatedBy: ' ') asUppercase. evt printString. evt virtualKey printString. evt physicalKey asString printString}). eventMorph on: #mouseEnter send: #handleEvent:emphasize: to: self; on: #mouseLeave send: #handleEvent:deemphasize: to: self; on: #mouseDown send: #handleEvent:inspect: to: self.
self addMorphBack: eventMorph.!
Item was changed: ----- Method: KeyboardExerciser>>logEventRepetition: (in category 'event handling') ----- logEventRepetition: evt
| label lastEvents box | (self submorphs last hasProperty: #repetition) ifTrue: [box := self submorphs last. label := box submorphs first] ifFalse: [ box := Morph new setProperty: #repetition toValue: true; color: Color transparent; layoutPolicy: TableLayout new; hResizing: #shrinkWrap; vResizing:#shrinkWrap; yourself. label := '' asText asMorph lock. box addMorph: label. box setProperty: #event toValue: (OrderedCollection with: self lastEvent). self addMorphBack: box].
lastEvents := box valueOfProperty: #event. lastEvents add: evt copy. box setProperty: #event toValue: lastEvents.
label newContents: (('x ', (lastEvents size)) asText addAttribute: (TextFontReference toFont: Preferences standardButtonFont); yourself). box balloonText: ('{1}{2}' format: { + lastEvents size > 10 ifTrue: ['... {1} older events and:' withCRs translated format: {lastEvents size - 10}] ifFalse: ['']. - lastEvents size > 10 ifTrue: ['... ', (lastEvents size - 10), ' older events and:', String cr] ifFalse: ['']. (lastEvents last: (10 min: lastEvents size)) joinSeparatedBy: String cr. }). box on: #mouseEnter send: #handleEvent:emphasize: to: self; on: #mouseLeave send: #handleEvent:deemphasize: to: self; on: #mouseDown send: #handleEvent:inspect: to: self.!
Item was changed: ----- Method: MenuItemMorph>>debugAction (in category 'browse') ----- debugAction
(Process forBlock: [self doButtonAction] runUntil: [:context | context selector = self effectiveActionSelector]) + debugWithTitle: ('Debug menu action "{1}" in model "{2}"' translated format: {self contents. self target printString}).! - debugWithTitle: ('Debug menu action "{1}" in model "{2}"' format: {self contents. self target printString}).!
Item was changed: ----- Method: MenuMorph>>addItem (in category 'menu') ----- addItem
| string sel | + string := Project uiManager request: 'Label for new item?' translated. - string := UIManager default request: 'Label for new item?'. string isEmpty ifTrue: [^ self]. + sel := Project uiManager request: 'Selector?' translated. - sel := UIManager default request: 'Selector?'. sel isEmpty ifFalse: [sel := sel asSymbol]. self add: string action: sel. !
Item was changed: ----- Method: MenuMorph>>addTitle (in category 'menu') ----- addTitle
| string | + string := Project uiManager request: 'Title for this menu?' translated. - string := UIManager default request: 'Title for this menu?'. string isEmpty ifTrue: [^ self]. self addTitle: string. !
Item was changed: ----- Method: MenuMorph>>detachSubMenu: (in category 'menu') ----- detachSubMenu: evt | possibleTargets item subMenu index | possibleTargets := self items select:[:any| any hasSubMenu]. possibleTargets size > 0 ifTrue:[ + index := Project uiManager - index := UIManager default chooseFrom: (possibleTargets collect:[:t| t contents asString]) + title: 'Which menu?' translated. - title: 'Which menu?'. index = 0 ifTrue:[^self]]. item := possibleTargets at: index. subMenu := item subMenu. subMenu ifNotNil: [ item subMenu: nil. item delete. subMenu stayUp: true. subMenu popUpOwner: nil. subMenu addTitle: item contents. evt hand attachMorph: subMenu]. !
Item was changed: ----- Method: MenuMorph>>showKeyboardHelp (in category 'keystroke helpers') ----- showKeyboardHelp
| help | help := self balloonMorphClass + string: 'Enter text to narrow selection\down to matching items ' translated - string: 'Enter text to narrow selection\down to matching items ' withCRs for: self corner: #topLeft. help popUpAt: self topCenter forHand: self activeHand!
Item was changed: ----- Method: MenuMorph>>toggleStayUp: (in category 'menu') ----- toggleStayUp: evt "Toggle my 'stayUp' flag and adjust the menu item to reflect its new state."
self items do: [:item | item isStayUpItem ifTrue: [self stayUp: stayUp not. stayUp + ifTrue: [item contents: 'dismiss this menu' translated] + ifFalse: [item contents: 'keep this menu up' translated]]]. - ifTrue: [item contents: 'dismiss this menu'] - ifFalse: [item contents: 'keep this menu up']]]. evt hand releaseMouseFocus: self. + stayUp ifFalse: [self topRendererOrSelf delete].! - stayUp ifFalse: [self topRendererOrSelf delete]. - !
Item was changed: ----- Method: MorphicProject>>loadFromServer: (in category 'file in/out') ----- loadFromServer: newerAutomatically "If a newer version of me is on the server, load it." | pair resp server | self assureIntegerVersion.
self isCurrentProject ifTrue: ["exit, then do the command" ^ self armsLengthCommand: #loadFromServer withDescription: 'Loading' translated ]. server := self tryToFindAServerWithMe ifNil: [^ nil]. pair := self class mostRecent: self name onServer: server. pair first ifNil: [^ self inform: ('can''t find file on server for {1}' translated format: {self name})]. self currentVersionNumber > pair second ifTrue: [ ^ self inform: ('That server has an older version of the project.' translated)]. version = (Project parseProjectFileName: pair first) second ifTrue: [ resp := (UIManager default chooseFrom: (Array with: 'Reload anyway' translated with: 'Cancel' translated withCRs) title: 'The only changes are the ones you made here.' translated). resp ~= 1 ifTrue: [^ nil] ] ifFalse: [ newerAutomatically ifFalse: [ resp := (UIManager default + chooseFrom: {'Load it' translated. 'Cancel' translated} + title: 'A newer version exists on the server.' translated). - chooseFrom: #('Load it' 'Cancel') - title: 'A newer version exists on the server.'). resp ~= 1 ifTrue: [^ nil] ]. ].
"let's avoid renaming the loaded change set since it will be replacing ours" self projectParameters at: #loadingNewerVersion put: true.
ComplexProgressIndicator new targetMorph: nil; historyCategory: 'project loading'; withProgressDo: [ ProjectLoading installRemoteNamed: pair first from: server named: self name in: parentProject + ]! - ] - !
Item was changed: ----- Method: ObjectExplorerWrapper>>asString (in category 'converting') ----- asString | explorerString label separator | explorerString := [self objectString] on: Error + do: ['<error: {1} in {2}: evaluate "{3}" to debug>' translated format: {self object class name. #asExplorerString. self itemName , ' asExplorerString'}]. - do: ['<error: ', self object class name, ' in asExplorerString: evaluate "' , self itemName , ' asExplorerString" to debug>']. (explorerString includes: Character cr) ifTrue: [explorerString := explorerString withSeparatorsCompacted].
label := self itemName ifNil: ['']. (label includes: Character cr) ifTrue: [label := label withSeparatorsCompacted]. separator := self class showContentsInColumns ifTrue: [String tab] ifFalse: [label ifEmpty: [''] ifNotEmpty: [': ']].
^ '{1}{2}{3}' format: {label. separator. explorerString}!
Item was changed: ----- Method: PasteUpMorph>>saveOnFile (in category 'objects from disk') ----- saveOnFile "Ask the user for a filename and save myself on a SmartReferenceStream file. Writes out the version and class structure. The file is fileIn-able. UniClasses will be filed out."
| aFileName fileStream |
self flag: #bob0302. self isWorldMorph ifTrue: [^self project saveAs].
+ aFileName := ('my {1}' translated format: {self class name}) , '.project' asFileName. "do better?" - aFileName := ('my {1}.project' translated format: {self class name}) asFileName. "do better?" aFileName := UIManager default saveFilenameRequest: 'File name?' translated initialAnswer: aFileName. aFileName ifNil: [^ Beeper beep]. self allMorphsDo: [:m | m prepareToBeSaved].
fileStream := FileStream newFileNamed: aFileName. fileStream fileOutClass: nil andObject: self. "Puts UniClass definitions out anyway"!
Item was changed: ----- Method: PluggableButtonMorph>>debugAction (in category 'debug menu') ----- debugAction
self updateArguments.
(Process forBlock: [self doButtonAction] runUntil: [:context | context selector = self effectiveActionSelector]) + debugWithTitle: ('Debug button action "{1}" in model "{2}"' translated format: {self label. self target printString}).! - debugWithTitle: ('Debug button action "{1}" in model "{2}"' format: {self label. self target printString}).!
Item was changed: ----- Method: PluggableListMorph>>debugGetList (in category 'debug and other') ----- debugGetList
(Process forBlock: [model perform: getListSelector] runUntil: [:context | context selector = getListSelector]) + debugWithTitle: ('Debug get-list invocation in model "{1}"' translated format: {model printString}).! - debugWithTitle: ('Debug get-list invocation in model "{1}"' format: {model printString}).!
Item was changed: ----- Method: PolygonMorph>>smoothOrSegmentedPhrase (in category 'access') ----- smoothOrSegmentedPhrase - | lineName | - lineName := (closed - ifTrue: ['outline'] - ifFalse: ['line']) translated.
+ | lineName | + lineName := closed + ifTrue: ['outline' translated] + ifFalse: ['line' translated]. + + ^ self isCurve + ifTrue: ['make segmented {1}' translated format: {lineName}] + ifFalse: ['make smooth {1}' translated format: {lineName}]! - ^ self isCurve - ifTrue: ['make segmented {1}' translated format: {lineName}] - ifFalse: ['make smooth {1}' translated format: {lineName}].!
Item was changed: ----- Method: SmalltalkEditor>>tallySelection (in category 'do-its') ----- tallySelection "Treat the current selection as an expression; evaluate it and return the time took for this evaluation" | code result rcvr ctxt v | self lineSelectAndEmptyCheck: [^ self].
(model respondsTo: #doItReceiver) ifTrue: [ rcvr := model doItReceiver. ctxt := model doItContext] ifFalse: [rcvr := ctxt := nil]. result := [ | cm | code := self selectionAsStream. cm := rcvr class evaluatorClass new compiledMethodFor: code in: ctxt to: rcvr notifying: self ifFail: [morph flash. ^ self]. Time millisecondsToRun: [v := cm valueWithReceiver: rcvr arguments: (ctxt ifNil: [#()] ifNotNil: [{ctxt}]) ]. ] on: OutOfScopeNotification do: [ :ex | ex resume: true]. UIManager default + inform: ('<b>Expression</b>{1}<br>{2}<br><br><b>Time</b> (compile and execute)<br>{3} ms<br><br><b>Result</b><br>{4}' translated format: { - inform: ('<b>Expression</b>{1}<br>{2}<br><br><b>Time</b> (compile and execute)<br>{3} ms<br><br><b>Result</b><br>{4}' format: { rcvr ifNil: [''] ifNotNil: [' (', (rcvr printString truncateWithElipsisTo: 20), ')']. (code contents truncateWithElipsisTo: 200) copyReplaceAll: String cr with: '<br>'. result printString. v printString truncateWithElipsisTo: 100}) asTextFromHtml.!
Item was changed: ----- Method: TextAnchor class>>alignmentExamples (in category 'examples') ----- alignmentExamples "self alignmentExamples" | anchoredMorph textMorph text demoMorph | demoMorph := Morph new changeTableLayout; color: Color white; hResizing: #shrinkWrap; vResizing: #shrinkWrap; yourself. #(top center bottom) do: [:morphAlignment | #(top center baseline bottom) do: [:textAlignment | anchoredMorph := Morph new. anchoredMorph textAnchorProperties verticalAlignment: {morphAlignment . textAlignment}. anchoredMorph textAnchorProperties padding: (anchoredMorph textAnchorProperties padding top: 10). text := Text streamContents: [ :stream | stream + nextPutAll: ('Here is an {1}, {2} example: ' translated format: {morphAlignment . textAlignment}); - nextPutAll: ('Here is an {1}, {2} example: ' format: {morphAlignment . textAlignment}); nextPutAll: (Text string: Character startOfHeader asString attributes: {TextAnchor new anchoredMorph: anchoredMorph. TextColor color: Color transparent}); + nextPutAll: ' with the morph in the text.' translated]. - nextPutAll: ' with the morph in the text.']. textMorph := text asMorph. textMorph height: 100. demoMorph addMorph: textMorph]]. demoMorph openInWorld!
Item was changed: ----- Method: TextEditor>>findReplace (in category 'menu messages') ----- findReplace
self setSearchFromSelectionOrHistory; setReplacementFromHistory.
(Project uiManager + request: 'Find what to replace?' translated - request: 'Find what to replace?' initialAnswer: FindText) ifNotEmpty: [:find |
(Project uiManager + request: ('Replace ''{1}'' with?' translated format: {find}) - request: ('Replace ''{1}'' with?' format: {find}) initialAnswer: (ChangeText ifEmpty: [find]) onCancelReturn: nil) ifNotNil: [:replace |
FindText := find. ChangeText := replace. self findReplaceAgainNow]]!
Item was changed: ----- Method: TheWorldMainDockingBar>>scaleFactorsOn: (in category 'submenu - extras') ----- 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)' translated] ifFalse: ['']] - ifTrue: [' (recommended)'] ifFalse: ['']] }); target: Display; selector: #relativeUiScaleFactor:; arguments: {scale / 100}]]. menu addLine. menu addItem: [:item | item + contents: ((presets includes: currentScaleFactor) not ifTrue: ['<yes>' , 'Custom: ' translated, currentScaleFactor, '% ...'] ifFalse: ['<no>' , 'Other scale factor...' translated]); - contents: ((presets includes: currentScaleFactor) not ifTrue: ['<yes> Custom: ', currentScaleFactor, '% ...'] ifFalse: ['<no>Other scale factor...']); target: self; selector: #chooseCustomScaleFactor].!
packages@lists.squeakfoundation.org