Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.808.mcz
==================== Summary ====================
Name: Morphic-mt.808
Author: mt
Time: 2 April 2015, 9:29:45.666 am
UUID: c0476a80-1468-aa46-bd81-9cbfd132266e
Ancestors: Morphic-mt.807
Text fields only show balloon if it has no text. The balloon text will be rendered in that case.
=============== Diff against Morphic-mt.807 ===============
Item was changed:
+ ----- Method: PluggableTextMorph>>wantsBalloon (in category 'halos and balloon help') -----
- ----- Method: PluggableTextMorph>>wantsBalloon (in category 'as yet unclassified') -----
wantsBalloon
^ self textMorph contents notEmpty and: [super wantsBalloon]!
Marcel Taeumel uploaded a new version of Morphic to project The Trunk:
http://source.squeak.org/trunk/Morphic-mt.807.mcz
==================== Summary ====================
Name: Morphic-mt.807
Author: mt
Time: 2 April 2015, 9:22:53.044 am
UUID: bfd9d718-68d4-f749-932e-755c12a3928d
Ancestors: Morphic-mt.806
Fixed #scrollToShow:, which needed an additional offset-lock, because scroll bars tend to call back their float values to the pane, which then tries to calculate pixels again.
=============== Diff against Morphic-mt.806 ===============
Item was changed:
MorphicModel subclass: #ScrollPane
+ instanceVariableNames: 'scrollBar scroller retractableScrollBar scrollBarOnLeft getMenuSelector getMenuTitleSelector scrollBarHidden hasFocus hScrollBar lockOffset'
- instanceVariableNames: 'scrollBar scroller retractableScrollBar scrollBarOnLeft getMenuSelector getMenuTitleSelector scrollBarHidden hasFocus hScrollBar'
classVariableNames: ''
poolDictionaries: ''
category: 'Morphic-Windows'!
!ScrollPane commentStamp: 'mk 8/9/2005 10:34' prior: 0!
The scroller (a transform) of a scrollPane is driven by the scrollBar. The scroll values vary from 0.0, meaning zero offset to 1.0 meaning sufficient offset such that the bottom of the scrollable material appears 3/4 of the way down the pane. The total distance to achieve this range is called the totalScrollRange.
Basic clue about utilization of the ScrollPane class is given in:
ScrollPane example1.
ScrollPane example2.!
Item was changed:
----- Method: ScrollPane>>hScrollBarValue: (in category 'scrolling') -----
hScrollBarValue: scrollValue
| x |
+ lockOffset == true ifTrue: [^ self].
+
self hIsScrollbarShowing ifFalse:
[^scroller offset: (0 - self hMargin)@scroller offset y].
((x := self hLeftoverScrollRange * scrollValue) <= 0)
ifTrue:[x := 0 - self hMargin].
scroller offset: (x@scroller offset y)
!
Item was changed:
----- Method: ScrollPane>>scrollToShow: (in category 'scrolling') -----
scrollToShow: aRectangle
+ "We have to lock the callback into me because rounding errors in scrollbar values would reset the offset to a different value. The given rectangle may not be visible anymore."
scroller offset: (self offsetToShow: aRectangle).
+ lockOffset := true.
+ self setScrollDeltas.
+ lockOffset := false.!
- self setScrollDeltas.!
Item was changed:
----- Method: ScrollPane>>vScrollBarValue: (in category 'scrolling') -----
vScrollBarValue: scrollValue
scroller hasSubmorphs ifFalse: [^ self].
+ lockOffset == true ifFalse: [
+ scroller offset: (scroller offset x @ (self vLeftoverScrollRange * scrollValue) rounded)].
- scroller offset: (scroller offset x @ (self vLeftoverScrollRange * scrollValue) rounded)
!
Marcel Taeumel uploaded a new version of Tools to project The Trunk:
http://source.squeak.org/trunk/Tools-mt.574.mcz
==================== Summary ====================
Name: Tools-mt.574
Author: mt
Time: 2 April 2015, 9:06:20.379 am
UUID: ccf2eb3b-c755-e342-8611-21ea886d0fe9
Ancestors: Tools-mt.573
Added #hMargin to trees. Feature moved from scroll panes to particular tools. Having this, tree selection will ecompass also this margin and no white pixels will be there.
Having this, it is a cosmetic change.
=============== Diff against Tools-mt.573 ===============
Item was added:
+ ----- Method: IndentingListItemMorph>>hMargin (in category 'accessing') -----
+ hMargin
+
+ ^ 3!
Item was changed:
----- Method: IndentingListItemMorph>>toggleRectangle (in category 'private') -----
toggleRectangle
| h |
h := bounds height.
+ ^(bounds left + self hMargin + (12 * indentLevel)) @ bounds top extent: 12@h!
- ^(bounds left + (12 * indentLevel)) @ bounds top extent: 12@h!
Marcel Taeumel uploaded a new version of Tools to project The Trunk:
http://source.squeak.org/trunk/Tools-mt.573.mcz
==================== Summary ====================
Name: Tools-mt.573
Author: mt
Time: 2 April 2015, 9:02:26.26 am
UUID: 44868c77-bafd-574f-bb56-3eb95728a7ba
Ancestors: Tools-cmm.572
Revert last change in opening explorer because additional call to #rootObject: not needed.
If there is a bug, which I cannot reproduce in my trunk image, it may lie somewhere else. Anyway, #rootObject: should always update the model correctly. No need to call it twice.
=============== Diff against Tools-cmm.572 ===============
Item was changed:
----- Method: ObjectExplorer>>openExplorerFor:withLabel: (in category 'user interface') -----
openExplorerFor: anObject withLabel: label
+ "ObjectExplorer new openExplorerFor: Smalltalk withLabel: 'Smalltalk'"
+
+ ToolBuilder open: self label: label.
+ self rootObject: anObject.!
- "ObjectExplorer new openExplorerFor: Smalltalk withLabel: 'Smalltalk'"
- "Model must be set to support Reuse Windows preference."
- self rootObject: anObject.
- ToolBuilder
- open: self
- label: label.
- "Set model again to ensure window title updated (hmm, why not the first time?)."
- self rootObject: anObject!
Marcel Taeumel uploaded a new version of ToolBuilder-Morphic to project The Trunk:
http://source.squeak.org/trunk/ToolBuilder-Morphic-mt.115.mcz
==================== Summary ====================
Name: ToolBuilder-Morphic-mt.115
Author: mt
Time: 2 April 2015, 8:54:11.711 am
UUID: 873458fe-19e8-0449-a9d1-c52476bc1077
Ancestors: ToolBuilder-Morphic-cmm.114
Revert something that was re-introduced in cmm.112 but already reverted before.
#selectPath:in: must send #setSelectedMorph: because both are callbacks from #update: within the tree morph.
#selection only talks to the model. We do not have an equivalent for tree-path selection, which talks to the model, yet.
=============== Diff against ToolBuilder-Morphic-cmm.114 ===============
Item was changed:
----- Method: PluggableTreeMorph>>selectPath:in: (in category 'selection') -----
selectPath: path in: listItem
+ path isEmpty ifTrue: [^self setSelectedMorph: nil].
- path isEmpty ifTrue: [^self selection: nil].
-
listItem withSiblingsDo: [:each |
(each complexContents item = path first) ifTrue: [
each isExpanded ifFalse: [
each toggleExpandedState.
self adjustSubmorphPositions.
].
each changed.
path size = 1 ifTrue: [
+ ^self setSelectedMorph: each
- ^self selection: each complexContents
].
+ each firstChild ifNil: [^self setSelectedMorph: nil].
- each firstChild ifNil: [^self selection: nil].
^self selectPath: path allButFirst in: each firstChild
].
].
+ ^self setSelectedMorph: nil
- ^self selection: nil
!
Item was changed:
----- Method: PluggableTreeMorph>>setSelectedMorph: (in category 'selection') -----
setSelectedMorph: aMorph
selectedWrapper := aMorph complexContents.
+
"Let the model now about the selected object, not wrapper."
setSelectionSelector ifNotNil: [:symbol |
model
perform: symbol
+ with: (selectedWrapper ifNotNil: [:w | w item])].
+
- with: (selectedWrapper ifNotNil: [ selectedWrapper item ])].
"The model may not have access to the parent object in terms of this tree structure."
setSelectedParentSelector ifNotNil: [:symbol |
model
perform: symbol
+ with: (selectedWrapper ifNotNil: [:w | w parent ifNotNil: [:pw | pw item]])].!
- with: (selectedWrapper ifNotNil: [selectedWrapper parent ifNotNil: [: parentWrapper | parentWrapper item]])].!
Levente Uzonyi uploaded a new version of Collections to project The Trunk:
http://source.squeak.org/trunk/Collections-ul.607.mcz
==================== Summary ====================
Name: Collections-ul.607
Author: ul
Time: 2 April 2015, 12:07:14.622 am
UUID: 607c7a3f-c462-454c-8e18-02c49e4ae91a
Ancestors: Collections-ul.606
Simplified CharacterSet class>>separators.
Fixed ReadStream >> #nextFloat, when collection is not a ByteString.
=============== Diff against Collections-ul.606 ===============
Item was changed:
----- Method: CharacterSet class>>separators (in category 'accessing') -----
separators
"return a set containing just the whitespace characters"
+ ^Separators ifNil: [ Separators := self newFrom: Character separators ]!
- ^Separators ifNil: [
- Separators := self new
- addAll: Character separators;
- yourself ]!
Item was changed:
----- Method: ReadStream>>nextFloat (in category 'accessing') -----
nextFloat
"Read a floating point value from the receiver. This method is highly optimized for cases
where many floating point values need to be read subsequently. And if this needs to go
even faster, look at the inner loops fetching the characters - moving those into a plugin
would speed things up even more."
| buffer count sign index cc value digit fraction exp startIndex anyDigit digitNeeded |
buffer := collection.
count := readLimit.
index := position+1.
"Skip separators"
+ index := ByteString findFirstInString: buffer inSet: CharacterSet nonSeparators byteArrayMap startingAt: index.
- index := buffer indexOfAnyOf: CharacterSet nonSeparators startingAt: index.
index = 0 ifTrue:[self setToEnd. ^nil].
"check for sign"
digitNeeded := false.
sign := 1. cc := buffer byteAt: index.
cc = 45 "$- asciiValue"
ifTrue:[sign := -1. index := index+1. digitNeeded := true]
ifFalse:[cc = 43 "$+ asciiValue" ifTrue:[index := index+1. digitNeeded := true]].
"Read integer part"
startIndex := index.
value := 0.
[index <= count and:[
digit := (buffer byteAt: index) - 48. "$0 asciiValue"
digit >= 0 and:[digit <= 9]]] whileTrue:[
value := value * 10 + digit.
index := index + 1.
].
anyDigit := index > startIndex.
index > count ifTrue:[
(digitNeeded and:[anyDigit not]) ifTrue:[^self error: 'At least one digit expected'].
self setToEnd. ^value asFloat * sign].
(buffer byteAt: index) = 46 "$. asciiValue" ifTrue:["<integer>.<fraction>"
index := index+1.
startIndex := index.
"NOTE: fraction and exp below can overflow into LargeInteger range. If they do, then things slow down horribly due to the relatively slow LargeInt -> Float conversion. This can be avoided by changing fraction and exp to use floats to begin with (0.0 and 1.0 respectively), however, this will give different results to Float>>readFrom: and it is not clear if that is acceptable here."
fraction := 0. exp := 1.
[index <= count and:[
digit := (buffer byteAt: index) - 48. "$0 asciiValue"
digit >= 0 and:[digit <= 9]]] whileTrue:[
fraction := fraction * 10 + digit.
exp := exp * 10.
index := index + 1.
].
value := value + (fraction asFloat / exp asFloat).
anyDigit := anyDigit or:[index > startIndex].
].
value := value asFloat * sign.
"At this point we require at least one digit to avoid allowing:
- . ('0.0' without leading digits)
- e32 ('0e32' without leading digits)
- .e32 ('0.0e32' without leading digits)
but these are currently allowed:
- .5 (0.5)
- 1. ('1.0')
- 1e32 ('1.0e32')
- 1.e32 ('1.0e32')
- .5e32 ('0.5e32')
"
anyDigit ifFalse:["Check for NaN/Infinity first"
(count - index >= 2 and:[(buffer copyFrom: index to: index+2) = 'NaN'])
ifTrue:[position := index+2. ^Float nan * sign].
(count - index >= 7 and:[(buffer copyFrom: index to: index+7) = 'Infinity'])
ifTrue:[position := index+7. ^Float infinity * sign].
^self error: 'At least one digit expected'
].
index > count ifTrue:[self setToEnd. ^value asFloat].
(buffer byteAt: index) = 101 "$e asciiValue" ifTrue:["<number>e[+|-]<exponent>"
index := index+1. "skip e"
sign := 1. cc := buffer byteAt: index.
cc = 45 "$- asciiValue"
ifTrue:[sign := -1. index := index+1]
ifFalse:[cc = 43 "$+ asciiValue" ifTrue:[index := index+1]].
startIndex := index.
exp := 0. anyDigit := false.
[index <= count and:[
digit := (buffer byteAt: index) - 48. "$0 asciiValue"
digit >= 0 and:[digit <= 9]]] whileTrue:[
exp := exp * 10 + digit.
index := index + 1.
].
index> startIndex ifFalse:[^self error: 'Exponent expected'].
value := value * (10.0 raisedToInteger: exp * sign).
].
position := index-1.
^value!
Levente Uzonyi uploaded a new version of Collections to project The Trunk:
http://source.squeak.org/trunk/Collections-ul.606.mcz
==================== Summary ====================
Name: Collections-ul.606
Author: ul
Time: 1 April 2015, 11:35:01.718 pm
UUID: cd3ba2f1-88d3-4f8a-a06b-089509ceccdf
Ancestors: Collections-mt.605
Cache and share #separators and #nonSeparators in CharacterSet (just like #crlf). Remove them on #cleanUp.
Implemented CharacterSet class >> #withAll:.
Removed #noSeparatorMap, #noSeparators, #separatorMap from String class. Also removed the class variables CSNonSeparators, CSSeparators, and CSLineEnders. All users were rewritten to use CharacterSet's version of these sets.
=============== Diff against Collections-mt.605 ===============
Item was changed:
----- Method: ByteString>>substrings (in category 'converting') -----
substrings
"Answer an array of the substrings that compose the receiver."
| result end beginning |
result := WriteStream on: (Array new: 10).
end := 0.
"find one substring each time through this loop"
[ "find the beginning of the next substring"
+ beginning := self indexOfAnyOf: CharacterSet nonSeparators
- beginning := self indexOfAnyOf: CSNonSeparators
startingAt: end+1 ifAbsent: [ nil ].
beginning ~~ nil ] whileTrue: [
"find the end"
+ end := self indexOfAnyOf: CharacterSet separators
- end := self indexOfAnyOf: CSSeparators
startingAt: beginning ifAbsent: [ self size + 1 ].
end := end - 1.
result nextPut: (self copyFrom: beginning to: end).
].
^result contents!
Item was changed:
Collection subclass: #CharacterSet
instanceVariableNames: 'map'
+ classVariableNames: 'CrLf NonSeparators Separators'
- classVariableNames: 'CrLf'
poolDictionaries: ''
category: 'Collections-Support'!
!CharacterSet commentStamp: '<historical>' prior: 0!
A set of characters. Lookups for inclusion are very fast.!
Item was added:
+ ----- Method: CharacterSet class>>cleanUp: (in category 'initialize-release') -----
+ cleanUp: aggressive
+
+ CrLf := NonSeparators := Separators := nil!
Item was changed:
----- Method: CharacterSet class>>crlf (in category 'accessing') -----
crlf
+
+ ^CrLf ifNil: [ CrLf := self with: Character cr with: Character lf ]!
- CrLf ifNil: [CrLf := self with: Character cr with: Character lf].
- ^CrLf!
Item was changed:
+ ----- Method: CharacterSet class>>nonSeparators (in category 'accessing') -----
- ----- Method: CharacterSet class>>nonSeparators (in category 'instance creation') -----
nonSeparators
"return a set containing everything but the whitespace characters"
+ ^NonSeparators ifNil: [
+ NonSeparators := self separators complement ]!
- ^self separators complement!
Item was changed:
+ ----- Method: CharacterSet class>>separators (in category 'accessing') -----
- ----- Method: CharacterSet class>>separators (in category 'instance creation') -----
separators
"return a set containing just the whitespace characters"
+ ^Separators ifNil: [
+ Separators := self new
+ addAll: Character separators;
+ yourself ]!
- | set |
- set := self empty.
- set addAll: Character separators.
- ^set!
Item was added:
+ ----- Method: CharacterSet class>>withAll: (in category 'instance creation') -----
+ withAll: aCollection
+ "Create a new CharacterSet containing all the characters from aCollection."
+
+ ^self newFrom: aCollection!
Item was changed:
----- Method: ReadStream>>nextFloat (in category 'accessing') -----
nextFloat
"Read a floating point value from the receiver. This method is highly optimized for cases
where many floating point values need to be read subsequently. And if this needs to go
even faster, look at the inner loops fetching the characters - moving those into a plugin
would speed things up even more."
| buffer count sign index cc value digit fraction exp startIndex anyDigit digitNeeded |
buffer := collection.
count := readLimit.
index := position+1.
"Skip separators"
+ index := buffer indexOfAnyOf: CharacterSet nonSeparators startingAt: index.
- index := ByteString findFirstInString: buffer inSet: String noSeparatorMap startingAt: index.
index = 0 ifTrue:[self setToEnd. ^nil].
"check for sign"
digitNeeded := false.
sign := 1. cc := buffer byteAt: index.
cc = 45 "$- asciiValue"
ifTrue:[sign := -1. index := index+1. digitNeeded := true]
ifFalse:[cc = 43 "$+ asciiValue" ifTrue:[index := index+1. digitNeeded := true]].
"Read integer part"
startIndex := index.
value := 0.
[index <= count and:[
digit := (buffer byteAt: index) - 48. "$0 asciiValue"
digit >= 0 and:[digit <= 9]]] whileTrue:[
value := value * 10 + digit.
index := index + 1.
].
anyDigit := index > startIndex.
index > count ifTrue:[
(digitNeeded and:[anyDigit not]) ifTrue:[^self error: 'At least one digit expected'].
self setToEnd. ^value asFloat * sign].
(buffer byteAt: index) = 46 "$. asciiValue" ifTrue:["<integer>.<fraction>"
index := index+1.
startIndex := index.
"NOTE: fraction and exp below can overflow into LargeInteger range. If they do, then things slow down horribly due to the relatively slow LargeInt -> Float conversion. This can be avoided by changing fraction and exp to use floats to begin with (0.0 and 1.0 respectively), however, this will give different results to Float>>readFrom: and it is not clear if that is acceptable here."
fraction := 0. exp := 1.
[index <= count and:[
digit := (buffer byteAt: index) - 48. "$0 asciiValue"
digit >= 0 and:[digit <= 9]]] whileTrue:[
fraction := fraction * 10 + digit.
exp := exp * 10.
index := index + 1.
].
value := value + (fraction asFloat / exp asFloat).
anyDigit := anyDigit or:[index > startIndex].
].
value := value asFloat * sign.
"At this point we require at least one digit to avoid allowing:
- . ('0.0' without leading digits)
- e32 ('0e32' without leading digits)
- .e32 ('0.0e32' without leading digits)
but these are currently allowed:
- .5 (0.5)
- 1. ('1.0')
- 1e32 ('1.0e32')
- 1.e32 ('1.0e32')
- .5e32 ('0.5e32')
"
anyDigit ifFalse:["Check for NaN/Infinity first"
(count - index >= 2 and:[(buffer copyFrom: index to: index+2) = 'NaN'])
ifTrue:[position := index+2. ^Float nan * sign].
(count - index >= 7 and:[(buffer copyFrom: index to: index+7) = 'Infinity'])
ifTrue:[position := index+7. ^Float infinity * sign].
^self error: 'At least one digit expected'
].
index > count ifTrue:[self setToEnd. ^value asFloat].
(buffer byteAt: index) = 101 "$e asciiValue" ifTrue:["<number>e[+|-]<exponent>"
index := index+1. "skip e"
sign := 1. cc := buffer byteAt: index.
cc = 45 "$- asciiValue"
ifTrue:[sign := -1. index := index+1]
ifFalse:[cc = 43 "$+ asciiValue" ifTrue:[index := index+1]].
startIndex := index.
exp := 0. anyDigit := false.
[index <= count and:[
digit := (buffer byteAt: index) - 48. "$0 asciiValue"
digit >= 0 and:[digit <= 9]]] whileTrue:[
exp := exp * 10 + digit.
index := index + 1.
].
index> startIndex ifFalse:[^self error: 'Exponent expected'].
value := value * (10.0 raisedToInteger: exp * sign).
].
position := index-1.
^value!
Item was changed:
ArrayedCollection subclass: #String
instanceVariableNames: ''
+ classVariableNames: 'AsciiOrder CSMacroCharacters CaseInsensitiveOrder CaseSensitiveOrder CrLfExchangeTable HtmlEntities LowercasingTable Tokenish UppercasingTable'
- classVariableNames: 'AsciiOrder CSLineEnders CSMacroCharacters CSNonSeparators CSSeparators CaseInsensitiveOrder CaseSensitiveOrder CrLfExchangeTable HtmlEntities LowercasingTable Tokenish UppercasingTable'
poolDictionaries: ''
category: 'Collections-Strings'!
!String commentStamp: '<historical>' prior: 0!
A String is an indexed collection of Characters. Class String provides the abstract super class for ByteString (that represents an array of 8-bit Characters) and WideString (that represents an array of 32-bit characters). In the similar manner of LargeInteger and SmallInteger, those subclasses are chosen accordingly for a string; namely as long as the system can figure out so, the String is used to represent the given string.
Strings support a vast array of useful methods, which can best be learned by browsing and trying out examples as you find them in the code.
Here are a few useful methods to look at...
String match:
String contractTo:
String also inherits many useful methods from its hierarchy, such as
SequenceableCollection ,
SequenceableCollection copyReplaceAll:with:
!
Item was changed:
----- Method: String class>>initialize (in category 'initialization') -----
initialize "self initialize"
| order |
AsciiOrder := (0 to: 255) as: ByteArray.
CaseInsensitiveOrder := AsciiOrder copy.
($a to: $z) do:
[:c | CaseInsensitiveOrder at: c asciiValue + 1
put: (CaseInsensitiveOrder at: c asUppercase asciiValue +1)].
"Case-sensitive compare sorts space, digits, letters, all the rest..."
CaseSensitiveOrder := ByteArray new: 256 withAll: 255.
order := -1.
' 0123456789' do: "0..10"
[:c | CaseSensitiveOrder at: c asciiValue + 1 put: (order := order+1)].
($a to: $z) do: "11-64"
[:c | CaseSensitiveOrder at: c asUppercase asciiValue + 1 put: (order := order+1).
CaseSensitiveOrder at: c asciiValue + 1 put: (order := order+1)].
1 to: CaseSensitiveOrder size do:
[:i | (CaseSensitiveOrder at: i) = 255 ifTrue:
[CaseSensitiveOrder at: i put: (order := order+1)]].
order = 255 ifFalse: [self error: 'order problem'].
"a table for translating to lower case"
LowercasingTable := String withAll: (Character allByteCharacters collect: [:c | c asLowercase]).
"a table for translating to upper case"
UppercasingTable := String withAll: (Character allByteCharacters collect: [:c | c asUppercase]).
"a table for testing tokenish (for fast numArgs)"
Tokenish := String withAll: (Character allByteCharacters collect:
[:c | c tokenish ifTrue: [c] ifFalse: [$~]]).
+
-
- "CR and LF--characters that terminate a line"
- CSLineEnders := CharacterSet crlf.
-
- "separators and non-separators"
- CSSeparators := CharacterSet separators.
- CSNonSeparators := CSSeparators complement.
-
"% and < for #expandMacros*"
CSMacroCharacters := CharacterSet newFrom: '%<'.
"a table for exchanging cr with lf and vica versa"
CrLfExchangeTable := Character allByteCharacters collect: [ :each |
each
caseOf: {
[ Character cr ] -> [ Character lf ].
[ Character lf ] -> [ Character cr ] }
otherwise: [ each ] ]!
Item was removed:
- ----- Method: String class>>noSeparatorMap (in category 'accessing') -----
- noSeparatorMap
- ^CSNonSeparators byteArrayMap!
Item was removed:
- ----- Method: String class>>noSeparators (in category 'accessing') -----
- noSeparators
- ^ CSNonSeparators!
Item was removed:
- ----- Method: String class>>separatorMap (in category 'accessing') -----
- separatorMap
- ^CSSeparators byteArrayMap!
Item was changed:
----- Method: String>>indentationIfBlank: (in category 'paragraph support') -----
indentationIfBlank: aBlock
"Answer the number of leading tabs in the receiver. If there are
no visible characters, pass the number of tabs to aBlock and return its value."
| leadingTabs nonTab nonTabIndex nonSepIndex lineEndIndex |
nonTab := (CharacterSet with: Character tab) complement.
nonTabIndex := self indexOfAnyOf: nonTab startingAt: 1.
nonTabIndex = 0 ifTrue: [
"Only made of tabs or empty"
^aBlock value: self size].
leadingTabs := nonTabIndex - 1.
+ nonSepIndex := self indexOfAnyOf: CharacterSet nonSeparators startingAt: 1.
- nonSepIndex := self indexOfAnyOf: CSNonSeparators startingAt: 1.
nonSepIndex = 0 ifTrue: [
"Only made of separators"
^aBlock value: leadingTabs].
+ lineEndIndex := self indexOfAnyOf: CharacterSet crlf startingAt: 1.
- lineEndIndex := self indexOfAnyOf: CSLineEnders startingAt: 1.
(lineEndIndex between: 1 and: nonSepIndex) ifTrue: [
"Only made of separators up to a line end"
^aBlock value: leadingTabs].
^leadingTabs!
Item was changed:
----- Method: String>>withBlanksTrimmed (in category 'converting') -----
withBlanksTrimmed
"Return a copy of the receiver from which leading and trailing blanks have been trimmed."
| first last |
+ first := self indexOfAnyOf: CharacterSet nonSeparators startingAt: 1 ifAbsent: [0].
- first := self indexOfAnyOf: CSNonSeparators startingAt: 1 ifAbsent: [0].
first = 0 ifTrue: [ ^'' ]. "no non-separator character"
+ last := self lastIndexOfAnyOf: CharacterSet nonSeparators startingAt: self size ifAbsent: [self size].
- last := self lastIndexOfAnyOf: CSNonSeparators startingAt: self size ifAbsent: [self size].
(first = 1 and: [ last = self size ]) ifTrue: [ ^self copy ].
^self
copyFrom: first
to: last
!
Item was changed:
----- Method: String>>withNoLineLongerThan: (in category 'converting') -----
withNoLineLongerThan: aNumber
"Answer a string with the same content as receiver, but rewrapped so that no line has more characters than the given number"
aNumber isNumber not | (aNumber < 1) ifTrue: [self error: 'too narrow'].
^self class
new: self size * (aNumber + 1) // aNumber "provision for supplementary line breaks"
streamContents: [ :stream |
self lineIndicesDo: [ :start :endWithoutDelimiters :end |
| pastEnd lineStart |
pastEnd := endWithoutDelimiters + 1.
"eliminate spaces at beginning of line"
+ lineStart := (self indexOfAnyOf: CharacterSet nonSeparators startingAt: start ifAbsent: [pastEnd]) min: pastEnd.
- lineStart := (self indexOfAnyOf: CSNonSeparators startingAt: start ifAbsent: [pastEnd]) min: pastEnd.
[| lineStop lineEnd spacePosition |
lineEnd := lineStop := lineStart + aNumber min: pastEnd..
spacePosition := lineStart.
[spacePosition < lineStop] whileTrue: [
+ spacePosition := self indexOfAnyOf: CharacterSet separators startingAt: spacePosition + 1 ifAbsent: [pastEnd].
- spacePosition := self indexOfAnyOf: CSSeparators startingAt: spacePosition + 1 ifAbsent: [pastEnd].
spacePosition <= lineStop ifTrue: [lineEnd := spacePosition].
].
"split before space or before lineStop if no space"
stream nextPutAll: (self copyFrom: lineStart to: lineEnd - 1).
"eliminate spaces at beginning of next line"
+ lineStart := self indexOfAnyOf: CharacterSet nonSeparators startingAt: lineEnd ifAbsent: [pastEnd].
- lineStart := self indexOfAnyOf: CSNonSeparators startingAt: lineEnd ifAbsent: [pastEnd].
lineStart <= endWithoutDelimiters ]
whileTrue: [stream cr].
stream nextPutAll: (self copyFrom: pastEnd to: end) ] ]!
Item was changed:
----- Method: String>>withSeparatorsCompacted (in category 'converting') -----
withSeparatorsCompacted
"replace each sequences of whitespace by a single space character"
"' test ' withSeparatorsCompacted = ' test '"
"' test test' withSeparatorsCompacted = ' test test'"
"'test test ' withSeparatorsCompacted = 'test test '"
| out in next isSeparator |
self isEmpty ifTrue: [^ self].
out := WriteStream on: (String new: self size).
in := self readStream.
isSeparator := [:char | char asciiValue < 256
+ and: [CharacterSet separators includes: char]].
- and: [CSSeparators includes: char]].
[in atEnd] whileFalse: [
next := in next.
(isSeparator value: next)
ifTrue: [
out nextPut: $ .
[in atEnd or:
[next := in next.
(isSeparator value: next)
ifTrue: [false]
ifFalse: [out nextPut: next. true]]] whileFalse]
ifFalse: [out nextPut: next]].
^ out contents!
Item was changed:
----- Method: Text>>withBlanksTrimmed (in category 'converting') -----
withBlanksTrimmed
"Return a copy of the receiver from which leading and trailing blanks have been trimmed."
| first last |
+ first := string indexOfAnyOf: CharacterSet nonSeparators startingAt: 1.
- first := string indexOfAnyOf: String noSeparators startingAt: 1 ifAbsent: [0].
first = 0 ifTrue: [ ^'' ]. "no non-separator character"
+ last := string lastIndexOfAnyOf: CharacterSet nonSeparators startingAt: self size ifAbsent: [self size].
- last := string lastIndexOfAnyOf: String noSeparators startingAt: self size ifAbsent: [self size].
(first = 1 and: [ last = self size ]) ifTrue: [ ^self copy ].
^self
copyFrom: first
to: last
!
Changes to Trunk (http://source.squeak.org/trunk.html) in the last 24 hours:
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007740.html
Name: ToolBuilder-Morphic-mt.109
Ancestors: ToolBuilder-Morphic-mt.108
Reverted path selection in tree to use #= instead of #==.
Fixed the code to indicate the actual selection in the tree (and scroll to it if too large).
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007741.html
Name: Tools-mt.569
Ancestors: Tools-mt.568
Fixed selection in FileList tool.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007742.html
Name: ToolBuilder-Morphic-mt.110
Ancestors: ToolBuilder-Morphic-mt.109
Revert "code to indicate the actual selection" because I confused the view-based API with the model-based API.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007743.html
Name: Morphic-mt.798
Ancestors: Morphic-mt.797
Fixes error that may occur in empty lazy lists when mapping a point to a row index.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007744.html
Name: Morphic-mt.799
Ancestors: Morphic-mt.798
Remove the balloon text when start typing because we assume that the user focuses on the input and not the help anymore.
This is similar to balloon help for buttons where the bubble disappears if the user clicks the button.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007745.html
Name: Morphic-mt.800
Ancestors: Morphic-mt.799
Elevated #roundedScrollBarLook into a preference (was: just hardcoded to false) and updated affected methods.
Added preference to hide even the arrow buttons of all scrollbars. This makes sense for mouse-wheel-driven usage.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007746.html
Name: Morphic-mt.801
Ancestors: Morphic-mt.800
Scrollbars: Fixed button initialization code for rounded scrollbars.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007747.html
Name: Morphic-mt.802
Ancestors: Morphic-mt.801
Fixed layouting bug of horizontal scrollbar if vertical scroll bar is on the left.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007748.html
Name: Kernel-topa.916
Ancestors: Kernel-topa.915
(same as before)
Fix arguments access in WeakMessageSend
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007749.html
Name: ToolBuilder-Morphic-mt.111
Ancestors: ToolBuilder-Morphic-mt.110
Fixed should background-styling to update text morph runs only from within the morphic UI process.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007750.html
Name: Morphic-mt.803
Ancestors: Morphic-mt.802
Recompose the paragraph if text or runs changed after keyboard input.
We did not notice this bug because Shout/Tools did this in #stylerStyled:. Only some jerky scrolling behavior occured from time to time because the first text morph update (while Shout was background-styling) was without paragraph recomposition.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007751.html
Name: Morphic-mt.804
Ancestors: Morphic-mt.803
Another fix for horizontal scroll bars in scroll panes, which affects layouting and scrolling.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007752.html
Name: Tools-cmm.570
Ancestors: Tools-mt.569
- SimpleHierarchicalListMorph's now honor preferences:
mouseOverForKeyboardFocus
Vertical Smart Splitters
Filterable Lists Clear Automatically
- After filtering Tree, refit the column-widths to the filtered results.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007753.html
Name: Morphic-cmm.805
Ancestors: Morphic-mt.804
- SimpleHierarchicalListMorph's now honor preferences:
mouseOverForKeyboardFocus
Vertical Smart Splitters
- Don't let splitter bars be dragged further than their PluggableListMorphs want them to go.
- PluggableTextMorph's now honor Vertical Smart Splitters to avoid wrapped lines, if possible.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007754.html
Name: ToolBuilder-Morphic-cmm.109
Ancestors: ToolBuilder-Morphic-mt.111
- PluggableTreeMorph support for Vertical Smart Splitters.
- Let single-level filtering also be a navigation gesture.
- After filtering a Tree, refit the column-widths to the filtered results.
- SimpleHierarchicalListMorph support mouseOverForKeyboardFocus.
- Fix selection rendering in PluggableTreeMorph (FileList and SqueakMap).
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007755.html
Name: Tools-cmm.569
Ancestors: Tools-cmm.570
- SimpleHierarchicalListMorph's now honor preferences:
mouseOverForKeyboardFocus
Vertical Smart Splitters
Filterable Lists Clear Automatically
- After filtering Tree, refit the column-widths to the filtered results.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007756.html
Name: Morphic-cmm.798
Ancestors: Morphic-cmm.805
- SimpleHierarchicalListMorph's now honor preferences:
mouseOverForKeyboardFocus
Vertical Smart Splitters
- Don't let splitter bars be dragged further than their PluggableListMorphs want them to go.
- PluggableTextMorph's now honor Vertical Smart Splitters to avoid wrapped lines, if possible.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007757.html
Name: Tools-cmm.571
Ancestors: Tools-cmm.569
Resaving package as highest version number to support proper trunk updating.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007758.html
Name: ToolBuilder-Morphic-cmm.112
Ancestors: ToolBuilder-Morphic-cmm.109
Resaving package with highest version # to support proper trunk update.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007759.html
Name: ToolBuilder-Morphic-cmm.113
Ancestors: ToolBuilder-Morphic-cmm.112
- Filter-navigation DNU when there is no selection. Filtering still needs to be figured out for the roots of a tree...
- Restore Marcel's latest selectPath:in: from today.
- Don't rely on #selection: from setSelectedMorph: to fix selection-rendering in UI's, instead we should be sending proper changed notifications from each model.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007760.html
Name: Tools-cmm.572
Ancestors: Tools-cmm.571
- Fix test for scrollbar presence for Vertical Smart Splitter support.
- Fix "Reuse Windows" preference for ObjectExplorers.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007761.html
Name: SMLoader-cmm.81
Ancestors: SMLoader-bf.80
- Fix selection rendering in SqueakMap.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007762.html
Name: ToolBuilder-Morphic-cmm.114
Ancestors: ToolBuilder-Morphic-cmm.113
No, you cannot send copyFrom: 0 to: 0 to an empty Array. Must check for emptiness.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007763.html
Name: System-ul.713
Ancestors: System-eem.712
Use a custom CharacterSet for separators instead of modifying the one in CharacterSet - which may be shared. Cache it for better performance, and get rid of it during cleanUp.
=============================================
http://lists.squeakfoundation.org/pipermail/packages/2015-April/007764.html
Name: System-ul.714
Ancestors: System-ul.713
Avoid LargeInteger arithmetic in ThirtyTwoBitRegister>>leftRotateBy:.
=============================================