David T. Lewis uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-hjh.1351.mcz
==================== Summary ====================
Name: Morphic-hjh.1351
Author: hjh
Time: 28 September 2017, 11:39:54.321636 am
UUID: 8eb78880-4b1d-4e8b-b961-d4d5c49d1c47
Ancestors: Morphic-mt.1350
Removed comment from Editor referring to
SimpleEditor and
CellStyleEditor
which are not in the image.
=============== Diff against Morphic-mt.1350 ===============
Item was changed:
Object subclass: #Editor
instanceVariableNames: 'morph selectionShowing'
classVariableNames: 'BlinkingCursor DestructiveBackWord DumbbellCursor KeystrokeActions SelectionsMayShrink'
poolDictionaries: ''
category: 'Morphic-Text Support'!
+ !Editor commentStamp: 'hjh 9/28/2017 11:37' prior: 0!
- !Editor commentStamp: '<historical>' prior: 0!
New text editors.
TextEditor provides most of the functionality that used to be in TextMorphEditor.
SmalltalkEditor is has Smalltalk code specific features.
+ !
- SimpleEditor provides basic functionality for single line text editing. It does not handle fonts and styles, aligning and Smalltalk utilities. It handles one single line.
- CellStyleEditor allows entering alphabetic characters using only number keys, like many cell phones do.!
David T. Lewis uploaded a new version of Compression to project The Trunk:
http://source.squeak.org/trunk/Compression-dtl.54.mcz
==================== Summary ====================
Name: Compression-dtl.54
Author: dtl
Time: 28 September 2017, 8:00:37.70922 am
UUID: 97cfd1cd-0c07-40a7-92e9-4ea35b82fd5e
Ancestors: Compression-nice.53
In an archive file is too short, or more commonly if it is empty, identify its name in the error message. This is helpful in the case of a corrupt file in a package-cache, which may have been created due to some earlier system or network problem.
=============== Diff against Compression-nice.53 ===============
Item was changed:
----- Method: ZipArchive class>>findEndOfCentralDirectoryFrom: (in category 'constants') -----
findEndOfCentralDirectoryFrom: stream
"Seek in the given stream to the end, then read backwards until we find the
signature of the central directory record. Leave the file positioned right
before the signature.
Answers the file position of the EOCD, or 0 if not found."
| data fileLength seekOffset pos maxOffset |
stream setToEnd.
fileLength := stream position.
"If the file length is less than 18 for the EOCD length plus 4 for the signature, we have a problem"
+ fileLength < 22 ifTrue: [^ self error: 'file is too short: ', stream name].
- fileLength < 22 ifTrue: [^ self error: 'file is too short'].
seekOffset := 0.
pos := 0.
data := ByteArray new: 4100.
maxOffset := 40960 min: fileLength. "limit search range to 40K"
[
seekOffset := (seekOffset + 4096) min: fileLength.
stream position: fileLength - seekOffset.
data := stream next: (4100 min: seekOffset) into: data startingAt: 1.
pos := self lastIndexOfPKSignature: EndOfCentralDirectorySignature in: data.
pos = 0 and: [seekOffset < maxOffset]
] whileTrue.
^ pos > 0
ifTrue: [ | newPos | stream position: (newPos := (stream position + pos - seekOffset - 1)). newPos]
ifFalse: [0]!
tim Rowledge uploaded a new version of SUnitGUI to project The Trunk:
http://source.squeak.org/trunk/SUnitGUI-tpr.68.mcz
==================== Summary ====================
Name: SUnitGUI-tpr.68
Author: tpr
Time: 25 September 2017, 2:40:47.67289 pm
UUID: 5d33c773-e628-446f-88e8-47bfdbf2dc22
Ancestors: SUnitGUI-ul.67
Add a simple way to run a single failed method in a MessageTally.
=============== Diff against SUnitGUI-ul.67 ===============
Item was changed:
----- Method: TestRunner>>failureMenu: (in category 'accessing-menu') -----
failureMenu: aMenu
+ ^ aMenu
+ add: 'Profile this test' action: #runProfileOnFailure;
+ yourself!
- ^ aMenu!
Item was added:
+ ----- Method: TestRunner>>runProfileOnFailure (in category 'actions') -----
+ runProfileOnFailure
+ "if we have selected a failure case, run it within a MessageTAlly and see what is taking time"
+
+ failedSelected ifNotNil: [self
+ basicRunSuite: (TestSuite new addTest: failedSelected;
+ yourself)
+ do: [:each | MessageTally
+ spyOn: [self runTest: each]]]!
tim Rowledge uploaded a new version of System to project The Trunk:
http://source.squeak.org/trunk/System-tpr.964.mcz
==================== Summary ====================
Name: System-tpr.964
Author: tpr
Time: 25 September 2017, 12:03:05.473661 pm
UUID: ee9898d1-8279-4c25-b78c-f423cf7eb408
Ancestors: System-mt.963
A proposed improvement to the class comment to reflect recent changes, along with adding the most basic property setting message to the request instances.
I suggest that there are a number of other messages that ought to be passed along in a similar manner but others are likely to have a better idea of the right ones.
=============== Diff against System-mt.963 ===============
Item was changed:
Object subclass: #UserInterfaceTheme
instanceVariableNames: 'properties name next ignoreApply lastScaleFactor'
classVariableNames: 'All Current Default'
poolDictionaries: ''
category: 'System-Support'!
+ !UserInterfaceTheme commentStamp: 'tpr 9/25/2017 11:59' prior: 0!
- !UserInterfaceTheme commentStamp: '<historical>' prior: 0!
A UserInterfaceTheme is a dictionary of preferred visual-properties; colors, borderStyles, borderWidths, fonts, forms, etc. used to color and style the IDE.
Accessing The Theme
+ To access the proper UserInterfaceTheme instance for an object, send it #userInterfaceTheme. The default implementation on Object provides the an instance of UserInterfaceThemeRequest that provides a lightweight, clean proxy of the actual theme in-use by the IDE at the current time. To do anything more sophisticated than basic query and setting of properties you must ask the proxy for the actual theme by sending #theme.
- To access the proper UserInterfaceTheme instance for an object, send it #userInterfaceTheme. The default implementation on Object provides the one instance of that is in-use by the IDE at the current time.
Customizing The Theme
We can ask the userInterfaceTheme for the value of any visual-property, by name:
mySystemWindow userInterfaceTheme closeBoxImage
+ Initially that would answer nil, which causes the legacy code to use whatever default it's always used. To override various visual-properties of any kind of object, the #set: for: to: message can be used. For example,
- Initially, the above answers nil, which causes the legacy code to use whatever default it's always used. To override various visual-properties of any kind of object, the #set: onAny: to: message can be used. For example,
myUserInterfaceTheme
set: #closeBoxImage
for: SystemWindow
to: MenuIcons smallCancelIcon
+ Now the closeBoxImage message will answer the MenuIcons icon instead of nil.
+
Alternatively, values may be derived based on other values in the theme, as in:
myUserInterfaceTheme
set: #color
for: FillInTheBlankMorph
to: { MenuMorph->#color. #twiceDarker }
+ This would make FillInTheBlankMorph use the same color as a MenuMorph but twiceDarker, providing a clean way to build coherent seets of colors within a theme. SystemWindow's code can be changed to use the expression above to access elements of the theme.
- Now, the accessing expression, above, will answer will answer MenuIcons' smallCancelIcon instead of nil. SystemWindow's code can be changed to use the expression above to access elements of the theme.
Upgrading Legacy Code
Following the introduction of this class, various client code all around the system must be modified to access it. This variety of legacy code uses a variety of methods to specify their visual properties:
1) a hard-coded values.
2) a values derived from some other value.
3) providing local storage for a settable value which can be nil.
4) providing local storage for a settable value which is expected to always have a particular valid value (never nil).
The requirement, for each case, is to let the value be overridden.
The solution for each of the above should be handled respectively to the above list, as follows:
1) Check the userInterfaceTheme, if that property returns nil, use the legacy hard-coded value. (see example: SystemWindow>>#createCloseBox).
2) Nothing to do -- simply perform the same derivation on the result of (1).
3) Check the local storage, if present, use it. If nil, then check the userInterfaceTheme, if it has this property present, use it, else return nil.
4) Check the userInterfaceTheme, if the property is not nil, use it, otherwise use the local value.
Tool Support
If a new access to #userInterfaceTheme is added to the code, be sure to add the property and its description to the #themeSettings for that class. See implementors of #themeSettings for examples.!
Item was added:
+ ----- Method: UserInterfaceThemeRequest>>set:for:to: (in category 'accessing') -----
+ set: propertySymbol for: aClassOrSymbol to: valueObject
+ "Where aClass asks its userInterfaceTheme for propertySymbol, provide valueObject. Pass this on to the actual theme"
+
+ ^self theme set: propertySymbol for: aClassOrSymbol to: valueObject
+
+ !
Marcel Taeumel uploaded a new version of Tests to project The Trunk:
http://source.squeak.org/trunk/Tests-mt.384.mcz
==================== Summary ====================
Name: Tests-mt.384
Author: mt
Time: 23 September 2017, 10:54:37.809102 am
UUID: e04a490b-01cb-bc4d-aca8-76336e7ce5a4
Ancestors: Tests-mt.383
UI Themes: Updates tests and benchmark for the latest changes in System-mt.963.
=============== Diff against Tests-mt.383 ===============
Item was added:
+ ----- Method: UserInterfaceThemeTest>>test27DanglingTheme (in category 'tests') -----
+ test27DanglingTheme
+
+ self
+ assert: (UserInterfaceTheme allThemes includes: UserInterfaceTheme current)
+ description: 'The current user interface theme is not registered.'.!
Item was removed:
- ----- Method: UserInterfaceThemeTest>>test27ScopeIntegrity (in category 'tests') -----
- test27ScopeIntegrity
- "If application code manages to use Object >> #userInterfaceTheme without invoking the DNU dispatch directly afterwards, the theme's scope might get inconsistent. Even though this should usually never happen, check for it to be sure."
-
- | issues |
- issues := OrderedCollection new.
- UserInterfaceTheme allThemes do: [:uit |
- (uit instVarNamed: #scope) isEmpty ifFalse: [issues add: uit]].
- UserInterfaceTheme current in: [:uit |
- (UserInterfaceTheme allThemes includes: uit)
- ifFalse: [(uit instVarNamed: #scope) isEmpty ifFalse: [issues add: uit]]].
- self assert: issues isEmpty description: 'Some user interface themes have an inconsistent scope state, which can interfere with GC.'.!
Item was removed:
- ----- Method: UserInterfaceThemeTest>>test28DanglingTheme (in category 'tests') -----
- test28DanglingTheme
-
- self
- assert: (UserInterfaceTheme allThemes includes: UserInterfaceTheme current)
- description: 'The current user interface theme is not registered.'.!
Item was changed:
----- Method: UserInterfaceThemeTestObject class>>benchLookup (in category 'benchmark') -----
benchLookup
"
+ Microsoft Surface Pro 3, Windows 10 v1703, CogVM 201708092224, Squeak 6.0alpha #17398
+ Up to '280,000 per second. 3.57 microseconds per run.' -- leaves enough room for quirky morphs that keep on drawing themselves based on direct theme lookup.
- Microsoft Surface Pro 3, Windows 10 v1511, CogVM r201606301459, Squeak 5.1alpha #16138
- '210,000 per second. 4.76 microseconds per run.' -- leaves enough room for quirky morphs that keep on drawing themselves based on direct theme lookup.
I think this setup is really heavy. Morphs should not look-up things that often. They can cache. Anyway:
- link through 3 themes
- look up superclasses up to ProtoObject (for each theme!!)
self benchLookup"
| c t1 t2 t3 m result |
c := UserInterfaceTheme current.
m := UserInterfaceThemeTestObject new.
t1 := UserInterfaceTheme new name: #benchmarkOne.
t2 := UserInterfaceTheme new name: #benchmarkTwo.
t3 := UserInterfaceTheme new name: #benchmarkThree.
t3 set: #testColor for: ProtoObject to: Color white.
t1 link: t2.
t2 link: t3.
t1 apply.
result := OrderedCollection new.
[
+ 3 timesRepeat: [
+ Smalltalk garbageCollect.
+ result add: [m getTestColor] bench].
- 3 timesRepeat: [result add: [m getTestColor] bench].
] ensure: [c apply].
result explore.!
Marcel Taeumel uploaded a new version of System to project The Trunk:
http://source.squeak.org/trunk/System-mt.963.mcz
==================== Summary ====================
Name: System-mt.963
Author: mt
Time: 23 September 2017, 10:47:56.940596 am
UUID: d6e13c37-16d6-c34b-a3cf-64afaf4cfaba
Ancestors: System-tpr.962
Removes "scope" from UI themes. Encapsulates look-up for properties in the current theme into short-living a request object.
Why?
1. Dispels some magic from UserInterfaceTheme class.
2. Supports keeping reference to the result of "self userInterfaceTheme" without annoying the GC.
3. Speeds up look-up performance by up to 5%.
=============== Diff against System-tpr.962 ===============
Item was changed:
----- Method: Object>>userInterfaceTheme (in category '*System-Preferences') -----
userInterfaceTheme
"Call this to conveniently access properties from the current user interface theme."
+ ^ UserInterfaceThemeRequest new
+ target: self;
+ theme: UserInterfaceTheme current;
- ^ UserInterfaceTheme current
- pushScope: self;
yourself!
Item was changed:
Object subclass: #UserInterfaceTheme
+ instanceVariableNames: 'properties name next ignoreApply lastScaleFactor'
- instanceVariableNames: 'scope properties name next ignoreApply lastScaleFactor'
classVariableNames: 'All Current Default'
poolDictionaries: ''
category: 'System-Support'!
!UserInterfaceTheme commentStamp: '<historical>' prior: 0!
A UserInterfaceTheme is a dictionary of preferred visual-properties; colors, borderStyles, borderWidths, fonts, forms, etc. used to color and style the IDE.
Accessing The Theme
To access the proper UserInterfaceTheme instance for an object, send it #userInterfaceTheme. The default implementation on Object provides the one instance of that is in-use by the IDE at the current time.
Customizing The Theme
We can ask the userInterfaceTheme for the value of any visual-property, by name:
mySystemWindow userInterfaceTheme closeBoxImage
Initially, the above answers nil, which causes the legacy code to use whatever default it's always used. To override various visual-properties of any kind of object, the #set: onAny: to: message can be used. For example,
myUserInterfaceTheme
set: #closeBoxImage
for: SystemWindow
to: MenuIcons smallCancelIcon
Alternatively, values may be derived based on other values in the theme, as in:
myUserInterfaceTheme
set: #color
for: FillInTheBlankMorph
to: { MenuMorph->#color. #twiceDarker }
Now, the accessing expression, above, will answer will answer MenuIcons' smallCancelIcon instead of nil. SystemWindow's code can be changed to use the expression above to access elements of the theme.
Upgrading Legacy Code
Following the introduction of this class, various client code all around the system must be modified to access it. This variety of legacy code uses a variety of methods to specify their visual properties:
1) a hard-coded values.
2) a values derived from some other value.
3) providing local storage for a settable value which can be nil.
4) providing local storage for a settable value which is expected to always have a particular valid value (never nil).
The requirement, for each case, is to let the value be overridden.
The solution for each of the above should be handled respectively to the above list, as follows:
1) Check the userInterfaceTheme, if that property returns nil, use the legacy hard-coded value. (see example: SystemWindow>>#createCloseBox).
2) Nothing to do -- simply perform the same derivation on the result of (1).
3) Check the local storage, if present, use it. If nil, then check the userInterfaceTheme, if it has this property present, use it, else return nil.
4) Check the userInterfaceTheme, if the property is not nil, use it, otherwise use the local value.
Tool Support
If a new access to #userInterfaceTheme is added to the code, be sure to add the property and its description to the #themeSettings for that class. See implementors of #themeSettings for examples.!
Item was removed:
- ----- Method: UserInterfaceTheme>>doesNotUnderstand: (in category 'lookup') -----
- doesNotUnderstand: aMessage
- "In order to be able to use a UserInterfaceTheme as a container of fairly arbitrary properties whilst making it seem like we are sending regular messages as a way of accessing those properties we can handle the dNU: and check the not understood message name against our property list. This is clever, devious, interesting and may confuse users until they get to see an explanation like this"
- "Answer nil or a value for the property specified by aMessage's #selector. Searching for the property proceeds by
- a) searching my dictionary for a key made up of an Association with a key of the class of the 'client' and a value of the message name. For example SimpleButtonMorph->borderColor
- b) searching again for a key made from the superclass(es) of the client - e.g. RectangleMorph->borderColor and then if required BorderedMorph->borderColor etc.
- c) if there is a linked theme, search it in the same manner.
-
- As an extreme example, consider a basic theme with a linked theme specifically for buttons.
- mySimpleButtonMorph borderColor
- would search the basic theme for SimpleButtonMorph->borderColor, the superclass equivalents as in b) above, then search the linked theme for SimpleButtonMorph->borderColor and, we hope, find something meaningful"
-
- aMessage numArgs > 0 ifTrue: [^ super doesNotUnderstand: aMessage].
- scope isEmpty ifTrue: [^ super doesNotUnderstand: aMessage].
-
- ^ [self get: scope top class -> aMessage selector]
- ensure: [scope pop]!
Item was changed:
----- Method: UserInterfaceTheme>>initialize (in category 'initialization') -----
initialize
super initialize.
name := 'unnamed'.
+ properties := Dictionary new.!
- properties := Dictionary new.
- scope := Stack new!
Item was changed:
----- Method: UserInterfaceTheme>>postCopy (in category 'copying') -----
postCopy
"Keep same name and linked next."
super postCopy.
+ properties := properties copy.!
- properties := properties copy.
- scope := nil!
Item was removed:
- ----- Method: UserInterfaceTheme>>pushScope: (in category 'private') -----
- pushScope: anObject
- scope push: anObject!
Item was added:
+ Object subclass: #UserInterfaceThemeRequest
+ instanceVariableNames: 'target theme'
+ classVariableNames: ''
+ poolDictionaries: ''
+ category: 'System-Support'!
+
+ !UserInterfaceThemeRequest commentStamp: 'mt 9/23/2017 10:37' prior: 0!
+ In order to be able to use a UserInterfaceTheme as a container of fairly arbitrary properties whilst making it seem like we are sending regular messages as a way of accessing those properties we can handle the dNU: and check the not understood message name against our property list. This is clever, devious, interesting and may confuse users until they get to see an explanation like this.
+
+ Answer nil or a value for the property specified by aMessage's #selector. Searching for the property proceeds by
+ a) searching my dictionary for a key made up of an Association with a key of the class of the 'client' and a value of the message name. For example SimpleButtonMorph->borderColor
+ b) searching again for a key made from the superclass(es) of the client - e.g. RectangleMorph->borderColor and then if required BorderedMorph->borderColor etc.
+ c) if there is a linked theme, search it in the same manner.
+
+ As an extreme example, consider a basic theme with a linked theme specifically for buttons.
+
+ mySimpleButtonMorph borderColor
+
+ ... would search the basic theme for SimpleButtonMorph->borderColor, the superclass equivalents as in b) above, then search the linked theme for SimpleButtonMorph->borderColor and, we hope, find something meaningful.!
Item was added:
+ ----- Method: UserInterfaceThemeRequest>>doesNotUnderstand: (in category 'lookup') -----
+ doesNotUnderstand: aMessage
+ "Look up the visual-attribute specified by aMessage's #selector in the current theme for the current target object."
+
+ ^ aMessage numArgs = 0
+ ifTrue: [self theme get: self target class -> aMessage selector]
+ ifFalse: [super doesNotUnderstand: aMessage]!
Item was added:
+ ----- Method: UserInterfaceThemeRequest>>target (in category 'accessing') -----
+ target
+
+ ^ target
+ !
Item was added:
+ ----- Method: UserInterfaceThemeRequest>>target: (in category 'accessing') -----
+ target: anObject
+
+ target := anObject.
+ !
Item was added:
+ ----- Method: UserInterfaceThemeRequest>>theme (in category 'accessing') -----
+ theme
+
+ ^ theme
+ !
Item was added:
+ ----- Method: UserInterfaceThemeRequest>>theme: (in category 'accessing') -----
+ theme: anObject
+
+ theme := anObject.
+ !
Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.1350.mcz
==================== Summary ====================
Name: Morphic-mt.1350
Author: mt
Time: 20 September 2017, 8:17:14.164191 pm
UUID: a858e498-8304-9c48-a4d8-06e6fc226960
Ancestors: Morphic-tpr.1349
Fixes a mouse-focus bug that has revealed itself in the score player morph when changing the instruments for the tracks.
Actually, we cannot just save/restore the moues focus for this modal dialog invocation. If that invocation comes after a mouse-down, it will mess up Morphic's assumption that there will be a mouse-up to clear the focus, which already happened in the above case.
=============== Diff against Morphic-tpr.1349 ===============
Item was changed:
----- Method: DialogWindow>>getUserResponse (in category 'running') -----
getUserResponse
| hand world |
(ProvideAnswerNotification signal: self message asString)
ifNotNil: [:answer|
^ answer = #default
ifTrue: [result]
ifFalse: [answer]].
self message ifEmpty: [messageMorph delete]. "Do not waste space."
self paneMorph submorphs ifEmpty: [self paneMorph delete]. "Do not waste space."
+
-
hand := self currentHand.
world := self currentWorld.
+
-
self fullBounds.
self center: preferredPosition.
self bounds: (self bounds translatedToBeWithin: world bounds).
self openInWorld: world.
hand keyboardFocus in: [:priorKeyboardFocus |
+ self exclusive ifTrue: [hand newMouseFocus: self].
+ hand newKeyboardFocus: self.
- hand mouseFocus in: [:priorMouseFocus |
- self exclusive ifTrue: [hand newMouseFocus: self].
- hand newKeyboardFocus: self.
+ [self isInWorld] whileTrue:[world doOneSubCycle].
- [self isInWorld] whileTrue:[world doOneSubCycle].
+ hand newKeyboardFocus: priorKeyboardFocus.
+ hand releaseMouseFocus].
- hand newKeyboardFocus: priorKeyboardFocus.
- self exclusive ifTrue: [
- hand newMouseFocus: priorMouseFocus]]].
^ result!