(* ::Package:: *)

(* :Title: JavaView via RunThrough *)

(* :Context: JavaView`RunThrough` *)

(* :Author:
		Konrad Polthier
		support@javaview.de
		www.javaview.de/
*)

(* :Package Version: 3.4.2 *)
(* :History 3.0.3, 16.03.2020: Some code beautifications. *)
(* :History 3.0.3, 16.03.2020: Compatibility to Mathematica 12.0., adjusted to new setting of installation path and of codebase.
                               Method findCurrentPkg[] for finding installation path of JavaView replaced with explicit setting
                               by user into new variable JavaView::InstallationPath. 
                               *)
(* :History 2.0.0, 26.03.2015: Compatibility to Mathematica 10.0., support of 5.x and 4.x lowered.
                               Working path now defaults to $UserDocumentsDirectory instead of installation directory.
                               Command RunJavaView now uses own RunThroughOK instead of system RunThrough
                               to circumvent missing quotes which should enclose MS Windows path names with blanks. *)
(* :History 1.1.5, 17.09.2006: Additional quotes around path names since Mathematica 5.2 has different handling. *)
(* :History 1.1.0, 02.10.2005: Invocation of Java runtime fully revised, batch files in ./bin removed. *)
(* :History 1.0.1, 13.02.2004: Documentation improved, mentioned that working path is prepended to filename. *)
(* :History 1.0.0, 05.10.2003: Release version. *)
(* :History 0.1.5, 07.07.2003: Disabling of certain warning message removed here, and moved to private init.m. *)
(* :History 0.1.4, 16.05.2003: Convert WorldGraphics[] to Graphics[] when exporting to file. *)
(* :History 0.1.3, 12.03.2003: Convert ContourGraphics[] to Graphics[] when exporting to file. *)
(* :History 0.1.2, 10.10.2002: Minor corrections. Still some options do not work. *)
(* :History 0.1.1, 13.03.2002: Test version to check handling of blanks. Codebase removed as argument. *)
(* :History 0.1.0, 11.03.2002: Codebase enclosed in quotations to handle blanks in Mathematica path. *)
(* :History 0.0.9, 17.01.2002: New command line option of JavaView identifying MGS file format. *)
(* :History 0.0.8, 11.10.2001: New option Animatable for Html export. *)
(* :History 0.0.7, 22.04.2001: Options for Html export and animations. *)
(* :History 0.0.6, 27.03.2001: Set codebase inside Mathematica tree. *)
(* :History 0.0.5, 04.03.2001: RunJavaView option Animate implemented. *)
(* :History 0.0.4, 15.02.2001: New module writeAnim implemented. *)
(* :History 0.0.1, **.07.2000: First version. *)

(* :Mathematica Version: 12.1 *)
		     
(* :Keywords: JavaView, Geometry, Graphics, Animation, Applets *)

(*:Requirements:
The command RunThrough[] requires a Java runtime environment and the JavaView archives.
Other utility commands for saving and formatting of Mathematica graphics are
self-contained within this package and do not need a Java installation. *)

(*:Summary:
This package provides various functions to view Mathematica graphics
with JavaView and to export Mathematica graphics for online display
in JavaView applets of web pages. *)

BeginPackage["JavaView`RunThrough`"]

