GnuplotGraphView.st
changeset 5742 5a4a11ee0b1f
child 5750 78ef41988e39
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/GnuplotGraphView.st	Mon Apr 30 22:10:59 2018 +0200
@@ -0,0 +1,251 @@
+"{ Package: 'stx:libwidg2' }"
+
+"{ NameSpace: Smalltalk }"
+
+ImageView subclass:#GnuplotGraphView
+	instanceVariableNames:'script data title'
+	classVariableNames:''
+	poolDictionaries:''
+	category:'Views-Misc'
+!
+
+!GnuplotGraphView class methodsFor:'documentation'!
+
+documentation
+"
+    displays the graph of the data (in model) using a gnuplot script
+
+    [author:]
+        cg
+
+    [instance variables:]
+
+    [class variables:]
+
+    [see also:]
+
+"
+!
+
+examples
+"
+ Notice that everything between [exBegin] and [exEnd] is extracted by the html-doc generator
+ to create nicely formatted and clickable executable examples in the generated html-doc.
+ (see the browsers class-documentation menu items for more)
+
+ trying the widget as standAlone view:
+                                                        [exBegin]
+    GnuplotGraphView new 
+        script:(GnuplotGraphView defaultScript);
+        model:(ValueHolder with:(Random new next:100));
+        open
+                                                        [exEnd]
+
+ embedded in another view:
+                                                        [exBegin]
+    |top v|
+
+    top := StandardSystemView new.
+    top extent:300@300.
+    v := GnuplotGraphView new.
+    v origin:10@10 corner:150@150.
+    top add:v.
+    top open
+                                                        [exEnd]
+"
+! !
+
+!GnuplotGraphView class methodsFor:'defaults'!
+
+defaultScript
+    "return a default initial gnuplot script"
+
+    ^ self defaultScriptForHistogram
+!
+
+defaultScriptForHistogram
+    "a default initial gnuplot script to show a histogram"
+
+    ^ '
+set term %(outputFormat)
+set output "%(outputFile)"
+set title "%(title)"
+plot [-10:110] ''%(data)'' with histogram 
+'
+! !
+
+!GnuplotGraphView methodsFor:'accessing'!
+
+data
+    ^ data
+!
+
+data:something
+    data := something.
+!
+
+script
+    ^ script
+!
+
+script:something
+    script := something.
+!
+
+title
+    ^ title
+!
+
+title:something
+    title := something.
+! !
+
+!GnuplotGraphView methodsFor:'drawing'!
+
+generateDataFileIn:aDirectory
+    "the format of data expected by gnuplot depends on the type of plot:
+        regular plot: a number of values (each in a separate line)
+        multiCol plots: a number of lines, each containing a row
+     here, handle common situations;
+     however, if the data does not match, the program should have prepared the 
+     data into a string and present it as such.
+     Strings will be sent as-is to the file"
+
+    |dataFilename printRow|
+
+    dataFilename := (Filename newTemporaryIn:aDirectory) pathName.
+    dataFilename := dataFilename asFilename withSuffix:'dat'.
+
+    (data isString or:[data isByteArray]) ifTrue:[
+        dataFilename contents:data.
+        ^ dataFilename.
+    ].
+
+    data isCollection ifFalse:[
+        dataFilename contents:data printString.
+        ^ dataFilename.
+    ].
+
+    printRow := 
+        [:s :eachValueOrRow |
+            eachValueOrRow isString ifTrue:[
+                s nextPutAll:eachValueOrRow
+            ] ifFalse:[
+                eachValueOrRow isAssociation ifTrue:[
+                    eachValueOrRow key printOn:s.
+                    s space.
+                    eachValueOrRow value printOn:s.
+                ] ifFalse:[
+                    eachValueOrRow isCollection ifTrue:[
+                        eachValueOrRow 
+                            do:[:element | element printOn:s]
+                            separatedBy:[ s space]
+                    ] ifFalse:[
+                        eachValueOrRow printOn:s
+                    ].
+                ].
+            ].
+            s cr.
+    ].
+
+    dataFilename writingFileDo:[:s |
+        data isSequenceable ifTrue:[
+            data do:[:eachValueOrRow |
+                printRow value:s value:eachValueOrRow.
+            ].
+        ] ifFalse:[
+            data keysAndValuesDo:[:eachKey :eachValueOrRow |
+                eachKey printOn:s.
+                s space.
+                printRow value:s value:eachValueOrRow.
+            ].
+        ].
+    ].
+    ^ dataFilename
+!
+
+generateImage
+    "
+     self new
+        script:(GnuplotGraphView defaultScript);
+        data:(RandomGenerator new next:50);
+        open
+    "
+    |command tmpDir outStream errorStream statusCode ok
+     dataFilename scriptFilename outFilename argsDict expandedScript
+     stdout stderr|
+
+    script isNil ifTrue:[^ self].
+
+    command := 'gnuplot "%1"'.
+    argsDict := Dictionary new.
+
+    tmpDir := Filename tempDirectory.
+
+    data notEmptyOrNil ifTrue:[
+        dataFilename := self generateDataFileIn:tmpDir.
+    ] ifFalse:[
+        dataFilename := ''.
+    ].
+
+    outFilename := (Filename newTemporaryIn:tmpDir) withSuffix:'png'.
+
+    argsDict at:'data' put:dataFilename.
+    argsDict at:'dataSize' put:(data size).
+    argsDict at:'outputFile' put:(outFilename pathName).
+    argsDict at:'outputFormat' put:'png'.
+    argsDict at:'title' put:(title ? '').
+
+    expandedScript := script bindWithArguments:argsDict.
+    scriptFilename := (Filename newTemporaryIn:tmpDir).
+    scriptFilename := scriptFilename asFilename withSuffix:'gnuplot'.
+    scriptFilename contents:expandedScript.
+
+    command := command bindWith:(scriptFilename pathName).
+
+    outStream := '' writeStream.
+    errorStream := '' writeStream.
+
+    ok := OperatingSystem 
+        executeCommand:command
+        inputFrom:Stdin
+        outputTo:outStream
+        errorTo:errorStream
+        environment:nil
+        inDirectory:tmpDir
+        lineWise:true
+        showWindow:false
+        onError:[:status | 
+            statusCode := status code.
+            ok := false.
+        ].
+
+    ok ifFalse:[
+        (stderr := errorStream contents) notEmptyOrNil ifTrue:[
+            Transcript showCR:(stderr withColor:Color red).
+        ].
+    ].
+    (stdout := outStream contents) notEmpty ifTrue:[
+        Transcript showCR:stdout.
+    ].
+
+    image := Image fromFile:outFilename.
+!
+
+generateMagnifiedImage
+    image isNil ifTrue:[
+        self generateImage  
+    ].
+    super generateMagnifiedImage.
+! !
+
+!GnuplotGraphView class methodsFor:'documentation'!
+
+version
+    ^ '$Header$'
+!
+
+version_CVS
+    ^ '$Header$'
+! !
+