(* ::Package:: *)

(* :Title: JavaView with JLink *)

(* :Context: JavaView`JLink` *)

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

(* :Package Version: 3.4.2 *)
(* :History 3.4.1, 02.04.2020: InstallJavaView updated to show tool and status bar,
							   also solved bug on panel exceptions. *)
(* :History 3.0.4, 28.03.2020: Compatibility to Mathematica 12.1. *)
(* :History 3.0.3, 10.03.2020: Compatibility to Mathematica 12.0. *)
(* :History 2.0.0, 26.03.2015: Compatibility to Mathematica 10.0, support of 5.x and 4.x lowered. *)
(* :History 1.1.0, 25.07.2012: Compatibility to Mathematica 8.0. *)
(* :History 1.0.1, 29.11.2003: Bug removed that animations where returned as array of removed objects. *)
(* :History 1.0.0, 15.10.2003: Release version. *)
(* :History 0.3.0, 06.10.2003: Identification of vertices implemented. *)
(* :History 0.2.0, 17.07.2003: Additional commands and options added. *)
(* :History 0.1.5, 07.07.2003: Disabling of certain warning message removed here, and moved to private init.m. *)
(* :History 0.1.4, 04.07.2003: Setting of codebase done before instantiation of viewer. *)
(* :History 0.1.3, 16.05.2003: Convert WorldGraphics[] to Graphics[]. *)
(* :History 0.1.2, 09.03.2003: Assure recreation of display and viewer in InstallJavaView[]. *)
(* :History 0.1.1, 12.01.2003: Assure selection of a geometry in the display. *)
(* :History 0.1.0, 16.11.2002: Update of display instead of update of geometry. *)
(* :History 0.0.9, 15.11.2002: Ensure update of display. *)
(* :History 0.0.8, 23.10.2002: Set embeddedness flag in JavaView, more graphics types allowed. *)
(* :History 0.0.7, 27.03.2001: Set codebase inside Mathematica tree. *)
(* :History 0.0.6, 21.03.2001: Code beautifications. *)
(* :History 0.0.5, 04.03.2001: RunJavaView option Animate implemented. *)
(* :History 0.0.4, 10.01.2001: Comments of Todd incorporated. *)
(* :History 0.0.1, **.07.2000: First version. *)

(* :Mathematica Version: 12.1 *)

