(* ::Package:: *)

(* :Title: JavaView with JLink *)

(* :Context: JavaView`JLink` *)

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

(* :Package Version: 1.1.0 *)
(* :History 1.1.0, 25.07.12: Compatibility to Mathematica 8.0. *)
(* :History 1.0.1, 29.11.03: Bug removed that animations where returned as array of removed objects. *)
(* :History 1.0.0, 15.10.03: Release version. *)
(* :History 0.3.0, 06.10.03: Identification of vertices implemented. *)
(* :History 0.2.0, 17.07.03: Additional commands and options added. *)
(* :History 0.1.5, 07.07.03: Disabling of certain warning message removed here, and moved to private init.m. *)
(* :History 0.1.4, 04.07.03: Setting of codebase done before instantiation of viewer. *)
(* :History 0.1.3, 16.05.03: Convert WorldGraphics[] to Graphics[]. *)
(* :History 0.1.2, 09.03.03: Assure recreation of display and viewer in InstallJavaView[]. *)
(* :History 0.1.1, 12.01.03: Assure selection of a geometry in the display. *)
(* :History 0.1.0, 16.11.02: Update of display instead of update of geometry. *)
(* :History 0.0.9, 15.11.02: Ensure update of display. *)
(* :History 0.0.8, 23.10.02: Set embeddedness flag in JavaView, more graphics types allowed. *)
(* :History 0.0.7, 27.03.01: Set codebase inside Mathematica tree. *)
(* :History 0.0.6, 21.03.01: Code beautifications. *)
(* :History 0.0.5, 04.03.01: RunJavaView option Animate implemented. *)
(* :History 0.0.4, 10.01.01: Comments of Todd incorporated. *)
(* :History 0.0.1, **.07.00: First version. *)

(* :Mathematica Version: 4.0 to 8.0 *)
		     
(* :Keywords: Graphics, JavaView, Geometry, Applets, Animation, J/Link *)

(*:Requirements:
Commands launching JavaView require the JavaView archives
installed within Mathematica, and J/Link to be installed.
*)

(*: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.
*)

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

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."

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

(*WorldPlot is necessary to read WorldGraphics objects.*)
(* This should be removed for new Mathamatica Versions (8.0)*)
Needs["Miscellaneous`WorldPlot`"]

Options[ JavaView ] = {
	Animatable -> False,
	Debug -> False,
	(*
	DisplaySize -> {320,256},
	DisplayLocation -> {0,50},
	*)
	Identify -> True,
	KeepView -> False,
	Replace -> True,
	Show -> True,
	Transparency -> 0.
}

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

Begin["`Private`"]

(* Currently options only enable debugging information. *)
Options[InstallJavaView] = {Verbose->False}

