ResourcePack.st
changeset 72 3e84121988c3
parent 54 29a6b2f8e042
child 97 dd6116883ac0
equal deleted inserted replaced
71:6a42b2b115f8 72:3e84121988c3
     1 "
     1 "
     2  COPYRIGHT (c) 1993 by Claus Gittinger
     2  COPYRIGHT (c) 1993 by Claus Gittinger
     3               All Rights Reserved
     3 	      All Rights Reserved
     4 
     4 
     5  This software is furnished under a license and may be used
     5  This software is furnished under a license and may be used
     6  only in accordance with the terms of that license and with the
     6  only in accordance with the terms of that license and with the
     7  inclusion of the above copyright notice.   This software may not
     7  inclusion of the above copyright notice.   This software may not
     8  be provided or otherwise made available to, or used by, any
     8  be provided or otherwise made available to, or used by, any
     9  other person.  No title to or ownership of the software is
     9  other person.  No title to or ownership of the software is
    10  hereby transferred.
    10  hereby transferred.
    11 "
    11 "
    12 
    12 
    13 Dictionary subclass:#ResourcePack
    13 Dictionary subclass:#ResourcePack
    14          instanceVariableNames:'elements dependents packsClassName'
    14 	 instanceVariableNames:'elements dependents packsClassName'
    15          classVariableNames:'Packs'
    15 	 classVariableNames:'Packs'
    16          poolDictionaries:''
    16 	 poolDictionaries:''
    17          category:'System-Support'
    17 	 category:'System-Support'
    18 !
    18 !
    19 
    19 
    20 ResourcePack comment:'
    20 ResourcePack comment:'
    21 COPYRIGHT (c) 1993 by Claus Gittinger
    21 COPYRIGHT (c) 1993 by Claus Gittinger
    22               All Rights Reserved
    22 	      All Rights Reserved
    23 
    23 
    24 $Header: /cvs/stx/stx/libview/ResourcePack.st,v 1.8 1994-08-05 01:14:58 claus Exp $
    24 $Header: /cvs/stx/stx/libview/ResourcePack.st,v 1.9 1994-10-10 02:33:00 claus Exp $
    25 '!
    25 '!
    26 
    26 
    27 !ResourcePack class methodsFor:'documentation'!
    27 !ResourcePack class methodsFor:'documentation'!
    28 
    28 
    29 copyright
    29 copyright
    30 "
    30 "
    31  COPYRIGHT (c) 1993 by Claus Gittinger
    31  COPYRIGHT (c) 1993 by Claus Gittinger
    32               All Rights Reserved
    32 	      All Rights Reserved
    33 
    33 
    34  This software is furnished under a license and may be used
    34  This software is furnished under a license and may be used
    35  only in accordance with the terms of that license and with the
    35  only in accordance with the terms of that license and with the
    36  inclusion of the above copyright notice.   This software may not
    36  inclusion of the above copyright notice.   This software may not
    37  be provided or otherwise made available to, or used by, any
    37  be provided or otherwise made available to, or used by, any
    40 "
    40 "
    41 !
    41 !
    42 
    42 
    43 version
    43 version
    44 "
    44 "
    45 $Header: /cvs/stx/stx/libview/ResourcePack.st,v 1.8 1994-08-05 01:14:58 claus Exp $
    45 $Header: /cvs/stx/stx/libview/ResourcePack.st,v 1.9 1994-10-10 02:33:00 claus Exp $
    46 "
    46 "
    47 !
    47 !
    48 
    48 
    49 documentation
    49 documentation
    50 "
    50 "
    57     The resourcePack consists of a mapping from strings to values, which are
    57     The resourcePack consists of a mapping from strings to values, which are
    58     then used in labels, buttons, menus etc.
    58     then used in labels, buttons, menus etc.
    59     The resourcePack initializes itself from a file found in 'resources/<className>.rs',
    59     The resourcePack initializes itself from a file found in 'resources/<className>.rs',
    60     where 'className' is built by the usual abbreviation mechanism (see abbrev-files).
    60     where 'className' is built by the usual abbreviation mechanism (see abbrev-files).
    61     Conditional mappings are possible, by including lines as:
    61     Conditional mappings are possible, by including lines as:
    62         #if <expression>
    62 	#if <expression>
    63         #endif
    63 	#endif
    64     in the resourcefile. Example:
    64     in the resourcefile. Example:
    65     file 'foo.rs':
    65     file 'foo.rs':
    66         #if Language == #german
    66 	#if Language == #german
    67         'abort' 'Abbruch'
    67 	'abort' 'Abbruch'
    68         #endif
    68 	#endif
    69         #if Language == #french
    69 	#if Language == #french
    70         'abort' 'canceller'
    70 	'abort' 'canceller'
    71         #endif
    71 	#endif
    72     the corresponding resource-strings are accessed using:
    72     the corresponding resource-strings are accessed using:
    73         resource string:'abort'
    73 	resource string:'abort'
    74     returning the mapped string (i.e. 'Abbruch' if the global Language is set
    74     returning the mapped string (i.e. 'Abbruch' if the global Language is set
    75     to #german)..
    75     to #german)..
    76     If no corresponding entry is found in the resources, the key is returned.
    76     If no corresponding entry is found in the resources, the key is returned.
    77     Translations can also include arguments, such as:
    77     Translations can also include arguments, such as:
    78         resources string:'really delete %1' with:fileName
    78 	resources string:'really delete %1' with:fileName
    79 "
    79 "
    80 ! !
    80 ! !
    81 
    81 
    82 !ResourcePack class methodsFor:'initialization'!
    82 !ResourcePack class methodsFor:'initialization'!
    83 
    83 
    84 initialize
    84 initialize
    85     Packs isNil ifTrue:[
    85     Packs isNil ifTrue:[
    86         Packs := WeakArray new:30
    86 	Packs := WeakArray new:30
    87     ].
    87     ].
    88 
    88 
    89     "ResourcePack initialize"
    89     "ResourcePack initialize"
    90 !
    90 !
    91 
    91 
    92 flushResources
    92 flushCachedResourcePacks
    93     "forget all cached resources - needed after a style change"
    93     "forget all cached resources - needed after a style change"
    94 
    94 
    95     Packs := nil.
    95     Packs := nil.
    96     self initialize
    96     self initialize
    97 
    97 
    98     "ResourcePack flushResources"
    98     "ResourcePack flushCachedResourcePacks"
    99 ! !
    99 ! !
   100 
   100 
   101 !ResourcePack class methodsFor:'private'!
   101 !ResourcePack class methodsFor:'private'!
   102 
   102 
   103 addToCache:aPack
   103 addToCache:aPack
   104     |idx|
   104     |idx|
   105 
   105 
   106     idx := Packs identityIndexOf:nil.
   106     idx := Packs identityIndexOf:nil.
   107     idx == 0 ifTrue:[
   107     idx == 0 ifTrue:[
   108         "
   108 	"
   109          throw away oldest
   109 	 throw away oldest
   110         "
   110 	"
   111         idx := Packs size.
   111 	idx := Packs size.
   112         Packs replaceFrom:1 to:idx-1 with:Packs startingAt:2.
   112 	Packs replaceFrom:1 to:idx-1 with:Packs startingAt:2.
   113     ].
   113     ].
   114     Packs at:idx put:aPack
   114     Packs at:idx put:aPack
   115 !
   115 !
   116 
   116 
   117 searchCacheFor:aClassname
   117 searchCacheFor:aClassname
   118     |sz|
   118     |sz|
   119 
   119 
   120     Packs isNil ifTrue:[
   120     Packs isNil ifTrue:[
   121         self initialize.
   121 	self initialize.
   122         ^ nil
   122 	^ nil
   123     ].
   123     ].
   124 
   124 
   125     sz := Packs size.
   125     sz := Packs size.
   126     1 to:sz do:[:idx |
   126     1 to:sz do:[:idx |
   127         |aPack|
   127 	|aPack|
   128 
   128 
   129         aPack := Packs at:idx.
   129 	aPack := Packs at:idx.
   130         aPack notNil ifTrue:[
   130 	aPack notNil ifTrue:[
   131             aPack packsClassName = aClassname ifTrue:[
   131 	    aClassname = aPack packsClassName ifTrue:[
   132                 "
   132 		"
   133                  bring to end for LRU
   133 		 bring to end for LRU
   134                 "
   134 		"
   135                 Packs replaceFrom:idx to:sz-1 with:Packs startingAt:idx+1.
   135 		Packs replaceFrom:idx to:sz-1 with:Packs startingAt:idx+1.
   136                 Packs at:sz put:aPack.
   136 		Packs at:sz put:aPack.
   137                 ^ aPack
   137 		^ aPack
   138             ]
   138 	    ]
   139         ]
   139 	]
   140     ].
   140     ].
   141     ^ nil
   141     ^ nil
   142 ! !
   142 ! !
   143 
   143 
   144 !ResourcePack class methodsFor:'instance creation'!
   144 !ResourcePack class methodsFor:'instance creation'!
   145 
   145 
   146 fromFile:aFileName directory:dirName
   146 fromFile:aFileName directory:dirName
   147     "get the resource definitions from a file in a directory.
   147     "get the resource definitions from a file in a directory.
   148      Uncached low-level entry."
   148      Uncached low-level entry."
   149 
   149 
   150     |inStream newPack|
   150     |newPack|
   151 
   151 
   152     newPack := self new.
   152     newPack := self new.
   153     inStream := Smalltalk systemFileStreamFor:('resources/' , aFileName).
   153     newPack readFromFile:aFileName directory:dirName.
   154     inStream isNil ifTrue:[
       
   155         "
       
   156          an empty pack
       
   157         "
       
   158         ^ newPack
       
   159     ].
       
   160     newPack readFromResourceStream:inStream.
       
   161     inStream close.
       
   162 
       
   163     self addToCache:newPack.
       
   164     ^ newPack
   154     ^ newPack
   165 !
   155 !
   166 
   156 
   167 fromFile:aFileName
   157 fromFile:aFileName
   168     "get the resource definitions from a file in the default directory.
   158     "get the resource definitions from a file in the default directory.
   187     pack := self searchCacheFor:nm.
   177     pack := self searchCacheFor:nm.
   188     pack notNil ifTrue:[^ pack].
   178     pack notNil ifTrue:[^ pack].
   189 
   179 
   190     pack := self fromFile:(Smalltalk fileNameForClass:nm) , '.rs'.
   180     pack := self fromFile:(Smalltalk fileNameForClass:nm) , '.rs'.
   191     aClass == Object ifFalse:[
   181     aClass == Object ifFalse:[
   192         superPack := self for:(aClass superclass).
   182 	superPack := self for:(aClass superclass).
   193         pack := pack merge:superPack
   183 	pack := pack merge:superPack
   194     ].
   184     ].
   195     pack packsClassName:nm.
   185     pack packsClassName:nm.
   196     self addToCache:pack.
   186     self addToCache:pack.
   197     ^ pack
   187     ^ pack
   198 ! !
   188 ! !
   199 
   189 
   200 !ResourcePack methodsFor:'merging'!
   190 !ResourcePack methodsFor:'merging'!
   201 
   191 
   202 merge:anotherPack
   192 merge:anotherPack
   203     anotherPack keysAndValuesDo:[:key :value |
   193     anotherPack keysAndValuesDo:[:key :value |
   204         (self includesKey:key) ifFalse:[
   194 	(self includesKey:key) ifFalse:[
   205             self at:key put:value
   195 	    self at:key put:value
   206         ]
   196 	]
   207     ]
   197     ]
   208 ! !
   198 ! !
   209 
   199 
   210 !ResourcePack methodsFor:'accessing'!
   200 !ResourcePack methodsFor:'accessing'!
   211 
   201 
   224 packsClassName:aString
   214 packsClassName:aString
   225     packsClassName := aString
   215     packsClassName := aString
   226 !
   216 !
   227 
   217 
   228 at:aKey
   218 at:aKey
   229     ^ self at:aKey ifAbsent:[aKey]
   219     ^ self at:aKey ifAbsent:aKey
   230 !
   220 !
   231 
   221 
   232 at:aKey default:default
   222 at:aKey default:default
   233     ^ self at:aKey ifAbsent:[default]
   223     ^ self at:aKey ifAbsent:default
   234 !
   224 !
   235 
   225 
   236 name:aKey
   226 name:aKey
   237     ^ self at:aKey ifAbsent:[aKey]
   227     ^ self at:aKey ifAbsent:aKey
   238 !
   228 !
   239 
   229 
   240 name:aKey default:default
   230 name:aKey default:default
   241     ^ self at:aKey ifAbsent:[default]
   231     ^ self at:aKey ifAbsent:default
   242 !
   232 !
   243 
   233 
   244 array:anArray
   234 array:anArray
   245     ^ anArray collect:[:r | self at:r default:r]
   235     ^ anArray collect:[:r | self at:r default:r]
   246 !
   236 !
   247 
   237 
   248 string:s
   238 string:s
   249     ^ self at:s ifAbsent:[s]
   239     ^ self at:s ifAbsent:s
   250 !
   240 !
   251 
   241 
   252 string:s with:arg
   242 string:s with:arg
   253     ^ self string:s withArgs:(Array with:arg)
   243     ^ self string:s withArgs:(Array with:arg)
   254 !
   244 !
   263     template := self at:s ifAbsent:[s].
   253     template := self at:s ifAbsent:[s].
   264     expandedString := ''.
   254     expandedString := ''.
   265     stop := template size.
   255     stop := template size.
   266     start := 1.
   256     start := 1.
   267     [start < stop] whileTrue:[
   257     [start < stop] whileTrue:[
   268         idx := template indexOf:$% startingAt:start.
   258 	idx := template indexOf:$% startingAt:start.
   269         idx == 0 ifTrue:[
   259 	idx == 0 ifTrue:[
   270             ^ expandedString , (template copyFrom:start to:stop)
   260 	    ^ expandedString , (template copyFrom:start to:stop)
   271         ].
   261 	].
   272         "found a %"
   262 	"found a %"
   273         expandedString := expandedString , (template copyFrom:start to:(idx - 1)).
   263 	expandedString := expandedString , (template copyFrom:start to:(idx - 1)).
   274         next := template at:(idx + 1).
   264 	next := template at:(idx + 1).
   275         (next == $%) ifTrue:[
   265 	(next == $%) ifTrue:[
   276             expandedString := expandedString , '%'
   266 	    expandedString := expandedString , '%'
   277         ] ifFalse:[
   267 	] ifFalse:[
   278             expandedString := expandedString , (argArray at:(next digitValue)) printString
   268 	    expandedString := expandedString , (argArray at:(next digitValue)) printString
   279         ].
   269 	].
   280         start := idx + 2
   270 	start := idx + 2
   281     ].
   271     ].
   282     ^  expandedString
   272     ^  expandedString
   283 ! !
   273 ! !
   284 
   274 
   285 !ResourcePack methodsFor:'file reading'!
   275 !ResourcePack methodsFor:'file reading'!
   286 
   276 
   287 readFromResourceStream:inStream
   277 readFromFile:fileName directory:dirName
   288     |lineString rest value ifLevel skipping l name first|
   278     |inStream|
       
   279 
       
   280     inStream := Smalltalk systemFileStreamFor:(dirName , '/' , fileName).
       
   281     inStream isNil ifTrue:[
       
   282 	"
       
   283 	 an empty pack
       
   284 	"
       
   285 	^ nil
       
   286     ].
       
   287     self readFromResourceStream:inStream in:dirName.
       
   288     inStream close.
       
   289 !
       
   290 
       
   291 readFromResourceStream:inStream in:dirName
       
   292     |lineString rest value ifLevel skipping l name first str macroName|
   289 
   293 
   290     ifLevel := 0.
   294     ifLevel := 0.
   291     skipping := false.
   295     skipping := false.
   292     [inStream atEnd] whileFalse:[
   296     [inStream atEnd] whileFalse:[
   293         lineString := inStream nextLine.
   297 	lineString := inStream nextLine.
   294         (lineString notNil and:[lineString isEmpty not]) ifTrue:[
   298 	(lineString notNil and:[lineString isEmpty not]) ifTrue:[
   295             first := lineString at:1.
   299 	    first := lineString at:1.
   296             first == $; ifFalse:[
   300 	    first == $; ifFalse:[
   297                 first == $# ifTrue:[
   301 		first == $# ifTrue:[
   298                     (lineString startsWith:'#if') ifTrue:[
   302 		    lineString := (lineString copyFrom:2) withoutSpaces.
   299                         skipping ifFalse:[
   303 
   300                             rest := lineString copyFrom:4.
   304 		    (lineString startsWith:'if') ifTrue:[
   301                             value := Compiler evaluate:rest.
   305 			skipping ifFalse:[
   302                             (value == #Error) ifTrue:[
   306 			    rest := lineString copyFrom:3.
   303                                 Transcript show:('error in resource:' , lineString).
   307 			    value := Compiler evaluate:rest.
   304                             ].
   308 			    (value == #Error) ifTrue:[
   305                             (value == false) ifTrue:[
   309 				Transcript show:('error in resource:' , lineString).
   306                                 skipping := true
   310 			    ].
   307                             ]
   311 			    (value == false) ifTrue:[
   308                         ].
   312 				skipping := true
   309                         ifLevel := ifLevel + 1
   313 			    ]
   310                     ] ifFalse:[
   314 			].
   311                         (lineString startsWith:'#endif') ifTrue:[
   315 			ifLevel := ifLevel + 1
   312                             ifLevel := ifLevel - 1.
   316 		    ] ifFalse:[
   313                             ifLevel == 0 ifTrue:[
   317 			(lineString startsWith:'endif') ifTrue:[
   314                                 skipping := false
   318 			    ifLevel := ifLevel - 1.
   315                             ]
   319 			    ifLevel == 0 ifTrue:[
   316                         ].
   320 				skipping := false
   317                     ].
   321 			    ]
   318                 ] ifFalse:[
   322 			] ifFalse:[
   319                     skipping ifFalse:[
   323 			    (lineString startsWith:'else') ifTrue:[
   320                         lineString := lineString withoutSeparators.
   324 				skipping := skipping not
   321                         name := nil.
   325 			    ] ifFalse:[
   322                         (lineString at:1) == $' ifTrue:[
   326 				(lineString startsWith:'include') ifTrue:[
   323                             l := lineString indexOf:$' startingAt:2.
   327 				    rest := lineString copyFrom:8.
   324                             l ~~ 0 ifTrue:[
   328 				    value := Compiler evaluate:rest.
   325                                 name := (lineString copyFrom:2 to:l-1).
   329 				    self readFromFile:value directory:dirName
   326                                 l := l + 1
   330 				]
   327                             ]
   331 			    ]
   328                         ] ifFalse:[
   332 			]
   329                             l := lineString indexOfSeparatorStartingAt:1.
   333 		    ].
   330                             l ~~ 0 ifTrue:[
   334 		] ifFalse:[
   331                                 name := lineString copyFrom:1 to:l-1.
   335 		    skipping ifFalse:[
   332                             ]
   336 			lineString := lineString withoutSeparators.
   333                         ].
   337 			name := nil.
   334                         name notNil ifTrue:[
   338 			(lineString at:1) == $' ifTrue:[
   335                             rest := lineString copyFrom:l.
   339 			    str := ReadStream on:lineString.
   336                             value := Compiler evaluate:rest.
   340 			    name := String readFrom:str.
   337                             (value == #Error) ifTrue:[
   341 			    l := str position.
   338                                 Transcript show:('error in resource:' , name).
   342 
   339                             ].
   343 "/			    l := lineString indexOf:$' startingAt:2.
   340                             self at:name put:value.
   344 "/			    l ~~ 0 ifTrue:[
   341                         ]
   345 "/				name := (lineString copyFrom:2 to:l-1).
   342                     ]
   346 "/				l := l + 1
   343                 ]
   347 "/			    ]
   344             ]
   348 			] ifFalse:[
   345         ]
   349 			    l := lineString indexOfSeparatorStartingAt:1.
       
   350 			    l ~~ 0 ifTrue:[
       
   351 				name := lineString copyFrom:1 to:l-1.
       
   352 			    ]
       
   353 			].
       
   354 			name notNil ifTrue:[
       
   355 			    rest := (lineString copyFrom:l) withoutSeparators.
       
   356 			    (rest startsWith:'=') ifTrue:[
       
   357 				rest := rest copyFrom:2.
       
   358 				str := ReadStream on:rest.
       
   359 				macroName := str nextWord.
       
   360 				rest := str upToEnd.
       
   361 				value := self at:macroName.
       
   362 				value := Compiler evaluate:('self ' , rest)
       
   363 						  receiver:value
       
   364 						  notifying:nil.
       
   365 			    ] ifFalse:[
       
   366 				value := Compiler evaluate:rest.
       
   367 				(value == #Error) ifTrue:[
       
   368 				    Transcript show:('error in resource:' , name).
       
   369 				]
       
   370 			    ].
       
   371 			    self at:name put:value.
       
   372 			]
       
   373 		    ]
       
   374 		]
       
   375 	    ]
       
   376 	]
   346     ].
   377     ].
   347 ! !
   378 ! !
   348 
   379 
   349 ResourcePack initialize!
   380 ResourcePack initialize!