(* :Copyright:
	JavaView`Link source code (c) 2000-2020, Konrad Polthier, All rights reserved.
*)

(* :Summary:
	This package provides commands to setup and attach JavaView displays to
	Mathematica for display and interaction with Mathematica graphics.
	Events issued from the JavaView display may be received in Mathematica.
	Further, export of Mathematica graphics for online display in web pages
	using JavaView applets.
*)

(* :Keywords: JavaView, Geometry, Graphics, Animation, Java, J/Link *)

(* :Requirements:
	The JavaView'JLink package requires the JavaView archives to be
	installed within Mathematica, and the native J/Link package.
*)

BeginPackage["JavaView`JLink`",{"JLink`","JavaView`RunThrough`"}]

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

InstallJavaView::usage =
"InstallJavaView[] calls JLink`InstallJava[] to launch the Java runtime and prepares it
to be used from Mathematica. InstallJavaView assumes that all options of InstallJava
to control the Java runtime program, the classpath etc have been set using setOptions[InstallJava,...].
Only one Java runtime is ever launched; InstallJavaView[] assumes that the package JavaView`JLink`
was loaded.
\n\n
InstallJavaView[] creates a JavaView viewer manager and a new display inside a new frame.
The frame is made visible in the first invocation of JavaView[g].
\n\n
Return value of this command is the JavaView viewer manager which is instance of class
jv.viewer.PvViewer. The viewer can be queried for the current display, the current geometry
or current project.
\n\n
Subsequent calls to InstallJavaView[] after the first have no effect, unless either the
the display was closed or the viewer was removed. If the display was closed then
InstallJavaView[] ensures that a new display in a frame is available. If the viewer was
removed either manually using Remove[viewer] or using UninstallJavaView[] then
InstallJavaView[] starts from scratch.
\n\n
Some additional JavaView classes are loaded to simplify access to static methods and variables.
\n\n
See in package JavaView`RunThrough`: JavaView[g], WriteMgs[g,file], WriteHtml[g,file]"

UninstallJavaView::usage =
"UninstallJavaView[] removes global variables which where created by JavaView."

LoadJavaViewClasses::usage =
"Load some essential JavaView classes used in the JavaView'JLink applications."

(* Enable for debug purpose only: *)
AssureDisplay::usage =
"AssureDisplay[] test existence of JavaView display, or creates a new display."

JavaView::usage =
"JavaView[g] displays a Mathematica graphics object in JavaView.
Graphics objects may be Graphics, Graphics3D, SurfaceGraphics, and others.
\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
In contrast to the command 'RunJavaView[g]' this JLink connection to JavaView does not block
further execution of Mathematica.
\n\n
Return value is the JavaView display which is instance of class jv.viewer.PvDisplay.
\n\n
See: InstallJavaView[]
See in package JavaView`RunThrough`: JavaView[g], WriteMgs[g,file], WriteHtml[g,file]"

DoubleSlider::usage =
"DoubleSlider[] creates a new JavaView slider which calls a previously defined
Mathematica module."

RemoveGeometries::usage =
"RemoveGeometries[] removes all geometries from the JavaView display.
\n\n
See: JavaView[]"

ToJavaView::usage =
"ToJavaView[g] converts a Mathematica graphics to a list of JavaView geometries.
JavaView has individual geometry classes for point set, face set, polygons
and a few other shapes. The command ToJavaView[] is listable, that means,
application to a list of Mathematica graphics returns a double list of
geometries, one list per Mathematica graphics.
\n\n
See: JavaView[]"

TextureCoordinates::usage =
"TextureCoordinates[numU,numV] creates the vertex based texture coordinates
associated to a ParametricPlot3D graphics with given discretization.
Method returns an array of vertex texture coordinates which
are intended to be assigned to a JavaView geometry using geom@setVertexTextures[..].
\n\n
See: TextureImage[]"

TextureImage::usage =
"TextureImage[String] loads an image from file and
creates a new texture object to be assigned to a JavaView geometry.
Method returns a texture objects which is intended to be assigned
to a JavaView geometry using geom@setTexture[tex].
\n\n
See: TextureCoordinates[]"

(* Load Java runtime into Mathematica. *)
Needs["JLink`"]

(* Export functionality is provided with JavaView`RunThrough`. *)
Needs["JavaView`RunThrough`"]

Options[ JavaView ] = {
	Animatable -> False,
	(*
	DisplaySize -> {640,512},
	DisplayLocation -> {0,50},
	*)
	Identify -> True,
	KeepView -> False,
	Name -> "", (* JavaView's PgMathLoader will assign a default name indicating the geometry class. *)
	Replace -> True,
	Show -> True,
	Transparency -> 0.,
	Verbose -> False
}

Options[ ToJavaView ] = {
	Identify -> True,
	Verbose -> False
}

(* Currently, options allow to print debugging information. *)
Options[ InstallJavaView ] = {
	MonitorDpi -> 1,
	Verbose -> False
}

(* Currently, options allow to print debugging information. *)
Options[ AssureDisplay ] = {
	Verbose -> False
}

Begin["`Private`"]


InstallJavaView[opts___?OptionQ]:=
	JavaBlock[
		Module[{codebase,props,userDir,verbose,monitorDpi,monitorDpiStr,otherHeight},
			{verbose, monitorDpi} =	{Verbose, MonitorDpi} /. Flatten[{opts}] /. Options[InstallJavaView];

			If[verbose, Print["Calling InstallJavaView_",$ModuleNumber]];

			(* Simply quit if this method was called before. *)
			If[ValueQ[viewer],
				If[verbose, Print["Using existing viewer"] ];
				AssureDisplay[];
				Return[viewer]
			];
			
			(* Check for codebase. *)
			If[GetInstallationPath[] === "",
				Message[JavaView::path];
				Return[$Failed]
			];
			(* Print installation path and user directory. *)
			If[verbose,
				Print["Installation path = " <> GetInstallationPath[]];
				Print["Working path = " <> GetWorkingPath[]];
			];

			InstallJava[];
			
			If[verbose, ShowJavaConsole[];];

			LoadJavaViewClasses[]

			(* Indicate current project of JavaView. *)
			PsConfig.setProgramExtension("JLink");

			(* Process command line arguments of JavaView. *)
			codebase = StringReplace[GetInstallationPath[], $PathnameSeparator -> "/"];
			userDir = StringReplace[GetWorkingPath[], $PathnameSeparator -> "/"];
			monitorDpiStr = Integer`toString[monitorDpi];
			args = {"codebase="<>codebase, "user.dir="<>userDir, "monitor.dpi="<>monitorDpiStr};
			If[verbose, Print["\nCommand line arguments:\n",Column[args],"\n... end of arguments\n"]];

			(* Create main frame to contain the 3D display plus menu and tool bar. *)
			frame = JavaNew["jv.object.PsMainFrame", "JavaView'JLink Main", args];

			If[verbose, Print["Creating viewer and display ..."]];
			(* Create global viewer manager to handle displays, frames and dialogs.
			Variable viewer must be global in this context. *)	
			viewer = JavaNew["jv.viewer.PvViewer", Null, frame];
			(* Instruct JavaView not to exit when the frame is closed. *)
			viewer@setEmbedded[True];
			(* KeepJavaObject[viewer]; Not needed, since viewer is returned.*)

			(* Create a JavaView 3d-display, do not show it yet.
			Variable disp must be global in this context. *)
			(* disp = viewer@newDisplay["Display: From Mathematica_"<>Integer`toString[$ModuleNumber],True]; *)
			disp = viewer@getDisplay[];
			KeepJavaObject[disp];
			If[verbose, Print["Display was created: "<>disp@getName[]]];

			(* Variable frame must be global in this context. *)	
			frame@add[disp@getCanvas[], MakeJavaObject[BorderLayout`CENTER]];
			frame@pack[];

			frame@setLocation[0, 50];
			(* Add height of tool bar and status bar. *)
			otherHeight = PsMainFrame`getTotalHeightOther[frame, disp];
			frame@setInnerSize[640, 512+otherHeight/PsConfig`getMonitorScale[]];
			KeepJavaObject[frame];
			If[verbose, Print["Frame was created: "<>frame@getName[]]];

			Return[viewer]
		]
	]

JavaView::inst =
"JavaView does not seem to be properly installed. InstallJavaView[] must be
called prior to JavaView[g]."

JavaView::load =
"JavaView: loading failed, graphics=`1`"

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

JavaView::usage =
"JavaView[] displays a Mathematica graphics, a list of graphics, or a JavaView geometry in a JavaView display.
\n\n
See: JavaViewGraphics[],JavaViewList[],JavaViewGeom[]"

AssureDisplay[opts___?OptionQ]:=
	JavaBlock[  
		Module[{verbose,otherHeight},
			{verbose} = {Verbose} /. Flatten[{opts, Options[AssureDisplay]}];
			If[verbose, Print["Calling AssureDisplay_",$ModuleNumber]];

			If[!ValueQ[viewer],
				Message[JavaView::inst];
				Return[False]
			];
			(*
			  If frame was deleted through window manager, then only
			  JavaView receives that event but not Mathematica. Therefore
			  we need to check availability of the Mathematica display
			  in JavaView's viewer manager whenever we access the disp.
			  The check JavaObjectQ[] returns false if the display was
			  destroyed by JavaView, and therefore ensure that a new display
			  is allocated. The main display will be destroyed when a user
			  pressed the (upper right) destroy checkbox of a window.
			*)
			If[verbose,
				If[!JavaObjectQ[disp], Print["Current display is no longer valid."]];
				If[!viewer@hasDisplay[disp], Print["Display not registered in the viewer."]];
			];
			If[!JavaObject[disp],
				If[verbose, Print["Missing disp, creating a new display ..."]];
				disp = viewer@newDisplay["Display: From Mathematica", True];
				frame = disp@getFrame[];
				frame@setLocation[0,50];
				(* Add height of tool bar and status bar. *)
				otherHeight = PsMainFrame.getTotalHeightOther[frame, disp];
				frame@setInnerSize[640, 512+otherHeight/PsConfig'getMonitorScale[]];
			];
			If[!viewer@hasDisplay[disp],
				If[verbose, Print["Adding missing disp to viewer: disp = "<>disp@getName[]]];
				viewer@addDisplay["Display: From Mathematica", disp];
			];
			Return[True]
		]
	]


(* View a Mathematica graphics object in a JavaView display using JLink. *)
JavaView[g_Graphics,opts___?OptionQ]:= JavaViewGraphics[g,opts]
JavaView[g_Graphics3D,opts___?OptionQ]:= JavaViewGraphics[g,opts]
JavaView[g_SurfaceGraphics,opts___?OptionQ]:= JavaViewGraphics[g,opts]
JavaView[g_DensityGraphics,opts___?OptionQ]:= JavaViewGraphics[g,opts]
JavaView[g_ContourGraphics,opts___?OptionQ]:= JavaViewGraphics[g,opts]
JavaView[g_GraphicsArray,opts___?OptionQ]:= JavaViewGraphics[g,opts]
JavaView[g_WorldGraphics,opts___?OptionQ]:= JavaViewGraphics[g,opts]

(* View a JavaView geometry. *)
JavaView[geom_?JavaObjectQ,opts___?OptionQ]:= JavaViewGeom[geom,opts]

(* View a list of Mathematica graphics objects. *)
JavaView[g_List,opts___?OptionQ]:= JavaViewList[g,opts]

(* The unclassified declaration was added since otherwise ShowAnimation[] was not understood. *)
(* JavaView[g_,opts___?OptionQ]:= JavaViewGraphics[g,opts] *)

(* Show the main JavaView window, for example, after it was closed.
Here we require that the variable "frame" is in the current context
and was not released. *)
JavaView[opts___?OptionQ]:=
	JavaBlock[
		Module[{name,verbose},
			{name,verbose} = {Name,Verbose}/. Flatten[{opts, Options[JavaView]}];
			If[verbose, Print["Calling JavaView[]_",$ModuleNumber]];
			If[!AssureDisplay[],
				Message[JavaView::inst];
				Return[$Failed]
			];
			If[name =!= Null,frame@setTitle[name];];
			JavaShow[frame];
		]
	]
	 
JavaViewGraphics[g_,opts___?OptionQ]:=
	JavaBlock[
		Module[{animatable,geomArr,geomName,gs,i,identify,keepview,loader,name,replace,selGeom,show,sort,transparency,verbose},
			{animatable,identify,keepview,name,replace,show,transparency,verbose} = {Animatable,Identify,KeepView,Name,Replace,Show,Transparency,Verbose}/. Flatten[{opts, Options[JavaView]}];
			If[verbose, Print["Calling JavaViewGraphics[g]_",$ModuleNumber]];
			If[!AssureDisplay[],
				Message[JavaView::inst];
				Return[Null]
			];

			If[g === Null,
				Message[JavaView::load,g];
				Return[Null]
			];

			If[Head[g]===ContourGraphics || Head[g]===WorldGraphics,
				gs = FormatGraphics[Graphics[g]];,
			(* else *)
				gs = FormatGraphics[g];
			];
			loader = JavaNew["jv.loader.PgLoader"];
			(* Allow or prevent identification of equal vertices. *)
			loader@setEnabledOptimization[identify];
			geomArr = loader@loadGeometry[gs,"mgs"];
			If[geomArr===Null || geomArr[[1]]===Null,
				Message[JavaView::load,gs];
				Return[Null]
			];
			If[replace,RemoveGeometries[];];
		
			selGeom = disp@getSelectedGeometry[];
			For[i=1,i<=Length[geomArr],i++,
				If[name =!= "",
					If[Length[geomArr] === 1,
						geomName = name;,
						geomName = name <> ToString[i];
					];
					If[verbose, Print["Geometry[",i,"] name: ",geomName];];
					geomArr[[i]]@setName[geomName];
				];
				If [transparency =!= 0.,
					geomArr[[i]]@setTransparency[transparency];
					geomArr[[i]]@showTransparency[True];
				];
				disp@addGeometry[geomArr[[i]]];
			];
			(* Explicitly selecting a geometry will inform PvViewer too
				such that the Method menu is enabled. *)
			If[selGeom === Null,
				disp@selectGeometry[geomArr[[1]]];
			];

			(* Assign display options after registering the geometry
				since otherwise display might not update correctly.*)
			If[!keepview,
				dispOption = loader@getDisplayOption[];
				If[dispOption =!= Null,
					sort = (Head[g]=!=ContourGraphics && Head[g]=!=WorldGraphics);
					dispOption@setOption[PvDisplayOption`SHOWUSORTING,sort];
					dispOption@configure[disp];
					ReleaseJavaObject[dispOption];
				];
			];
			disp@update[disp];

			If[show, JavaShow[frame]];
	
			Return[geomArr[[1]]]
		]
	]