JavaView`$Version = "JavaView`RunThrough` v3.4.2"

(* Installation path of JavaView archives within the Mathematica installation. *)
JavaView::InstallationPath = $InstallationDirectory<>$PathnameSeparator<>"AddOns"<>$PathnameSeparator<>"Applications"<>$PathnameSeparator<>"JavaView"<>$PathnameSeparator<>"Java"<>$PathnameSeparator
(* Working path to user directory for temporary storage of user documents. *)
JavaView::WorkingPath = $UserDocumentsDirectory<>$PathnameSeparator


RunJavaView::usage =
"RunJavaView[g, options...] displays a Mathematica graphics object in JavaView.
Graphics objects may be Graphics, Graphics3D, SurfaceGraphics, and others.
\n\n
The method uses the RunThrough[g] command of Mathematica to invoke JavaView.
Method accesses a local Java installation and uses the JavaView archives *.jar.
\n\n
The graphics object is formatted by replacing infinite precision with standard double
precision in order to avoid parsing of Mathematica specific number representations.
\n\n
Depending on the lauching style and operating system this command may block further
execution of Mathematica until JavaView exits. In this case during the lifetime of
the JavaView process the kernel is waiting for JavaView to finish.
\n\n
An important option of RunJavaView[] is\n
   Runtime -> java -Xmx512m\n
which determines the Java runtime and its arguments. The program 'java' must
either be in the path variable, or an absolute path must be specified.
Here the option -Xmx512m provides 512MB main memory for the Java virtual
machine. This value may be increased to specific needs.\n
(For compatibility, a user can specify other Java runtimes, for example, the
deprecated Microsoft JVM by setting: Runtime -> jview)\n
\n\n
See: WriteMgs[g,file], WriteAnim[g,file], WriteHtml[g,file]
See in package JavaView`JLink`: JavaView[g]"

RunJavaViewOK::usage =
"RunJavaView[g, options...] displays a Mathematica graphics object in JavaView.
Graphics objects may be Graphics, Graphics3D, SurfaceGraphics, and others.
\n\n
The method uses the RunThrough[g] command of Mathematica to invoke JavaView.
Method accesses a local Java installation and uses the JavaView archives *.jar.
\n\n
The graphics object is formatted by replacing infinite precision with standard double
precision in order to avoid parsing of Mathematica specific number representations.
\n\n
Depending on the lauching style and operating system this command may block further
execution of Mathematica until JavaView exits. In this case during the lifetime of
the JavaView process the kernel is waiting for JavaView to finish.
\n\n
An important option of RunJavaView[] is\n
   Runtime -> java -Xmx512m\n
which determines the Java runtime and its arguments. The program 'java' must
either be in the path variable, or an absolute path must be specified.
Here the option -Xmx512m provides 512MB main memory for the Java virtual
machine. This value may be increased to specific needs.\n
(For compatibility, a user can specify other Java runtimes, for example, the
deprecated Microsoft JVM by setting: Runtime -> jview)\n
\n\n
See: WriteMgs[g,file], WriteAnim[g,file], WriteHtml[g,file]
See in package JavaView`JLink`: JavaView[g]"

WriteMgs::usage =
"WriteMgs[g,file] saves a Mathematica graphics object in the given file.
The current working path is prepended to the given filename.
The exported file may later be viewed with JavaView from the command line or read from an applet.
The file name should have the extension 'file.mgs' to be identified as Mathematica
graphics file. To view the saved file, type at the command prompt either
'javaview file' or 'java javaview file' depending on the Java runtime system,
or import the file back into Mathematika using '<<filename.mgs'.
\n\n
The command uses FormatGraphics[g] to format a Graphics object into a string
and saves it in the given file. The file must be specified relative to Mathematica
or with an absolute path.
\n\n
See: RunJavaView[g], WriteAnim[g,file], WriteHtml[g,file], SetWorkingPath[String]
See in package JavaView`JLink`: JavaView[g]"

WriteAnim::usage =
"WriteAnim[g,file] saves a list of Mathematica graphics objects in the given file as an animation.
The current working path is prepended to the given filename.
The animation may later be viewed with JavaView from the command
line or read from an applet.
The file name should have the extension 'file.mgs' to be identified as Mathematica
graphics file. To view the saved file, type at the command prompt either
'javaview file' or 'java javaview file' depending on the Java runtime system,
or import the file back into Mathematika using '<<filename.mgs'.
\n\n
The command uses FormatGraphics[g] to format a Graphics object into a string
and saves it in the given file. The file must be specified relative to Mathematica
or with an absolute path.
\n\n
See: RunJavaView[g], WriteMgs[g,file], WriteHtml[g,file], SetWorkingPath[String]
See in package JavaView`JLink`: JavaView[g]"

WriteHtml::usage =
"WriteHtml[g,file,options...] saves a Mathematica graphics object as applet in an Html file.
The current working path is prepended to the given filename.
The Html file may later be viewed with any Java enabled web browser. The applet uses
JavaView to display the graphics. The command uses FormatGraphics[g] to format a
Graphics object into a string and saves it in the given HTML file. The file must
be specified relative to Mathematica or with an absolute path.
\n\n
The applet contains no codebase setting, it relies on the JavaView archives
being included in the classpath.
\n\n
See: RunJavaView[g], WriteMgs[g,file], WriteAnim[g,file], SetWorkingPath[String]
See in package JavaView`JLink`: JavaView[g]"

FormatGraphics::usage =
"FormatGraphics[g] formats a graphics object by replacing infinite precision with
standard double precision in order to avoid parsing of Mathematica specific number
representations. Further, the graphics is converted to InputForm, CForm and
finally returned as String."

GetInstallationPath::usage =
"Returns the path to the JavaView installation, typically within the Mathematica installation.
This directory is also used as JavaView codebase relative to which JavaView
resource files like images and license information are stored.
\n\n
See: SetInstallationPath[String], GetWorkingPath[]"

SetInstallationPath::usage =
"Sets the path to the JavaView installation, typically within the Mathematica installation.
This directory is also used as JavaView codebase relative to which JavaView
resource files like images and license information are stored.
\n\n
See: GetInstallationPath[], GetWorkingPath[]"

GetWorkingPath::usage =
"Returns the path to the current working directory relative to which
the JavaView commands store user documents such as geometry and html files
produced in a Mathematica session.
\n\n
Note, if the working directory is different from the InstallationPath of JavaView
and HTML files with applets reside in the working directory, then the working directory
might also need a copy of the JavaView archives.
\n\n
See: SetWorkingPath[String], GetInstallationPath[]"

SetWorkingPath::usage =
"Sets the path to the current working directory relative to which
the JavaView commands store user documents such as geometry and html files
produced in a Mathematica session.
\n\n
See: GetWorkingPath[], GetInstallationPath[]"

(* WorldPlot is necessary to read WorldGraphics objects. *)
Needs["WorldPlot`"]

