From VisualWorks®, 7.6 of February 8, 2008 on March 3, 2008 at 9:41:43 pm (Dialog confirm: 'You are filing-in a Parcel source file!\\While this is possible it will not have\the same effect as loading the parcel.\None of the Parcel''s prerequisites will\be loaded and none of its load actions\will be performed.\\Are you sure you want to file-in?' withCRs) ifFalse: [self error: 'Parcel file-in abandoned. Choose terminate or close.'] <class> <name>CachedBlockClosure</name> <environment>Kernel</environment> <super>Kernel.BlockClosure</super> <private>false</private> none cachedValue <imports></imports> <category>WhenYouComeBack</category> <attributes> <package>Assets</package> </attributes> </class> <comment> Kernel.CachedBlockClosure
I'm a BlockClosure with an added instance variable for storing the once upon a time result of evaluating myself when I was simple BlockClosure. This is triggered by sending #once to a normal BlockClosure. Future sends of once will simply return this value rather than evaluate myself. When sent value, I revert back to a BlockClosure. Instance Variables: cachedValue <Object > result of having sent value to myself when i was just a BlockClosure
</comment> <class> <name>Assets</name> <environment>Core</environment> <super>Core.Object</super> <private>false</private> none lastDirectory <imports></imports> <category>Assets</category> <attributes> <package>Assets</package> </attributes> </class> <comment> Core.Assets
I (and subclasses) am a library of of assets (images, icons, strings, etc), to be used by an application. My methods which return Smallalk objects, can be tagged to specify a file "links" external files in as Smalltalk objects during development time. The method used to turn the file contents into a Smalltalk object is a negotiation between the file's type (extension) and methods provided by the receiver. Implementation Details: Asset classes are singletons. There is never a need to create instances of them. Assets are retrieved by simply sending the name of the asset to the them. A preliminary asset method might look like this: myIcon <file: 'somePath.png'> After it has been "integrated, it would look something like: myIcon <file: 'somePath.png'> <md5sum: #[1 2 3 4 5 6 7 8]> ^[CachedImage on: (Image extent: 2@2 depth: 1 bitsPerPixel: 1 palette: (Graphics.MappedPalette withColors: (#(#(#{Graphics.ColorValue} #scaledRed:scaledGreen:scaledBlue: #(0 0 0)) ) collect: [:each | (each at: 1) value perform: (each at: 2) withArguments: (each at: 3)])) usingBits: #[0 0 0 0 0 0 0 0])] once The following is an explanation of the various parts: - File Specifier: (<file: 'somePath.png'>) The first tag is used to link the method with an external resource. The external resource is specified by the argument which is path to a file. The method that is used to "integrate" the external source file into a reproducible Smalltak object, is determined by the file's extension type. In this case, 'png'. Each import type needs to have a method called import_<extension>: if it is to integrate that file type. For example, the one used in this case is import_png: By default, there is support for gif, jpeg, jpg, bmp, and png. You can add to this set or override them, in either your own subclass or by extending the base Assets class. - Remembered Hash: (<md5sum: #[1 2 3 4 5 6 7 8]>) The second tag (i.e. md5sum:) shows up after we have "integrated" the external file with the method. It is a snapshot of the md5sum of the external file at the time of integration. It can then be used to determine at future points which assets need to be reintegrated because the hash of their external files no longer matches that of the method. - Once Block: (^[....] once) Though the return value of an asset method is an object generated by importing from an external resouce file, it is considered a must that after that fact, the method be able to reproduce the object without the resource file. This is necessary because applications shouldn't require big directories full of files. Applications must be able to be loaded from Store or Parcel without external file references. The code to recreate the object goes in the block. The message once is special. It is like value, in that returns the value of the block. But the value returned is that as rememebered from the first time the block was sent this message. For example, if the contents of the block were to create a new OpaqueImage of moderate size, each time we asked for this asset, performance would be dismal. It would a waste of both cpu cycles and memory. This technique is more than 100 times faster than the former 'ListIconLibrary visualFor: aSymbol' technique.
</comment> <methods> Kernel.CachedBlockClosure <category>private</category>
becomeCached "I am already"
becomeUncached "convert myself back to my uncaching superclass" | withoutCache | withoutCache := ((self copy changeClassTo: Array) allButLast: 1) changeClassTo: BlockClosure. self become: withoutCache
</methods> <methods> Kernel.CachedBlockClosure <category>accessing</category>
once ^cachedValue
</methods> <methods> Kernel.CachedBlockClosure <category>evaluating</category>
value "uncache myself and resend" self becomeUncached. ^self value
</methods> <methods> Kernel.CachedBlockClosure <category>tracing</category>
traceFrom: aTracer "We need to revert back to original block form when parcelling. Our cached value could be any number of non-traceable things." self becomeUncached. self traceFrom: aTracer
</methods> <methods> Kernel.CachedBlockClosure class <category>utility</category>
uncacheAll self allInstances do: [:each | each becomeUncached]
</methods> <methods> Kernel.CachedBlockClosure class <category>initialize-release</category>
obsolete "Removal of this from the system, should revert all blocks that may be cached back to normal 'every-time' blocks." self uncacheAll. super obsolete
</methods> <methods> Core.ByteArray class <category>instance creation</category>
fromNibbleString: aString "Same thing as fromHexString:, but that was taken already." | result map | result := ByteArray new: aString size // 2. map := #(nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 0 1 2 3 4 5 6 7 8 9 nil nil nil nil nil nil nil 10 11 12 13 14 15 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil 10 11 12 13 14 15). 2 to: aString size by: 2 do: [:n | result at: n // 2 put: ((map at: (aString at: n - 1) asInteger) bitShift: 4) + (map at: (aString at: n) asInteger)]. ^result
</methods> <methods> Core.ByteArray <category>printing</category>
printNibblesOn: aStream "Print hexadecimal nibble values on aStream." "| ws | ws := String new writeStream. #[16r89 16r0F] printNibblesOn: ws. ws contents" | chars | chars := '0123456789ABCDEF'. self do: [:each | aStream nextPut: (chars at: (each bitShift: -4) + 1); nextPut: (chars at: (each bitAnd: 16rF) + 1)]
</methods> <methods> Kernel.BlockClosure <category>private</category>
becomeCached "convert myself to my caching subclass with the result of my value loaded in the cache" | withCache | withCache := ((self copy changeClassTo: Array) copyWith: self value) changeClassTo: CachedBlockClosure. self become: withCache
becomeUncached "do nothing"
</methods> <methods> Kernel.BlockClosure <category>accessing</category>
once "cache myself and resend" self becomeCached. ^self once
</methods> <methods> Core.Assets class <category>private-support</category>
housekeepingTags <pragmas: #class> ^#(#md5sum: #file:)
</methods> "Imported Classes:" self error: 'Attempting to file-in parcel imports. Choose terminate or close' <class> <name>Object</name> <environment>Core</environment> <super></super> <private>false</private> none <imports></imports> <category>Kernel-Objects</category> <attributes> <package>Kernel-Objects</package> </attributes> </class> <class> <name>ByteArray</name> <environment>Core</environment> <super>Core.IntegerArray</super> <private>false</private> bytes <imports></imports> <category>Collections-Arrayed</category> <attributes> <package>Collections-Arrayed</package> </attributes> </class> <class> <name>BlockClosure</name> <environment>Kernel</environment> <super>Core.Object</super> <private>false</private> none method outerContext copiedValues <imports></imports> <category>Kernel-Methods</category> <attributes> <package>Kernel-Methods</package> </attributes> </class>