(* View a list of Mathematica graphics in a JavaView display using JLink. *)
JavaViewList[g_List,opts___?OptionQ] := 
	JavaBlock[
		Module[{animatable,geomArr,geomJvxArr,geomName,geomRun,gs,i,identify,keepview,loader,name,replace,selGeom,show,transparency,verbose},
			{animatable,identify,keepview,name,replace,show,transparency,verbose} = {Animatable,Identify,KeepView,Name,Replace,Show,Transparency,Verbose}/. Flatten[{opts, Options[JavaView]}];
			If[verbose, Print["Calling JavaViewList[g_List]_",$ModuleNumber]];
			If[!AssureDisplay[],
				Message[JavaView::inst];
				Return[Null]
			];
			If[verbose,
				Print["Called: JavaView with List ..."];
			];

			If[g===Null || g[[1]]===Null,
				Message[JavaView::load,g];
				Return[Null]
			];
		
			(* First check if list of geometries is a list of JavaView geometries.
				Only parse Mathematica graphics if not JavaView geometries. *)
			(* TODO: handle lists with mixed Mathematica and JavaView geometries.*)
			If[JavaObjectQ[g[[1]]],
				If[animation,
					geomJvxArr = {};
					Do[geomRun = g[[i]]@getJvx[];geomJvxArr = Join[geomJvxArr, {{geomRun}}],{i, 1, Length[g]}];
					loader = JavaNew["jv.loader.PgLoader"];
					geomArr = loader@readAnimation[geomJvxArr, animation];,
				(* Else *)
					geomArr = g;
				];,
			(* Else *)
				loader = JavaNew["jv.loader.PgLoader"];
				loader@setAnimated[animation];
				
				(* Allow or prevent identification of equal vertices. *)
				loader@setEnabledOptimization[identify];
			
				gs=FormatGraphics[g];
				geomArr = loader@loadGeometry[gs,"mgs"];
				If[geomArr===Null || geomArr[[1]]===Null,
					Message[JavaView::load,gs];
					Return[Null]
				];
			];
			If[replace,
				RemoveGeometries[];
			];

			selGeom = disp@getSelectedGeometry[];
			If[verbose,
				Print["Assigning name:"];
			];
			For[i=1,i<=Length[geomArr],i++,
				If[name =!= "",
					If[Length[geomArr] === 1,
						geomName = name;,
					(* else *)
						geomName = name <> ToString[i];
					];
					If[verbose,
						Print["Geometry name: "<>geomName];
					];
					geomArr[[i]]@setName[geomName];
				];
				If [transparency =!= 0.,
					geomArr[[i]]@setTransparency[transparency];
					geomArr[[i]]@showTransparency[True];
				];
				disp@addGeometry[geomArr[[i]]];
			];
			(* Explicitly selecting a geometry will inform PvViewer too
				such that the Method menu is enabled. *)
			If[selGeom === Null,
				disp@selectGeometry[geomArr[[1]]];];

			(* Assign display options after registering the geometry
				since otherwise display might not update correctly.*)

			If[!keepview,
				dispOption = loader@getDisplayOption[];
				If[dispOption =!= Null,
					dispOption@configure[disp];
					ReleaseJavaObject[dispOption];
				];
			];

			disp@update[disp];
			ReleaseJavaObject[loader];

			If[show,JavaShow[frame];];
			(*
			Must use "Return[geomArr]" instead of simply "geomArr"
			since otherwise the entries of the array appear as Removed[JavaObject]
			in the Mathematica notebook.
			*)
			Return[geomArr]
		]
	]