Options[RunThroughOK] = {
	Debug -> False
	}
Options[RunJavaView] = {
	Animatable -> False,
	Debug -> False,
	Runtime -> "java -Xmx512m"
	}
Options[WriteHtml] = {
	Animatable -> False,
	Codebase -> "../",
	Debug -> False,
	JvxArchive -> False,
	PathToArchive -> "Java/"
	}

Begin["`Private`"]

(* RunThroughOK is a replacement of Mathematica RunThrough[] command. *)
RunThroughOK[cmd_String,expr_,opts___?OptionQ] :=
	Block[{tmpfile,resfile,mgs,res,rtCmd,tresult},
		{debug} = {Debug}/. Flatten[{opts}] /. Options[RunThroughOK];
		If[Developer`ProtectedModeBlockedQ[RunThroughOK],
			Message[RunThroughOK::sandbox,RunThroughOK];
			$Failed,
		(* else *)
			tmpfile = OpenWrite[];
			resfile = OpenWrite[];
			Write[tmpfile,expr];
			WriteString[tmpfile,"\n"];
			Close[tmpfile];
			Close[resfile];
			(* Encloses files in temporary folder with quotes, THIS IS MISSING in original RunThrough[]. *)
			mgs = "\""<>StreamFileName[tmpfile]<>"\"";
			res = "\""<>StreamFileName[resfile]<>"\"";
			rtCmd = cmd <> " < " <> mgs <> " > " <> res;
			If[debug,
				Print["RunThroughOK calls: " <> rtCmd];
			];
			Run[rtCmd];
			tresult=Get[StreamFileName[resfile]];
			DeleteFile[StreamFileName[tmpfile]];
			DeleteFile[StreamFileName[resfile]];
			tresult
		]
	]
(* Helper method in RunThroughOK. *)
StreamFileName[streamhead_Symbol[name_String,serialnumber_Integer]]:=name
(* Helper method in RunThroughOK. *)
StreamFileName[name_String]:=name

RunJavaView::path = "Path to JavaView package not found, empty string as path."
RunJavaViewOK::path = "Path to JavaView package not found, empty string as path."

(* View a Mathematica graphics object in standalone JavaView application which is called using RunThrough[].
   The JavaView application is launched by calling java with JavaView jar archives. The Mathematica graphics
   is provided via stdin. Requires the Java runtime in the path. *)
RunJavaView[g_,opts___?OptionQ] :=
	Module[{gs,animation,debug,runtime,sort,thisPkgPath,codebase,binbase,jvBin,sep,fmtGeom,jvOptions},
		{animation,debug,runtime} = {Animatable,Debug,Runtime}/. Flatten[{opts}] /. Options[RunJavaView];
		(* Some JavaView options which are automatically set. *)
		jvOptions = " file=stdin format=mgs";
		If[ animation,
			jvOptions = jvOptions <> " Animate=Show";
		];
		If[Head[g] === ContourGraphics || Head[g] === WorldGraphics,
			gs = Graphics[g];
			jvOptions = jvOptions <> " Sorting=Hide";,
			gs=g;
		];
		(* We build the external call to launch JavaView listening to stdin: 
			jvCmd = "java -Xmx512m -cp \"C:/Program Files/Wolfram \
			Research/Mathematica/10.0/AddOns/Applications/JavaView/Java/javaview.\
			jar;\" javaview codebase=\"C:/Program Files/Wolfram \
			Research/Mathematica/10.0/AddOns/Applications/JavaView/\" file=stdin \
			format=mgs"
			
			respectively it performes the following commandline call:

			java -Xmx512m -cp "C:/Program Files/Wolfram Research/Mathematica/10.0/AddOns/Applications/JavaView/Java/javaview.jar;" javaview codebase="C:/Program Files/Wolfram Research/Mathematica/10.0/AddOns/Applications/JavaView/" file=stdin format=mgs
			
		*)
		(* Get package base which is used to determine the JavaView codebase. *)
		jvCB = StringReplace[GetInstallationPath[], $PathnameSeparator -> "/"];
		
		(* Assign the JavaView archives. *)
		jvArchive1 = jvCB <> "javaview.jar";
		jvArchive2 = jvCB <> "jvx.jar";
		jvArchive3 = jvCB <> "vgpapp.jar";
		
		(* Combine the JavaView archives, enclosed in quotes to take care of blanks in filenames. *)
		jvJARS = "\"" <> jvArchive1 <> ";" <> jvArchive2 <> ";" <> jvArchive3 <> "\"";
		jvCB = "\"" <> jvCB <> "\"";
		
		(* Get the Java runtime and additional command line arguments of 'java'. *)
		javaRT = runtime;
		
		(* jvCmd combines the call to Java and all parameters. *)
		jvCmd		= javaRT <> " -cp " <> jvJARS <> " javaview codebase=" <> jvCB <> jvOptions;
		If[debug, Print["RunJavaView calls: " <> jvCmd]];
		fmtGeom = InputForm[N[gs] /. x_Real :> CForm[Chop[x]]];
		RunThrough[jvCmd, fmtGeom];
	]

(* View a Mathematica graphics object in standalone JavaView application which is called using RunThrough[].
   The JavaView application is launched by calling java with JavaView jar archives. The Mathematica graphics
   is provided via stdin. Requires the Java runtime in the path. *)
RunJavaViewOK[g_,opts___?OptionQ] :=
	Module[{gs,animation,debug,sort,thisPkgPath,codebase,binbase,jvBin,sep,fmtGeom,jvOptions},
		{animation,debug,runtime} = {Animatable,Debug,Runtime}/. Flatten[{opts}] /. Options[RunJavaView];
		(* Some JavaView options which are automatically set. *)
		jvOptions = " file=stdin format=mgs";
		If[ animation,
			jvOptions = jvOptions <> " Animate=Show";
		];
		If[Head[g] === ContourGraphics || Head[g] === WorldGraphics,
			gs = Graphics[g];
			jvOptions = jvOptions <> " Sorting=Hide";,
			gs=g;
		];
		(* We build the external call to launch JavaView listening to stdin: 
			jvCmd = "java -Xmx512m -cp \"C:/Program Files/Wolfram \
			Research/Mathematica/10.0/AddOns/Applications/JavaView/Java/javaview.\
			jar;\" javaview codebase=\"C:/Program Files/Wolfram \
			Research/Mathematica/10.0/AddOns/Applications/JavaView/\" file=stdin \
			format=mgs"
			
			respectively it performes the following commandline call:

			java -Xmx512m -cp "C:/Program Files/Wolfram Research/Mathematica/10.0/AddOns/Applications/JavaView/Java/javaview.jar;" javaview codebase="C:/Program Files/Wolfram Research/Mathematica/10.0/AddOns/Applications/JavaView/" file=stdin format=mgs
			
		*)
		(* Get package base which is used to determine the JavaView codebase. *)
		jvCB = StringReplace[GetInstallationPath[], $PathnameSeparator -> "/"];
		
		(* Assign the JavaView archives. *)
		jvArchive1 = jvCB <> "javaview.jar";
		jvArchive2 = jvCB <> "jvx.jar";
		jvArchive3 = jvCB <> "vgpapp.jar";
		
		(* Combine the JavaView archives, enclosed in quotes to take care of blanks in filenames. *)
		jvJARS = "\"" <> jvArchive1 <> ";" <> jvArchive2 <> ";" <> jvArchive3 <> "\"";
		jvCB = "\"" <> jvCB <> "\"";
		
		(* Get the Java runtime and additional command line arguments of 'java'. *)
		javaRT = runtime;
		
		(* jvCmd combines the call to Java and all parameters. *)
		jvCmd		= javaRT <> " -cp " <> jvJARS <> " javaview codebase=" <> jvCB <> jvOptions;
		If[debug,
			Print["RunJavaView calls: " <> jvCmd];
		];
		fmtGeom = InputForm[N[gs] /. x_Real :> CForm[Chop[x]]];
		RunThroughOK[jvCmd, fmtGeom, Debug->debug];
	]



(* Get the path to the current working directory. Files are saved and
   loaded relative to the current working directory. *)
GetWorkingPath[] :=
	Module[{}, Return[JavaView::WorkingPath]
	]

(* Set the path to the current working directory. Files are saved and
   loaded relative to the current working directory. *)
SetWorkingPath[path_] :=
	Module[{}, JavaView::WorkingPath = path
	]

(* Get the path to the JavaView installation, typically inside the Mathematica installation. *)
GetInstallationPath2[] :=
	Module[{}, Return[JavaView::InstallationPath2]
	]

(* Get the path to the JavaView installation, typically inside the Mathematica installation. *)
GetInstallationPath[] :=
	Module[{}, Return[JavaView::InstallationPath]
	]

(* Set the path to the JavaView installation, typically inside the Mathematica installation. *)
SetInstallationPath[path_] :=
	Module[{}, JavaView::InstallationPath = path
	]

(* Format graphics objects by reducing precision to machine accuracy,
   and inserting line breaks for better readability of ascii files.
   This method returns a string object which behaves slightly different
   as if the graphics would have been converted to InputForm instead. *)
FormatGraphics[g_] :=
	Module[{}, StringReplace[ToString[N[g] /. x_Real :> CForm[Chop[x]],
		FormatType -> InputForm, PageWidth -> Infinity], {"}," -> "},\n", "]," -> "],\n"}]
	]

(* Write a graphics object to a geometry file.
The current working path is prepended to the given filename. 
The file filename.mgs on a local disk may be displayed with JavaView
using "javaview filename.mgs" or "java javaview filename.mgs",
or it maybe imported back into Mathematika using "<<filename.mgs". *)
WriteMgs[g_, filename_String] :=
	Module[{gs, strm = OpenWrite[GetWorkingPath[]<>filename, PageWidth -> Infinity]},
		If[Head[g] === ContourGraphics || Head[g] === WorldGraphics,
			gs = Graphics[g];,
			gs = g;
		];
		WriteString[strm, FormatGraphics[gs]];
		Close[strm]
	]

(* Write a list of graphics object to into an ascii file as argument of ShowAnimation[].
The current working path is prepended to the given filename.
The file filename.mgs on a local disk may be displayed with JavaView
using "javaview filename.mgs" or "java javaview filename.mgs",
or it maybe imported back into Mathematica using "<<filename.mgs". *)
WriteAnim[g_, filename_String] := 
	Module[{strm = OpenWrite[GetWorkingPath[]<>filename, PageWidth -> Infinity]},
		WriteString[strm, "ShowAnimation["]; 
		WriteString[strm, FormatGraphics[g]];
		WriteString[strm, "]"];
		Close[strm]
	]

(* Write a graphics object into an Html file as parameter of a JavaView applet.
The current working path is prepended to the given filename. 
The applet contains no codebase setting, therefore it relies on the JavaView archives
being included in the classpath. *)
WriteHtml[g_, filename_String ,opts___?OptionQ] :=
  	Module[{strm = OpenWrite[GetWorkingPath[]<>filename, PageWidth -> Infinity],geom,archive,htmlstart,htmlend},
		{animation,codebase,debug,jvxarchive,pathtoarchive} = {Animatable,Codebase,Debug,JvxArchive,PathToArchive}/. Flatten[{opts, Options[WriteHtml]}];

		(* Replace inner "-quotes to avoid interference with outer quotes of applet parameter. *)
		geom = FormatGraphics[g];
		geom = StringReplace[geom, "\""-> "'"];

		archive = pathtoarchive<>"javaview.jar";
		If[ jvxarchive,
			archive = archive <> "," <> pathtoarchive <> "jvx.jar";
		];

		param = "";
		If[ animation,
			param = param <> "   <PARAM NAME=Animate VALUE=Show>\n";
		];

		(* Text for Html Output *)
		htmlstart = "<html>\n
		<head><title>Demo: Mathematica Graphics via Applet Parameter</title></head>\n
		<body>\n
		<h2>Demo: Mathematica Graphics via Applet Parameter</h2>\n
		<P>\n
		This Html page contains a demonstration applet which uses an applet\n
		parameter to pass a Mathematica graphics object to\n
		<EM><FONT color=#004080>JavaView</FONT></EM> for display</P>\n
		<p>Note, the applet contains a codebase setting which may need be adjusted to your settings.</p>
		<p>\n
		<APPLET code=javaview.class name=\"Parameter Demo\"\n
			codebase=\""<>codebase<>"\" height=300 width=400\n
			archive=\""<>archive<>"\">\n"<>param<>"
			<PARAM NAME=control VALUE=Hide>\n
			<PARAM NAME=panel VALUE=Material>\n
			<PARAM NAME=language VALUE=en>\n
			<PARAM NAME=menu-new-project VALUE=disable>\n
			<PARAM NAME=mathematica VALUE=\"\n";
		htmlend = "\">\n</APPLET>\n</p>\n</body>\n</html>";

		WriteString[strm, htmlstart <> geom <> htmlend];
		Close[strm]
    ]

Print[JavaView`$Version]

End[]

EndPackage[]   (* JavaView`RunThrough` *)
