Second try (was Re: [GOODIE] MacOSXGraphVizGenerator-dd)
Lic. Edgar J. De Cleene
edgardec2001 at yahoo.com.ar
Sat Mar 12 08:26:36 UTC 2005
On 11/03/05 19:47, "John Pierce" <john.raymond.pierce at gmail.com> wrote:
> I'm sorry if I misunderstand, but where is the tested Mac code for
> GraphViz I can incorporate? I only got a morph attachment in the last
> email.
Yes, blame the 100 k limit.
Original mail have the two and was rejected, so I split
Here is yours original, more Dominique "idea", more my tune-up. (very
little)
>>Would you like developer access to my SqueakSource project so you can
>>just put in the Mac extensions? That could be the most direct route
>>if you feel comfortable with that.
>>John
If you have a little time for IRC exchange , I prefer, but if not the case,
I agree.
I have a semi backed parse, and I hope finishing it today.
Some questions remains, as I load the png and other graphic formats
generated for GraphViz in image programs as GraphicConverter, and see the
pixels data don't match the inches data (in GraphicConverter and xxx.txt
exported files)
Also , when the png are very huge (more 10000 x 10000 pixels as originated
by Morphic-Basic) , don't be saved to disk,
I not familiar with GraphViz project, but like know if was possible do the
conversion on C side and have a new exporting format "Squeak compatible"
with more reliable/useful data.
Regards
Edgar
-------------- next part --------------
Object subclass: #GraphViz
instanceVariableNames: 'graphName contentStream directed indentLevel'
classVariableNames: ''
poolDictionaries: ''
category: 'GraphViz'!
!GraphViz methodsFor: 'accessing' stamp: 'jrp 2/26/2005 23:37'!
baseFileName
^ graphName ifNil: ['unnamed']! !
!GraphViz methodsFor: 'accessing' stamp: 'jrp 2/26/2005 17:01'!
beDirected
directed _ true! !
!GraphViz methodsFor: 'accessing' stamp: 'jrp 2/26/2005 17:03'!
beUndirected
directed _ false! !
!GraphViz methodsFor: 'accessing' stamp: 'jrp 2/28/2005 23:39'!
dot
^ String streamContents: [:stream |
directed ifTrue: [stream nextPutAll: 'di'].
stream nextPutAll: 'graph'.
graphName ifNotNilDo: [:name | stream nextPut: $ ;nextPutAll: (self safeIdFor: name)].
stream nextPutAll: ' {'.
stream nextPutAll: contentStream contents.
stream cr; nextPut: $}]! !
!GraphViz methodsFor: 'accessing' stamp: 'jrp 2/27/2005 21:39'!
dotExtension
^ '.dot'! !
!GraphViz methodsFor: 'accessing' stamp: 'jrp 2/27/2005 21:39'!
dotFileName
^ self baseFileName, self dotExtension! !
!GraphViz methodsFor: 'accessing' stamp: 'jrp 2/26/2005 16:14'!
name
^ graphName! !
!GraphViz methodsFor: 'accessing' stamp: 'jrp 2/26/2005 16:14'!
name: aString
graphName _ aString! !
!GraphViz methodsFor: 'accessing' stamp: 'jrp 2/27/2005 23:55'!
safeIdFor: anObject
| hasWhiteSpace firstCharIsDigit |
anObject isNumber ifTrue: [^ anObject asString].
anObject isString ifTrue:
[(anObject first = $< and: [anObject last = $>]) ifTrue: [^ anObject].
(anObject first = $" and: [anObject last = $"]) ifTrue: [^ anObject].
hasWhiteSpace _ anObject lastSpacePosition > 0.
hasWhiteSpace ifTrue: [^ '"', anObject, '"'].
firstCharIsDigit _ anObject first isDigit.
firstCharIsDigit ifTrue: [^ '"', anObject, '"'].
anObject do: [:char | (char isAlphaNumeric or: [char = $_]) ifFalse: [^ '"', anObject, '"']]].
^ anObject asString! !
!GraphViz methodsFor: 'graphing' stamp: 'jrp 2/27/2005 21:12'!
add: anObject
self add: anObject with: #()! !
!GraphViz methodsFor: 'graphing' stamp: 'jrp 2/27/2005 21:30'!
add: anObject with: associations
| attributes |
anObject isVariableBinding
ifFalse: [self writeNode: anObject]
ifTrue: [self writeEdge: anObject].
attributes _ associations isCollection ifTrue: [associations] ifFalse: [{associations}].
attributes isEmpty
ifTrue: [contentStream nextPut: $;]
ifFalse: [self writeAttributes: attributes]! !
!GraphViz methodsFor: 'graphing' stamp: 'jrp 2/28/2005 23:42'!
indentStream
indentLevel timesRepeat: [contentStream tab]! !
!GraphViz methodsFor: 'graphing' stamp: 'jrp 3/1/2005 07:40'!
subgraph: aString do: aBlock
contentStream cr.
self indentStream.
contentStream nextPutAll: 'subgraph'.
aString ifNotNilDo: [:name | contentStream nextPut: $ ;nextPutAll: (self safeIdFor: name)].
contentStream nextPutAll: ' {'.
indentLevel _ indentLevel + 1.
[aBlock value] ensure:
[indentLevel _ indentLevel - 1.
contentStream cr.
self indentStream.
contentStream nextPut: $}]! !
!GraphViz methodsFor: 'graphing' stamp: 'jrp 3/1/2005 07:40'!
subgraphDo: aBlock
self subgraph: nil do: aBlock! !
!GraphViz methodsFor: 'graphing' stamp: 'jrp 2/27/2005 23:43'!
writeAttributes: associations
contentStream nextPutAll: ' ['.
associations
do: [:each |
contentStream
nextPutAll: (self safeIdFor: each key);
nextPut: $=;
nextPutAll: (self safeIdFor: each value)]
separatedBy: [contentStream nextPut: $,].
contentStream nextPutAll: '];'! !
!GraphViz methodsFor: 'graphing' stamp: 'jrp 2/28/2005 23:42'!
writeEdge: anAssociation
contentStream cr.
self indentStream.
contentStream nextPutAll: (self safeIdFor: anAssociation key).
directed
ifTrue: [contentStream nextPutAll: ' -> ']
ifFalse: [contentStream nextPutAll: ' -- '].
contentStream nextPutAll: (self safeIdFor: anAssociation value)! !
!GraphViz methodsFor: 'graphing' stamp: 'jrp 2/28/2005 23:40'!
writeNode: anObject
contentStream cr.
self indentStream.
contentStream nextPutAll: (self safeIdFor: anObject)! !
!GraphViz methodsFor: 'graphing' stamp: 'jrp 2/26/2005 23:36'!
writeToFile
self writeToFileNamed: self dotFileName! !
!GraphViz methodsFor: 'graphing' stamp: 'jrp 2/27/2005 21:40'!
writeToFileNamed: aString
| fileName file |
fileName _ aString.
(aString endsWith: self dotExtension) ifFalse: [fileName _ fileName, self dotExtension].
file _ FileStream forceNewFileNamed: fileName.
[file nextPutAll: self dot] ensure: [file close]! !
!GraphViz methodsFor: 'initialization' stamp: 'jrp 2/28/2005 23:41'!
initialize
directed _ false.
contentStream _ String new writeStream.
indentLevel _ 1.! !
!GraphViz methodsFor: 'displaying' stamp: 'edc 3/11/2005 09:32'!
asMorph
| generator maxTimesToWait try fondoA t aWindow title |
self writeToFile.
generator := self class defaultGeneratorClass new.
directed
ifTrue: [generator runDotOn: self outputFormat: #jpg]
ifFalse: [generator runNeatoOn: self outputFormat: #jpg].
maxTimesToWait := 22.
try := 0.
fondoA:= [(ImageReadWriter formFromFileNamed: self baseFileName, '.png') asMorph]
on: Error
do:
[:err |
try := try + 1.
try > maxTimesToWait ifTrue: [^ 'GraphViz image could not be generated in approximately 45 seconds or less' asMorph].
2 second asDelay wait. err retry].
t := ScrollPane new.
t scroller addMorph: fondoA.
title := 'Squeak Road Map For : ' ,self baseFileName .
aWindow := (SystemWindow labelled: title)
model: nil.
aWindow
bounds: (fondoA position - (0 @ aWindow labelHeight + aWindow borderWidth) corner: fondoA bottomRight + aWindow borderWidth).
aWindow
addMorph: t
frame: (0 @ 0 extent: 1 @ 1).
aWindow setWindowColor: Color veryLightGray.
^aWindow .! !
"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
GraphViz class
instanceVariableNames: ''!
!GraphViz class methodsFor: 'samples' stamp: 'jrp 3/2/2005 00:08'!
directedGraphSample1
"GraphViz directedGraphSample1"
| graph |
graph _ GraphViz new.
graph
beDirected;
name: #directedGraphSample1;
add: #graph with: {#ratio -> '0.5'};
add: #node with: {#fontsize -> 10};
add: #Smalltalk -> #Squeak;
add: #Smalltalk -> 'C++';
add: 'C++' -> #Java;
add: #Java -> 'C#';
openAsMorph! !
!GraphViz class methodsFor: 'samples' stamp: 'jrp 3/1/2005 07:39'!
directedGraphSample2
"GraphViz directedGraphSample2"
| graph |
graph _ GraphViz new.
graph beDirected.
graph
name: #directedGraphSample2;
add: #node with: {#fontsize -> 28};
subgraph: #clusterfoo do:
[graph
add: #subgraph with: {#style -> #filled. #fillcolor -> #lightgrey};
add: #A -> #B;
add: #subgraph with: #label -> #Foo].
graph
add: #A -> #J;
add: #B -> #Z;
add: #graph with: {#label -> 'Cluster Graph'. #fontsize -> 50};
openAsMorph! !
!GraphViz class methodsFor: 'samples' stamp: 'edc 3/10/2005 17:28'!
hierarchyForClassesInCategoriesMatching: symbol
"GraphViz hierarchyForClassesInCategoriesMatching: 'System-Archives'"
"GraphViz hierarchyForClassesInCategoriesMatching: 'Collections-Weak'"
"GraphViz hierarchyForClassesInCategoriesMatching: #DynamicBindings"
| graph edges |
graph := GraphViz new.
graph beDirected.
graph
name: symbol;
add: #graph with: {#overlap -> #scale. #concentrate -> #true. #bgcolor -> #transparent};
add: #node with: {#shape -> #box. #fontsize -> 11. #style -> #filled. #fillcolor -> #tomato};
add: #edge with: {#arrowsize -> 0.5}.
edges := Set new.
(SystemOrganization categoriesMatching: (symbol, '*')) do:
[:cat |
(SystemOrganization listAtCategoryNamed: cat) do:
[:klass | | browser hierarchy |
graph add: klass with: {#fillcolor -> #palegreen}.
browser := HierarchyBrowser new initHierarchyForClass: (Smalltalk at: klass).
hierarchy := (browser classList collect: [:each | each withBlanksTrimmed asSymbol]).
hierarchy pairsDo: [:first :second | edges add: first -> second]]].
edges do: [:each | graph add: each].
graph
add: #graph with: {#label -> symbol. #fontsize -> 24};
openAsMorph.
! !
!GraphViz class methodsFor: 'samples' stamp: 'jrp 3/3/2005 00:20'!
referencesToClassesInCategoriesMatching: symbol
"GraphViz referencesToClassesInCategoriesMatching: 'System-Archives'"
"GraphViz referencesToClassesInCategoriesMatching: 'Collections-Weak'"
"GraphViz referencesToClassesInCategoriesMatching: #DynamicBindings"
| graph edges |
graph _ GraphViz new.
graph
name: symbol;
add: #graph with: {#overlap -> #scale. #concentrate -> #true. #start -> #rand. #splines -> #true. #bgcolor -> #transparent};
add: #node with: {#shape -> #box. #fontsize -> 14. #style -> #filled. #fillcolor -> #tomato};
add: #edge with: {#arrowtail -> #normal. #arrowsize -> 0.5}.
edges _ Set new.
(SystemOrganization categoriesMatching: (symbol, '*')) do:
[:cat |
(SystemOrganization listAtCategoryNamed: cat) do:
[:klass |
graph add: klass with: {#fillcolor -> #palegreen}.
(Smalltalk at: klass) allCallsOn do: [:each | edges add: klass -> each classSymbol]]].
edges do: [:each | graph add: each].
graph
add: #graph with: {#label -> symbol. #fontsize -> 40};
openAsMorph! !
!GraphViz class methodsFor: 'samples' stamp: 'jrp 2/28/2005 07:37'!
undirectedGraphSample1
"GraphViz undirectedGraphSample1"
| graph |
graph _ GraphViz new.
graph
name: #undirectedGraphSample1;
add: #graph with: #start -> #rand;
add: #node with: {#fontsize -> 28};
add: #A -> #X;
add: #node with: #shape -> #box;
add: #J with: {#style -> #filled. #fillcolor -> #red. #label -> 'J\nRed'};
add: #A -> #J;
add: #A -> #Z;
add: #graph with: {#label -> 'Test Graph'. #fontsize -> 50};
openAsMorph! !
!GraphViz class methodsFor: 'samples' stamp: 'jrp 3/2/2005 23:32'!
usersOfBag
"GraphViz usersOfBag"
| graph |
graph _ GraphViz new.
graph
name: #usersOfBag;
add: #graph with: {#size -> '8,8'. #overlap -> #scale. #splines -> #true. #concentrate -> #true};
add: #Bag;
add: #node with: {#fontsize -> 10}.
Bag allCallsOn do:
[:each |
graph add: (each classSymbol, '>>', each methodSymbol) with: #label -> (each classSymbol, '>>\n', each methodSymbol).
graph
add: #Bag -> (each classSymbol, '>>', each methodSymbol)
with: {#arrowtail -> #normal. #arrowsize -> 0.5}].
graph
add: #graph with: {#label -> 'Users of Bag'. #fontsize -> 50};
openAsMorph! !
!GraphViz class methodsFor: 'samples' stamp: 'edc 3/10/2005 11:14'!
usersOfMorph
"GraphViz usersOfMorph"
| graph |
graph := GraphViz new.
graph
name: #usersOfBag;
add: #graph with: {#size -> '8,8'. #overlap -> #scale. #splines -> #true. #concentrate -> #true};
add: #Morph;
add: #node with: {#fontsize -> 10}.
Morph allCallsOn do:
[:each |
graph add: (each classSymbol, '>>', each methodSymbol) with: #label -> (each classSymbol, '>>\n', each methodSymbol).
graph
add: #Morph -> (each classSymbol, '>>', each methodSymbol)
with: {#arrowtail -> #normal. #arrowsize -> 0.5}].
graph
add: #graph with: {#label -> 'Users of Morph'. #fontsize -> 36};
openAsMorph! !
!GraphViz class methodsFor: 'as yet unclassified' stamp: 'edc 3/9/2005 05:38'!
defaultGeneratorClass
^ MacOSXGraphVizGenerator! !
Object subclass: #GraphVizGenerator
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'GraphViz'!
!GraphVizGenerator methodsFor: 'generating' stamp: 'jrp 2/27/2005 21:58'!
runDotOn: graphviz outputFormat: aString
self runOSProcess: #dot with: (self commandLineFor: graphviz outputFormat: aString)! !
!GraphVizGenerator methodsFor: 'generating' stamp: 'jrp 3/2/2005 23:30'!
runFdpOn: graphviz outputFormat: aString
self runOSProcess: #fdp with: (self commandLineFor: graphviz outputFormat: aString)! !
!GraphVizGenerator methodsFor: 'generating' stamp: 'jrp 2/27/2005 21:57'!
runNeatoOn: graphviz outputFormat: aString
self runOSProcess: #neato with: (self commandLineFor: graphviz outputFormat: aString)! !
!GraphVizGenerator methodsFor: 'generating' stamp: 'jrp 3/2/2005 23:30'!
runTwopiOn: graphviz outputFormat: aString
self runOSProcess: #twopi with: (self commandLineFor: graphviz outputFormat: aString)! !
!GraphVizGenerator methodsFor: 'private' stamp: 'jrp 2/27/2005 21:53'!
runOSProcess: command with: arguments
self subclassResponsibility! !
!GraphVizGenerator methodsFor: 'accessing' stamp: 'edc 3/9/2005 08:21'!
commandLineFor: graphviz outputFormat: outputFormat
^ String streamContents:
[:stream |
stream
nextPutAll: graphviz dotFileName;
nextPutAll: ' -T';
nextPutAll: outputFormat;
nextPut: $ ;
nextPutAll: ' -o ';
nextPutAll: graphviz baseFileName;
nextPut: $.;
nextPutAll: outputFormat]! !
GraphVizGenerator subclass: #MacOSXGraphVizGenerator
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'GraphViz'!
!MacOSXGraphVizGenerator methodsFor: 'accessing' stamp: 'edc 3/10/2005 10:49'!
commandLineFor: graphviz outputFormat: outputFormat
^ String streamContents:
[:stream |
stream
nextPutAll: self outputPath;
nextPutAll: graphviz dotFileName;
nextPutAll: ' -T';
nextPutAll: outputFormat;
nextPut: $ ;
nextPutAll: ' -o';
nextPutAll: self outputPath;
nextPutAll: graphviz baseFileName;
nextPut: $.;
nextPutAll: outputFormat]! !
!MacOSXGraphVizGenerator methodsFor: 'accessing' stamp: 'edc 3/9/2005 07:53'!
outputFileFor: aExtension
| s |
s _ self name ,aExtension! !
!MacOSXGraphVizGenerator methodsFor: 'accessing' stamp: 'edc 3/10/2005 17:13'!
outputPath
| aPath prefix |
aPath := FileDirectory default pathName,FileDirectory slash.
prefix := self isCarbonVM ifTrue: [ '/Volumes/' ] ifFalse: [ '' ].
^ prefix, (aPath copyReplaceAll: $: asString with: $/ asString)! !
!MacOSXGraphVizGenerator methodsFor: 'external calls' stamp: 'dd 3/8/2005 18:26'!
runWithLibC: string
<cdecl: short 'system' (char*) module: '/usr/lib/libc.dylib'>
^self externalCallFailed ! !
!MacOSXGraphVizGenerator methodsFor: 'external calls' stamp: 'dd 3/8/2005 18:25'!
runWithSystemFramework: string
<apicall: short 'system' (char*) module: 'System.framework'>
^self externalCallFailed ! !
!MacOSXGraphVizGenerator methodsFor: 'private' stamp: 'dd 3/8/2005 18:52'!
isCarbonVM
^(SmalltalkImage current platformName = 'Mac OS' and: [ SmalltalkImage current osVersion asNumber >= 1000 ])! !
!MacOSXGraphVizGenerator methodsFor: 'private' stamp: 'edc 3/10/2005 17:08'!
posixPathFor
"Answer a path which can be used with the system function from libc or System.framework."
| prefix aPath |
"Put /Volumes/ in front of the volume name. eg /Volumes/Macintosh HD"
aPath _ self outputPath .
prefix := self isCarbonVM ifTrue: [ '/Volumes/' ] ifFalse: [ '' ].
^ $" asString, prefix, (aPath copyReplaceAll: $: asString with: $/ asString), $" asString.! !
!MacOSXGraphVizGenerator methodsFor: 'private' stamp: 'dd 3/8/2005 20:19'!
posixPathFor: aPath
"Answer a path which can be used with the system function from libc or System.framework."
| prefix |
"Put /Volumes/ in front of the volume name. eg /Volumes/Macintosh HD"
prefix _ self isCarbonVM ifTrue: [ '/Volumes/' ] ifFalse: [ '' ].
^ $" asString, prefix, (aPath copyReplaceAll: $: asString with: $/ asString), $" asString.! !
!MacOSXGraphVizGenerator methodsFor: 'private' stamp: 'edc 3/10/2005 16:37'!
runOSProcess: command with: arguments
| helperCommand |
helperCommand := '/Applications/Graphviz.app/Contents/MacOS/', command.
helperCommand := helperCommand, ' ', arguments.
Transcript show: helperCommand;cr.
self isCarbonVM ifTrue: [ self runWithSystemFramework: helperCommand. ] ifFalse: [ self runWithLibC: helperCommand. ].! !
!MacOSXGraphVizGenerator methodsFor: 'private' stamp: 'edc 3/10/2005 16:36'!
runOSProcess: command with: arguments inDir: path
| helperCommand |
helperCommand := '/Applications/Graphviz.app/Contents/MacOS/', command.
helperCommand := helperCommand, ' ', arguments.
Transcript show: helperCommand;cr.
self isCarbonVM ifTrue: [ self runWithSystemFramework: helperCommand. ] ifFalse: [ self runWithLibC: helperCommand. ].! !
!MacOSXGraphVizGenerator methodsFor: 'generating' stamp: 'dd 3/8/2005 20:23'!
convertDotToXml: inputFile
| xmlFile commandLine |
xmlFile _ self outputFileFor: #xml.
commandLine _ String streamContents:
[:stream |
stream
nextPutAll: '-o';
nextPutAll: (self posixPathFor: xmlFile);
nextPut: $ ;
nextPutAll: (self posixPathFor: inputFile)
].
self
runOSProcess: #cvtgxl
with: commandLine
inDir: self outputPath fullName.
^ xmlFile! !
GraphVizGenerator subclass: #Win32GraphVizGenerator
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'GraphViz'!
!Win32GraphVizGenerator methodsFor: 'private' stamp: 'jrp 2/27/2005 21:53'!
runOSProcess: command with: arguments
| shell |
shell _ Win32Shell new.
shell
shellExecute: nil
lpOperation: 'open'
lpFile: command
lpParameters: arguments
lpDirectory: nil
nShowCmd: 0! !
More information about the Squeak-dev
mailing list
|