(* View a JavaView geometry produced in Mathematica in a JavaView display using JLink. *)
JavaViewGeom[geom_,opts___?OptionQ]:=
	JavaBlock[
		Module[{replace,show,verbose,selGeom},
			{replace,show,verbose} = {Replace,Show,Verbose}/. Flatten[{opts, Options[JavaView]}];
			If[verbose, Print["Calling JavaViewGeom[geom]_",$ModuleNumber]];
			If[!AssureDisplay[],
				Message[JavaView::inst];
				Return[Null]
			];

			If[replace,RemoveGeometries[];];

			selGeom = disp@getSelectedGeometry[];
			disp@addGeometry[geom];
			(* Explicitly selecting a geometry will inform PvViewer too
				such that the Method menu is enabled. *)
			If[selGeom === Null,
				disp@selectGeometry[geom];
			];

			If[show,
				JavaShow[frame];
			];
			geom@update[geom];

			Return[geom]
		]
	]
	
(* Remove all geometries from JavaView display. *)
RemoveGeometries[]:=
	JavaBlock[
		Module[{geometries,i,parent},
			geometries=disp@getGeometries[];
			For[i=1,i<=Length[geometries],i++,
				parent=geometries[[i]]@getFather[];
				If[parent=!=Null,
					If[parent@hasAnimation[],
						parent@getAnimation[]@getAnimationPanel[]@setVisible[False];
					];
				];
			];
			disp@removeGeometries[];
		]
	]
	 
