(* :Title: JavaView via RunThrough *)

(* :Context: JavaView`RunThrough` *)

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

(* :Package Version: 1.1.5 *)
(* :History 1.1.5, 17.09.06: Additional quotes around path names since Mathematica 5.2 has different handling. *)
(* :History 1.1.0, 02.10.05: Invocation of Java runtime fully revised, batch files in ./bin removed. *)
(* :History 1.0.1, 13.02.04: Documentation improved, mentioned that working path is prepended to filename. *)
(* :History 1.0.0, 05.10.03: Release version. *)
(* :History 0.1.5, 07.07.03: Disabling of certain warning message removed here, and moved to private init.m. *)
(* :History 0.1.4, 16.05.03: Convert WorldGraphics[] to Graphics[] when exporting to file. *)
(* :History 0.1.3, 12.03.03: Convert ContourGraphics[] to Graphics[] when exporting to file. *)
(* :History 0.1.2, 10.10.02: Minor corrections. Still some options do not work. *)
(* :History 0.1.1, 13.03.02: Test version to check handling of blanks. Codebase removed as argument. *)
(* :History 0.1.0, 11.03.02: Codebase enclosed in quotations to handle blanks in Mathematica path. *)
(* :History 0.0.9, 17.01.02: New command line option of JavaView identifying MGS file format. *)
(* :History 0.0.8, 11.10.01: New option Animatable for Html export. *)
(* :History 0.0.7, 22.04.01: Options for Html export and animations. *)
(* :History 0.0.6, 27.03.01: Set codebase inside Mathematica tree. *)
(* :History 0.0.5, 04.03.01: RunJavaView option Animate implemented. *)
(* :History 0.0.4, 15.02.01: New module writeAnim implemented. *)
(* :History 0.0.1, **.07.00: First version. *)

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

(*: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`"]

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 -Xmx256m\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 -Xmx256m provides 256MB 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."

findCurrentPkg::usage =
"findCurrentPkg[] return the path to the current package."

GetInstallationPath::usage =
"Get the path to the JavaView installation 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: GetWorkingPath[], SetWorkingPath[String]"

GetWorkingPath::usage =
"GetWorkingPath[] returns the path to the current working directory relative to which
the JavaView commands store 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: GetInstallationPath[], SetWorkingPath[String]"

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

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

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

Begin["`Private`"]

(* findCurrentPkg will return a full pathname to the current package file if its location fits the following rule.
   For a context named Foo`Bar`, the file can be in either *\Foo\Bar.m or *\Foo\Bar\Bar.m, where * stands for
   any directory on $Path. The second form is intended to catch cases where the developer relies on the idiom
   of putting a Kernel\init.m file in the directory Foo\Bar, which loads the package Foo\Bar\Bar.m.
   It returns "" if the file cannot be found. The returned dir name, if not "", ends with $PathnameSeparator.
   This module is taken from JLink.m following the kind advice of Todd Gayley.
*)
findCurrentPkg[] := 
	Module[{ctxt, pkgPath, pkgPath2, shortCtxt, correctedPaths, fullPaths, res},
		ctxt = StringDrop[Context[findCurrentPkg], -1];  (* Take off ` *)
		(* Print[ctxt]; *)
		pkgPath = StringReplace[ctxt, "`" -> $PathnameSeparator] <> ".m";
		(* Print[pkgPath]; *)
		shortCtxt = StringDrop[ctxt, Last[{0} ~Join~ Flatten[StringPosition[ctxt, "`"]]]];
		(* Print[shortCtxt]; *)
		pkgPath2 = StringReplace[ctxt <> $PathnameSeparator <> shortCtxt, "`" -> $PathnameSeparator] <> ".m";
		(* Print[pkgPath2]; *)
		correctedPaths = If[StringTake[#, -1] =!= $PathnameSeparator, # <> $PathnameSeparator, #]& /@ $Path;
		(* Print[correctedPaths]; *)
		fullPaths = Join[(# <> pkgPath)& /@ correctedPaths, (# <> pkgPath2)& /@ correctedPaths];
		(* Print[fullPaths]; *)
		res = DeleteCases[File /. (FileInformation /@ fullPaths), File];
		(* Print["res = " <> res]; *)
		If[Length[res] == 0,
			"",
		(* else *)
			(* Drop filename, leaving just dir. +2 is for .m *)
			StringDrop[First[res], -(StringLength[shortCtxt] + 2)] //
				(If[StringTake[#, -1] =!= $PathnameSeparator, # <> $PathnameSeparator, #]&)
		]
	]

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

(* Use RunThrough to view a Mathematica graphics object in JavaView.
Requires existence of an executable shell script "javaview" or binary "javaview.exe" in the path. *)
RunJavaView[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 === True,
			jvOptions = jvOptions <> " Animate=Show";
		];
		If[Head[g] === ContourGraphics || Head[g] === WorldGraphics,
			gs = Graphics[g];
			jvOptions = jvOptions <> " Sorting=Hide";,
			gs=g;
		];
		(* Get package base which is used to determine the JavaView codebase. *)
		jvIP = GetInstallationPath[];
		jvCB = StringReplace[jvIP, $PathnameSeparator -> "/"];
		(* Since Mathematica 5.0 we need to enclose in extra quotes since blanks
		   in filenames are handled differently under Windows. *)
		jvCB = "\"" <> jvCB <> "\"";
		
		(* Assign the JavaView archive base. *)
		jvAB = jvCB<>"Java/";
		
		(* Combine the JavaView archives. *)
		jvJARS = jvAB<>"javaview.jar"<>";"<>jvAB<>"jvx.jar"<>";"<>jvAB<>"vgpapp.jar";
		
		(* 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;
		If[debug === True,
			Print["calling: " <> jvCmd <> jvOptions];
		];
  		fmtGeom = InputForm[N[gs] /. x_Real :> CForm[Chop[x]]];
		RunThrough[jvCmd <> jvOptions, fmtGeom];
	]


JavaView::WorkingPath = findCurrentPkg[]

(* 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 within the Mathematica installation. *)
GetInstallationPath[] :=
	Module[{}, Return[findCurrentPkg[]]
	]

(* 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 == True,
			archive = archive <> "," <> pathtoarchive <> "jvx.jar";
		];

		param = "";
		If[ animation == True,
			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]
    ]
End[]

EndPackage[]   (* JavaView`RunThrough` *)
