Hi,
since I've been making new icons lately for my project I was frustrated with constantly copying code and methods around... so I've made a small utility for it on top of creating the icons it can add extra stuff like GTInspector support. Any feedback appreciated. Peter |
Tried your install instructions but give me an error[1] about being unable to resolve IconFactory , tries to look inside my package-cache of my image (pharo 4 - 40591 -MACOSX 10). Interesting tool, out of coincidence I am also working with icons but in my cases its SVG icons using Bloc . [1] MetacelloFetchingMCSpecLoader(MetacelloCommonMCSpecLoader)>>retryingResolvePackageSpecReferences:gofer: linearLoadPackageSpec: packageSpec gofer: gofer MetacelloPlatform current do: [ | references nearestReference cachedReference externalReference mcVersion loadedVersionInfos | "check to see if mcz file is already in cacheRepository" cachedReference := self resolvePackageSpec: packageSpec cachedGofer: self loaderPolicy cacheGofer. (cachedReference ~~ nil and: [ packageSpec getFile ~~ nil ]) ifTrue: [ cachedReference name = packageSpec file ifTrue: [ "exact match between packageSpec file and cache" ^ self scheduleFetchFor: packageSpec cachedReference: cachedReference ] ]. "look up mcz file" references := self retryingResolvePackageSpecReferences: packageSpec gofer: gofer. nearestReference := references last asMetacelloCachingResolvedReference. "If the mcz is already in the cacheRepository, no need to copy" (cachedReference ~~ nil and: [ cachedReference name = nearestReference name ]) ifTrue: [ "latest reference in repository matches cachedReference ... " ^ self scheduleFetchFor: packageSpec nearestReference: nearestReference ]. "If the mcz is already loaded into the image, no need to copy" (self ignoreImage not and: [ (loadedVersionInfos := self ancestorsFor: packageSpec) ~~ nil ]) ifTrue: [ loadedVersionInfos do: [ :info | info name = nearestReference name ifTrue: [ ^ self ] ] ]. externalReference := (references select: [ :ref | ref name = nearestReference name ]) first asMetacelloCachingResolvedReference. self repositoryMap at: externalReference name put: externalReference repository. (self resolveDependencies: externalReference nearest: nearestReference into: (OrderedCollection with: nearestReference)) do: [ :reference | | pSpec l | mcVersion := reference version. (l := (GoferVersionReference name: reference name) resolveAllWith: self loaderPolicy cacheGofer) isEmpty ifTrue: [ self cacheRepository storeVersion: mcVersion. reference == nearestReference ifTrue: [ pSpec := packageSpec ] ifFalse: [ pSpec := packageSpec project packageSpec. pSpec name: mcVersion package name ]. self loadData addVersion: mcVersion versionInfo: mcVersion info resolvedReference: reference packageSpec: pSpec ] ]. self scheduleFetchFor: packageSpec externalReference: externalReference ] displaying: 'Fetching ' , packageSpec file in MetacelloFetchingMCSpecLoader>>linearLoadPackageSpec:gofer: in Block: linearLoadPackageSpec: packageSpec gofer: gofer... MetacelloPharo30Platform(MetacelloPlatform)>>do:displaying: MetacelloFetchingMCSpecLoader>>linearLoadPackageSpec:gofer: MetacelloPackageSpec>>loadUsing:gofer: [ :pkg | pkg loadUsing: self gofer: gofer ] in MetacelloFetchingMCSpecLoader(MetacelloCommonMCSpecLoader)>>linearLoadPackageSpecs:repositories: in Block: [ :pkg | pkg loadUsing: self gofer: gofer ] OrderedCollection>>do: MetacelloFetchingMCSpecLoader(MetacelloCommonMCSpecLoader)>>linearLoadPackageSpecs:repositories: [ super linearLoadPackageSpecs: packageSpecs repositories: repositories ] in MetacelloFetchingMCSpecLoader>>linearLoadPackageSpecs:repositories: in Block: [ super linearLoadPackageSpecs: packageSpecs repos...etc... BlockClosure>>ensure: MetacelloLoaderPolicy>>pushLoadDirective:during: MetacelloLoaderPolicy>>pushLinearLoadDirectivesDuring:for: MetacelloFetchingMCSpecLoader>>linearLoadPackageSpecs:repositories: MetacelloFetchingMCSpecLoader(MetacelloCommonMCSpecLoader)>>load MetacelloMCVersionSpecLoader>>load MetacelloMCVersion>>executeLoadFromArray: [ :dict | ^ self executeLoadFromArray: anArray ] in [ self versionSpec loader: newLoader. MetacelloPlatform current useStackCacheDuring: [ :dict | ^ self executeLoadFromArray: anArray ] defaultDictionary: Dictionary new ] in [ [ self versionSpec loader: newLoader. MetacelloPlatform current useStackCacheDuring: [ :dict | ^ self executeLoadFromArray: anArray ] defaultDictionary: Dictionary new ] ensure: [ self versionSpec loader: originalLoader ] ] in MetacelloMCVersion>>fetchRequiredFromArray: in Block: [ :dict | ^ self executeLoadFromArray: anArray ] [ ^ aBlock value: dict ] in MetacelloPharo30Platform(MetacelloPlatform)>>useStackCacheDuring:defaultDictionary: in Block: [ ^ aBlock value: dict ] BlockClosure>>on:do: MetacelloPharo30Platform(MetacelloPlatform)>>useStackCacheDuring:defaultDictionary: [ self versionSpec loader: newLoader. MetacelloPlatform current useStackCacheDuring: [ :dict | ^ self executeLoadFromArray: anArray ] defaultDictionary: Dictionary new ] in [ [ self versionSpec loader: newLoader. MetacelloPlatform current useStackCacheDuring: [ :dict | ^ self executeLoadFromArray: anArray ] defaultDictionary: Dictionary new ] ensure: [ self versionSpec loader: originalLoader ] ] in MetacelloMCVersion>>fetchRequiredFromArray: in Block: [ ... BlockClosure>>ensure: [ [ self versionSpec loader: newLoader. MetacelloPlatform current useStackCacheDuring: [ :dict | ^ self executeLoadFromArray: anArray ] defaultDictionary: Dictionary new ] ensure: [ self versionSpec loader: originalLoader ] ] in MetacelloMCVersion>>fetchRequiredFromArray: in Block: [ ... MetacelloPharo30Platform(MetacelloPlatform)>>do:displaying: MetacelloMCVersion>>fetchRequiredFromArray: [ | fetchLoader | fetchLoader := self fetchRequiredFromArray: (self defaultPackageNamesToLoad: anArray). MetacelloPlatform current do: [ fetchLoader doLoad ] displaying: 'Loading ' , displayString. Transcript cr; show: '...finished ' , self versionNumber printString. ^ fetchLoader ] in MetacelloMCVersion>>doLoadRequiredFromArray: in Block: [ ... BlockClosure>>ensure: MetacelloMCVersion>>doLoadRequiredFromArray: MetacelloMCVersion>>load GoferMetacelloLoad>>loadConfiguration On Sat, Apr 4, 2015 at 2:50 PM, Peter Uhnák <[hidden email]> wrote:
|
That's strange :< try this please Gofer new smalltalkhubUser: 'peteruhnak' project: 'IconFactory'; package: 'IconFactory'; load. In the meantime I'll be fixing the configuration... but it should be ok. :/ Peter On Sat, Apr 4, 2015 at 2:00 PM, kilon alios <[hidden email]> wrote:
|
yes thats better , install works, first step works too. createIconsFromDirectory seems to see only the first png, maybe because its too large. createIconFromFile gives me a MNU: ByteString >> base [1]. Why those methods are not on the class side ? [1]ByteString(Object)>>doesNotUnderstand: #base IconFactory>>createIconFromFile:inClass: UndefinedObject>>DoIt OpalCompiler>>evaluate SmalltalkEditor>>evaluateSelectionAndDo: SmalltalkEditor>>evaluateSelection [ textMorph editor evaluateSelection ] in PluggableTextMorph>>doIt in Block: [ textMorph editor evaluateSelection ] [ result := editBlock value ] in PluggableTextMorph>>handleEdit: in Block: [ result := editBlock value ] TextMorphForEditView(TextMorph)>>handleEdit: PluggableTextMorph>>handleEdit: PluggableTextMorph>>doIt Workspace(Object)>>perform:orSendTo: [ | selArgCount | "show cursor in case item opens a new MVC window" (selArgCount := selector numArgs) = 0 ifTrue: [ target perform: selector ] ifFalse: [ selArgCount = arguments size ifTrue: [ target perform: selector withArguments: arguments ] ifFalse: [ target perform: selector withArguments: (arguments copyWith: evt) ] ]. self changed ] in ToggleMenuItemMorph(MenuItemMorph)>>invokeWithEvent: in Block: [ ... BlockClosure>>ensure: CursorWithMask(Cursor)>>showWhile: ToggleMenuItemMorph(MenuItemMorph)>>invokeWithEvent: ToggleMenuItemMorph(MenuItemMorph)>>mouseUp: ToggleMenuItemMorph(MenuItemMorph)>>handleMouseUp: MouseButtonEvent>>sentTo: ToggleMenuItemMorph(Morph)>>handleEvent: MorphicEventDispatcher>>dispatchDefault:with: MorphicEventDispatcher>>handleMouseUp: MouseButtonEvent>>sentTo: [ ^ anEvent sentTo: self ] in MorphicEventDispatcher>>dispatchEvent:with: in Block: [ ^ anEvent sentTo: self ] BlockClosure>>ensure: MorphicEventDispatcher>>dispatchEvent:with: ToggleMenuItemMorph(Morph)>>processEvent:using: MorphicEventDispatcher>>dispatchDefault:with: MorphicEventDispatcher>>handleMouseUp: MouseButtonEvent>>sentTo: |
how large?
it accepts a FileReference, not a string; I should put guard there. Peter |
Also if it really sees only the first file, try dir allFiles select: [ :each | each extension = 'png' ], because that would mean FileSystem is failing or something. Peter On Sat, Apr 4, 2015 at 2:41 PM, Peter Uhnák <[hidden email]> wrote:
|
Administrator
|
In reply to this post by Peter Uhnak
Or it seems cheap enough to just send #asFileReference to give the user a bit of flexibility
Cheers,
Sean |
In reply to this post by Peter Uhnak
actually i was wrong its not that large, only 34kbs , I have also attached it if you want to take a look at it. On Sat, Apr 4, 2015 at 3:41 PM, Peter Uhnák <[hidden email]> wrote:
cpctest.png (44K) Download Attachment |
In reply to this post by Sean P. DeNigris
Or it seems cheap enough to just send #asFileReference to give the user a Yep, I've changed that. Interesting that google is showing me, that you've replied 8 minutes before I even posted it. :) |
In reply to this post by kilon.alios
On Sat, Apr 4, 2015 at 2:46 PM, kilon alios <[hidden email]> wrote:
This works just fine for me; does it show any error for you? Or did it just create one file and then gave up? Peter |
create file ? i thought the class only creates methods anyway, the method is created , but it does not proceed to next png. Shouldn create a method for each png it finds in the directory ?On Sat, Apr 4, 2015 at 3:54 PM, Peter Uhnák <[hidden email]> wrote:
|
yeah, I mean method
yes it should, it operates on a collection, so if dir allFiles select: [ :each | each extension = 'png' ] shows more then one file it should also create a method for each one, not just the first Peter |
I found the problem looks like it does not like that i use "-" inside the file name. In the folder the name of the file is not Norse_large-cpc.png but Norse-large-cpc.png "Norse_largeThe '-' prefix works only for literal numbers (use #negated instead) -> -cpcIconContents "Private - Method generated with the content of the file File @ /Users/kilon/Downloads/Norse_large-cpc.png"" On Sat, Apr 4, 2015 at 4:12 PM, Peter Uhnák <[hidden email]> wrote:
|
Aha, of course. The program makes assumptions about the file name and since it is naming the method like the file it fails, because you can't have "-" in method name. I could change it so it removes all non-alphanumeric characters from the name. Peter On Sat, Apr 4, 2015 at 3:52 PM, kilon alios <[hidden email]> wrote:
|
once more I really dont like idea of methods returning single values. This also one of the reasons why Spec annoys me. Why not have Collection / Dictionary that stores all these strings ? Having 100 methods for 100 icons seems really ugly . Instead one collection with 100 entries and a single method would be more than enough. I know its not just you that do this and is how icons work in Pharo .Its basically how many things work like this inside Pharo. But I still dont get it.... why ? On Sat, Apr 4, 2015 at 5:15 PM, Peter Uhnák <[hidden email]> wrote:
|
Because composition/decomposition is good (among others for re-use), because with separate entries you can browse them more easily, because we don't like long methods, ... You get the idea ;-)
> On 04 Apr 2015, at 16:45, kilon alios <[hidden email]> wrote: > > once more I really dont like idea of methods returning single values. This also one of the reasons why Spec annoys me. Why not have Collection / Dictionary that stores all these strings ? Having 100 methods for 100 icons seems really ugly . Instead one collection with 100 entries and a single method would be more than enough. > > I know its not just you that do this and is how icons work in Pharo .Its basically how many things work like this inside Pharo. But I still dont get it.... why ? > > On Sat, Apr 4, 2015 at 5:15 PM, Peter Uhnák <[hidden email]> wrote: > Aha, of course. > The program makes assumptions about the file name and since it is naming the method like the file it fails, because you can't have "-" in method name. > I could change it so it removes all non-alphanumeric characters from the name. > > Peter > > On Sat, Apr 4, 2015 at 3:52 PM, kilon alios <[hidden email]> wrote: > I found the problem > > "Norse_largeThe '-' prefix works only for literal numbers (use #negated instead) -> -cpcIconContents > "Private - Method generated with the content of the file File @ /Users/kilon/Downloads/Norse_large-cpc.png"" > > looks like it does not like that i use "-" inside the file name. In the folder the name of the file is not Norse_large-cpc.png but Norse-large-cpc.png > > "-" has some special meaning here ? > > On Sat, Apr 4, 2015 at 4:12 PM, Peter Uhnák <[hidden email]> wrote: > create file ? i thought the class only creates methods > yeah, I mean method > > anyway, the method is created , but it does not proceed to next png. Shouldn create a method for each png it finds in the directory ? > yes it should, it operates on a collection, so if > dir allFiles select: [ :each | each extension = 'png' ] > shows more then one file it should also create a method for each one, not just the first > > Peter > > > |
No really I dont get the idea, composition decomposition is the bread and butter of collection types in any language. Unless pharo has a weakness in this area that I am not aware of, in python I had never such problem. actually its a foremost reason to use them in the first place. Browsing is a limitation of the browser which does not provide a special view for variables but not that hard to amend with inspector. And I find hard to believe you prefer a ton of short methods instead one short one for returning those values. The only reason I can think in this case of icons is that compiling a string as return value of a method to be used statically is easier/ more convenient than defining a huge collection in the initialize method. Thats the only way I see for avoiding long methods. On Sat, Apr 4, 2015 at 6:01 PM, Sven Van Caekenberghe <[hidden email]> wrote: Because composition/decomposition is good (among others for re-use), because with separate entries you can browse them more easily, because we don't like long methods, ... You get the idea ;-) |
Maybe we are not talking about the same thing ?
You question the fact that the resource is stored as source code in the image instead of in a file ? If so, then the reason to keep them in image has to do with resource management, an image is self contained. I was talking about managing resources as a collection of methods, an example would be ZnByteEncoder, where mappings are defined on the class side. If resources are originally downloaded from somewhere else but cached inside the image, it is worth mentioning that, and shipping the necessary code to redo it, in the case of the example, #generateByteToUnicodeSpec: > On 04 Apr 2015, at 17:17, kilon alios <[hidden email]> wrote: > > No really I dont get the idea, composition decomposition is the bread and butter of collection types in any language. Unless pharo has a weakness in this area that I am not aware of, in python I had never such problem. actually its a foremost reason to use them in the first place. Browsing is a limitation of the browser which does not provide a special view for variables but not that hard to amend with inspector. And I find hard to believe you prefer a ton of short methods instead one short one for returning those values. > > The only reason I can think in this case of icons is that compiling a string as return value of a method to be used statically is easier/ more convenient than defining a huge collection in the initialize method. > > on the other hand would not make more sense to have all this data that means nothing for the user as separate files and let them load at the startup of the image ? Its not as if anyone would bother editing those huge gibberish strings . > > Thats the only way I see for avoiding long methods. > > Or am I missing something here ? > > On Sat, Apr 4, 2015 at 6:01 PM, Sven Van Caekenberghe <[hidden email]> wrote: > Because composition/decomposition is good (among others for re-use), because with separate entries you can browse them more easily, because we don't like long methods, ... You get the idea ;-) > > > On 04 Apr 2015, at 16:45, kilon alios <[hidden email]> wrote: > > > > once more I really dont like idea of methods returning single values. This also one of the reasons why Spec annoys me. Why not have Collection / Dictionary that stores all these strings ? Having 100 methods for 100 icons seems really ugly . Instead one collection with 100 entries and a single method would be more than enough. > > > > I know its not just you that do this and is how icons work in Pharo .Its basically how many things work like this inside Pharo. But I still dont get it.... why ? > > > > On Sat, Apr 4, 2015 at 5:15 PM, Peter Uhnák <[hidden email]> wrote: > > Aha, of course. > > The program makes assumptions about the file name and since it is naming the method like the file it fails, because you can't have "-" in method name. > > I could change it so it removes all non-alphanumeric characters from the name. > > > > Peter > > > > On Sat, Apr 4, 2015 at 3:52 PM, kilon alios <[hidden email]> wrote: > > I found the problem > > > > "Norse_largeThe '-' prefix works only for literal numbers (use #negated instead) -> -cpcIconContents > > "Private - Method generated with the content of the file File @ /Users/kilon/Downloads/Norse_large-cpc.png"" > > > > looks like it does not like that i use "-" inside the file name. In the folder the name of the file is not Norse_large-cpc.png but Norse-large-cpc.png > > > > "-" has some special meaning here ? > > > > On Sat, Apr 4, 2015 at 4:12 PM, Peter Uhnák <[hidden email]> wrote: > > create file ? i thought the class only creates methods > > yeah, I mean method > > > > anyway, the method is created , but it does not proceed to next png. Shouldn create a method for each png it finds in the directory ? > > yes it should, it operates on a collection, so if > > dir allFiles select: [ :each | each extension = 'png' ] > > shows more then one file it should also create a method for each one, not just the first > > > > Peter > > > > > > > > > |
"Maybe we are not talking about the same thing ?" We do I just brought an alternative. My initial question is why this data is not stored inside a Collection and instead individual methods are preferred. But now that I thought it through I understand in practice would not make much difference. And as you said methods are already browsable, Collections are not. "If so, then the reason to keep them in image has to do with resource management, an image is self contained. I was talking about managing resources as a collection of methods, an example would be ZnByteEncoder, where mappings are defined on the class side. If resources are originally downloaded from somewhere else but cached inside the image, it is worth mentioning that, and shipping the necessary code to redo it, in the case of the example, #generateByteToUnicodeSpec:" Yeah I think I understand that now too, it makes the distribution of the image much easier not to have to worry about external resources. Yes I did understood what you were talking about, I just was not clear about the benefits of this approach over using Collections and instance variables instead. But I do think that now I understand . Thank you for trying to help me understand :) It was important for me to understand this because I want to import a lot of SVG data into the image and I was not sure if I should use just SVG files or instead use methods that return SVG strings. I would be using methods since it will make my distribution much simpler and easier to version control too. |
> On 05 Apr 2015, at 20:16, kilon alios <[hidden email]> wrote: > > Thank you for trying to help me understand :) You're welcome. > It was important for me to understand this because I want to import a lot of SVG data into the image and I was not sure if I should use just SVG files or instead use methods that return SVG strings. I would be using methods since it will make my distribution much simpler and easier to version control too. SVG is human readable (XML based), no ? If they are not too large, it might even be quite useful to store them as strings in the image, although I do agree this is not scalable in the end. (But Seaside uses this mechanism to store real images in the image, and that works very well during development, in the sense that it is convenient). |
Free forum by Nabble | Edit this page |