InstallJavaView[opts___?OptionQ]:=
	JavaBlock[
		Module[{CP,cmdLine,codebase,msJava,props,userStr,userVal,sep,thisPkgPath},
			{verbose} =	{Verbose} /. Flatten[{opts}] /. Options[InstallJavaView];
		   InstallJava[];
			(* Simply quit if this method was called before. *)
			If[ValueQ[viewer]==True,
				AssureDisplay[];
		  		Return[viewer]
	  		];
	  		
			(* Compute codebase. *)
			thisPkgPath = findCurrentPkg[];
			If[thisPkgPath === "",
				Message[JavaView::path];
				Return[$Failed],
			(* else *)
				sep 		= $PathnameSeparator;
				codebase	= StringReplace[thisPkgPath, $PathnameSeparator -> "/"];
			  	PsConfig`setCodeBase[codebase];
			  	Print["JavaView CodeBase = "<>codebase];

				BeginJavaBlock[];
		  		(* Set the user dir such that JavaView is able to find its language resources.
  		  		   Without explicit setting, the user dir is the parent directory of AddOns. *)
  	  			LoadClass["java.lang.System"];
				props=System`getProperties[];
(*Print["Properties = "<>props];*)
				userStr=JavaNew["java.lang.String","user.dir"];
(*Print["User Directory = "<>userStr];*)
				userVal=JavaNew["java.lang.String",codebase];
(*Print["UserVal = "<>userVal];*)
				props@put[userStr,userVal];
				EndJavaBlock[];
			];

		  	(* Load some basic Java classes. *)
			LoadJavaClass["java.awt.Color"];
			
		  	(* 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.PsObject"];
			LoadJavaClass["jv.object.PsDebug"];
			LoadJavaClass["jv.object.PsViewerIf"];
			LoadJavaClass["jv.project.PgGeometryIf"];
			LoadJavaClass["jv.project.PvGeometryIf"];
			LoadJavaClass["jv.project.PvCameraIf"];
			LoadJavaClass["jv.project.PvDisplayIf"];
			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"];
			(* Variable viewer must be global in this context. *)	
    	   	viewer = JavaNew["jv.viewer.PvViewer"];
		  	(* Instruct JavaView not to exit when the frame is closed. *)
	  		viewer@setEmbedded[True];
            (* KeepJavaObject[viewer]; Not needed, 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",True];
            KeepJavaObject[disp];
			(* Variable frame must be global in this context. *)	
    		frame = disp@getFrame[];
		  	frame@setLocation[0,50];
    		frame@setInnerSize[320,256];
            KeepJavaObject[frame];
			Return[viewer]
(*Print["... ready"];*)
		]
	]

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."

JavaViewGeom::usage =
"JavaViewGeom[geom] displays a JavaView geometry in a JavaView display.
Geometry must implement the interface jv.project.PgGeometryIf.
\n\n
See: JavaView[]"

AssureDisplay[]:=
	JavaBlock[  
	  	Module[{},
		   If[ValueQ[viewer]==False,
				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[JavaObjectQ[disp] == False,
				Print["Current display is no longer valid."];
			];
			If[viewer@hasDisplay[disp] == False,
				Print["Current display is not registered in the viewer."];
			];
			*)
            If[!JavaObject[disp],
    	         (* Print["Creating a new display ..."]; *)
(* Print["disp does not exist as Java Object."]; *)
            	disp = viewer@newDisplay["Display: From Mathematica", True];
            	frame = disp@getFrame[];
            	frame@setLocation[0,50];
            	frame@setInnerSize[320,256];
            ];
            If[!viewer@hasDisplay[disp],
(* Print["disp was not registered to the viewer."]; *)
                viewer@addDisplay["Display: From Mathematica", disp];
(*  
For some reason the first time closing the JavaView Window unregisters
the display from the viewer, repeated window.close doesn't.
Without reseting the frame it looks the same at least, but internally it isn't ...
                disp@setFrame[frame];
            	frame@setLocation[0,50];
              	frame@setInnerSize[320,256];
*)
            ];
    		Return[True]
		]
	]

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

(* View a Mathematica graphics in a JavaView display using JLink. *)
(* The unclassified declaration was added since otherwise ShowAnimation[]
was not understood. *)
(* JavaView[g_,opts___?OptionQ]:= JavaViewGraphics[g,opts] *)
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]

(*
	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[]:=
	JavaBlock[
	  	Module[{},
		   If[AssureDisplay[]==False,
				Message[JavaView::inst];
				Return[$Failed]
	    	];
			JavaShow[frame];
		]
	]

(* View a list of Mathematica graphics in a JavaView display using JLink. *)
JavaView[g_List,opts___?OptionQ] := 
	JavaBlock[
		Module[{animation,debug,geomArr,geomJvxArx,gs,i,identify,keepview,replace,show,transparency},
		   If[AssureDisplay[]==False,
				Message[JavaView::inst];
				Return[Null]
			];
			{animation,debug,identify,keepview,replace,show,transparency} = {Animatable,Debug,Identify,KeepView,Replace,Show,Transparency}/. Flatten[{opts, Options[JavaView]}];
			If[debug == True,
				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]]]==True,
				If[animation == True,
					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 == True,
				RemoveGeometries[];
			];

			selGeom = disp@getSelectedGeometry[];
		 	For[i=1,i<=Length[geomArr],i++,
    			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 == False,
				dispOption = loader@getDisplayOption[];
	   		If[dispOption =!= Null,
		 			dispOption@configure[disp];
					ReleaseJavaObject[dispOption];
    			];
			];

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

	    	If[show == True,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]
		]
	]
    
JavaViewGraphics[g_,opts___?OptionQ]:=
	JavaBlock[
	  	Module[{debug,gs,i,keepview,replace,show,sort,transparency},
	      If[AssureDisplay[]==False,
				Message[JavaView::inst];
				Return[Null]
		  	];
			{debug,identify,keepview,replace,show,transparency} = {Debug,Identify,KeepView,Replace,Show,Transparency}/. Flatten[{opts, Options[JavaView]}];

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

	    	If[Head[g]===ContourGraphics || Head[g]===WorldGraphics,
  				gs = FormatGraphics[Graphics[g]];,
  				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 == True,RemoveGeometries[];];
		
			selGeom = disp@getSelectedGeometry[];
		  	For[i=1,i<=Length[geomArr],i++,
    			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 == False,
				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];
			ReleaseJavaObject[loader];

	    	If[show == True,JavaShow[frame];];
	
		 	Return[geomArr[[1]]]
		]
	]
(* View a JavaView geometry produced in Mathematica in a JavaView display using JLink. *)
JavaViewGeom[geom_,opts___?OptionQ]:=
	JavaBlock[
	  	Module[{replace,show},
		   If[AssureDisplay[]==False,
				Message[JavaView::inst];
				Return[Null]
	    	];

		 	{replace,show} = {Replace,Show}/. Flatten[{opts, Options[JavaView]}];
    		If[replace == True,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 == True,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[]==True,
  						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];
			Return[tex]
		]
	]

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

    		If[Head[g]===ContourGraphics || Head[g]===WorldGraphics,
  				gs = FormatGraphics[Graphics[g]];,
  				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]
			];
			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==True,
				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]
		]
	]

End[]

EndPackage[]