(* Create a list of vertex-based texture coordinates of a ParametricPlot3D surface. *)
TextureCoordinates[numU_Integer,numV_Integer]:=
	JavaBlock[
		Module[{u,v,geomTex,gTex},
			gTex = ParametricPlot3D[{u, v, 0}, {u, 0, 1}, {v, 0, 1}, 
							PlotPoints -> {numU, numV}, Axes->False];
			geomTex = First[ToJavaView[gTex]];
			geomTex@setDimOfVertices[2];
			Return[geomTex@getVertices[]]
		]
	]

(* Load an image from file and create a texture object. *)
TextureImage[fileName_String]:=
	JavaBlock[
		Module[{tex,img},
			tex = JavaNew["jv.geom.PgTexture"];
			tex@setImageName[fileName];
			img = tex@loadImage[];
			ReleaseJavaObject[img];
			KeepJavaObject[tex];
			Return[tex]
		]
	]

(* Convert a Mathematica graphics to a list of JavaView geometries. *)
ToJavaView[g_,opts___?OptionQ]:=
	JavaBlock[
		Module[{geomArr,geomName,gs,i,identify,loader,verbose},
			{identify,verbose} = {Identify,Verbose}/. Flatten[{opts, Options[ToJavaView]}];
			If[g === Null,
				Message[JavaView::load,g];
				Return[Null]
			];

			If[Head[g]===ContourGraphics || Head[g]===WorldGraphics,
				gs = FormatGraphics[Graphics[g]];,
			(* else *)
				gs = FormatGraphics[g];
			];
			loader = JavaNew["jv.loader.PgLoader"];
			(* Allow or prevent identification of equal vertices. *)
			loader@setEnabledOptimization[identify];
			geomArr = loader@loadGeometry[gs,"mgs"];
			If[geomArr===Null || geomArr[[1]]===Null,
				Message[JavaView::load,gs];
				Return[Null]
			];
			For[i=1,i<=Length[geomArr],i++,
				KeepJavaObject[geomArr[[i]]];
				If[debug === True,
					geomName = geomArr[[i]]@getName[] <> ToString[i];
					Print["Geometry name: "<>geomName];
				];
			];
			Return[geomArr]
		]
	]

(* The command ToJavaView[] is invoked on all elements of a list. *)
SetAttributes[ToJavaView,Listable];

(* Remove global variables which where created/assigned by JavaView. *)
UninstallJavaView[]:=
	Module[{},
		If[frame=!=Null,
			frame@setVisible[False];
			frame@dispose[];
			ReleaseJavaObject[frame];
		];
		RemoveGeometries[];
		If[viewer=!=Null && disp=!=Null,
			If[viewer@hasDisplay[disp]==True,
				viewer@removeDisplay[disp];
			];
		];
		If[viewer=!=Null,
			(* Print["Releasing viewer ..."]; *)
			ReleaseJavaObject[viewer];
			Remove[viewer];
		];
		If[disp=!=Null,
			(* Print["Releasing disp ..."]; *)
			ReleaseJavaObject[disp];
			Remove[disp];
		];
		If[frame=!=Null,
			(* Print["Releasing frame ..."]; *)
			ReleaseJavaObject[frame];
			Remove[frame];
		];
	 ]
	 
Options[ DoubleSlider ] = {
	Show -> True
}

(* Create a new double slider. *)
DoubleSlider[method_String,opts___?OptionQ] := DoubleSlider["Slider", method, 50, 50]
DoubleSlider[name_String,method_String,opts___?OptionQ] := DoubleSlider[name, method, 50, 50]
DoubleSlider[name_String,method_String,xpos_Integer,ypos_Integer,opts___?OptionQ]:=
	JavaBlock[
		Module[{frame,listener,show,slider,sliderIP},
			{show} = {Show}/. Flatten[{opts, Options[DoubleSlider]}];
		
			(* Create a new JavaView slider. *)
			slider = JavaNew["jv.number.PuDouble", name];
		
			(* Show the slider panel in a new frame. *)
			If[show,
				sliderIP = slider@getInfoPanel[];			
				frame = JavaNew["jv.object.PsMainFrame", "Slider Frame"];
				frame@add["Center", sliderIP];
				frame@setBounds[xpos, ypos, 400, 70];
				JavaShow[frame];
			];
		
			(* Register a listener to receive update events whenever
				the slider changes its state. *)
			listener = JavaNew["jvx.math.MathUpdateListener"];
			listener@setHandler["update", method];
			slider@addUpdateListener[listener];
		
			(* Share the kernel to allow further interaction with the slider and display. *)
			ShareKernel[];
			Return[slider]
		]
	]
	
Options[ LoadJavaViewClasses ] = {
	Verbose -> True
}
(* Load some essential JavaView classes used in the JavaView'JLink applications. *)
LoadJavaViewClasses[opts___?OptionQ]:=
	Module[{verbose},
			{verbose} = {Verbose} /. Flatten[{opts, Options[LoadJavaViewClasses]}];

		(* Load some basic Java classes. *)
		LoadJavaClass["java.awt.Color"];
		LoadJavaClass["java.lang.Integer"];
	
		(* Load some basic JavaView interfaces, sometimes useful. *)
		LoadJavaClass["javaview"];
		LoadJavaClass["jv.geom.PgPointSet"];
		LoadJavaClass["jv.geom.PgElementSet"];
		LoadJavaClass["jv.geom.PgPolygon"];
		LoadJavaClass["jv.geom.PgPolygonSet"];
		LoadJavaClass["jv.geom.PgVectorField"];		
		LoadJavaClass["jv.loader.PgLoader"];
		LoadJavaClass["jv.loader.PvDisplayOption"];
		LoadJavaClass["jv.object.PsConfig"];
		LoadJavaClass["jv.object.PsDebug"];
		LoadJavaClass["jv.object.PsMainFrame"];
		LoadJavaClass["jv.object.PsObject"];
		LoadJavaClass["jv.object.PsViewerIf"];
		LoadJavaClass["jv.project.PgGeometryIf"];
		LoadJavaClass["jv.project.PvCameraIf"];
		LoadJavaClass["jv.project.PvDisplayIf"];
		LoadJavaClass["jv.project.PvGeometryIf"];
		LoadJavaClass["jv.project.PvLightIf"];
		LoadJavaClass["jv.project.PvViewerIf"];
		LoadJavaClass["jv.vecmath.PdVector"];
		LoadJavaClass["jv.vecmath.PiVector"];
		LoadJavaClass["jv.viewer.PvDisplay"];
		LoadJavaClass["jv.viewer.PvViewer"];

		LoadJavaClass["jv.geom.PuCleanMesh"];
		LoadJavaClass["jvx.geom.PwCleanMesh"];

		LoadJavaClass["java.awt.BorderLayout"];

		(* Print installation path and user directory. *)
		If[verbose, Print["Loading JavaView classes completed."]];
		
		Return[True]
	]

Print[JavaView`$Version]

End[]

EndPackage[]
