Inheritance: java.lang.Object
        protected override void onCreate(global::android.os.Bundle savedInstanceState)
        {
            // cmd /K c:\util\android-sdk-windows\platform-tools\adb.exe logcat
            // Camera PTP

            // http://developer.android.com/guide/topics/ui/notifiers/notifications.html

            base.onCreate(savedInstanceState);

            ScrollView sv = new ScrollView(this);

            LinearLayout ll = new LinearLayout(this);

            ll.setOrientation(LinearLayout.VERTICAL);

            sv.addView(ll);


            Button b = new Button(this);

            b.setText("AlertDialog! " + new { id = Thread.currentThread().getId() });
            int counter = 0;

            // ScriptCoreLib.Ultra ?
            b.AtClick(
                delegate
            {
                counter++;

                // http://www.tomswebdesign.net/Articles/Android/number-pad-input-class.html
                // https://android.googlesource.com/platform/frameworks/base/+/b896b9f/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
                // http://xmlstackoverflow.blogspot.com/2014/07/how-to-use-alertdialog-to-prompt-for-pin.html
                // http://incidencias-ctt.administracionelectronica.gob.es/websvn/filedetails.php?repname=clienteafirma&path=%2Fproject%2Fafirma-mobile%2Fafirma-android%2Ftrunk%2Fafirma-ui-android%2Fsrc%2Fes%2Fgob%2Fafirma%2Fandroid%2Fgui%2FPinDialog.java&peg=4040

                // X:\jsc.svn\examples\java\android\forms\FormsMessageBox\FormsMessageBox\ApplicationActivity.cs
                // X:\jsc.svn\examples\java\android\Test\TestAlertDialog\TestAlertDialog\ApplicationActivity.cs
                AlertDialog alertDialog = new AlertDialog.Builder(this).create();

                alertDialog.setTitle("Reset...");
                alertDialog.setMessage("Are you sure?");
                alertDialog.setButton("OK",
                    new xOnClickListener
                {
                    yield = delegate
                    {
                        b.setText("clicked! " + new { id = Thread.currentThread().getId() });
                    }
                }

                    );

                // skip icons?
                //alertDialog.setIcon(android.R.drawable.star_off);

                // can we do async yet?
                alertDialog.show();


            }
            );

            ll.addView(b);

            this.setContentView(sv);

            // X:\jsc.svn\examples\java\android\HelloOpenGLES20Activity\HelloOpenGLES20Activity\ScriptCoreLib.Android\Shader.cs

            // Error	1	'TestAlertDialog.Activities.ApplicationActivity' does not contain a definition for 'ShowLongToast' and no extension method 'ShowLongToast' accepting a first argument of type 'TestAlertDialog.Activities.ApplicationActivity' could be found (are you missing a using directive or an assembly reference?)	X:\jsc.svn\examples\java\android\TestAlertDialog\TestAlertDialog\ApplicationActivity.cs	80	18	TestAlertDialog
            //this.ShowLongToast("http://jsc-solutions.net");
            //this.ShowToast("http://jsc-solutions.net");


        }
        public static global::System.Windows.Forms.DialogResult Show(string text, string caption)
        {

            // or are we called on a background thread? 
            // for java, we can block a worker thread until ui is shown. for javascript cannot do it without async?
            // assume we are activity based..
            var context = ScriptCoreLib.Android.ThreadLocalContextReference.CurrentContext as Activity;
            var ui = context.getMainLooper() == Looper.myLooper();
            Console.WriteLine("enter MessageBox.Show " + new { ui });

            var value = default(global::System.Windows.Forms.DialogResult);
            var thread0 = Thread.CurrentThread;
            var sync = new AutoResetEvent(false);

            context.runOnUiThread(
                a =>
                {
                    //thread0 = Thread.CurrentThread;
                    //sync0ui.Set();

                    // X:\jsc.svn\examples\java\android\forms\FormsMessageBox\FormsMessageBox\Library\ApplicationControl.cs
                    // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2014/201410/20141025
                    // X:\jsc.svn\examples\java\android\Test\TestAlertDialog\TestAlertDialog\ApplicationActivity.cs


                    var alertDialog = new AlertDialog.Builder(context);

                    alertDialog.setTitle(caption);

                    if (!string.IsNullOrEmpty(caption))
                    {
                        alertDialog.setMessage(text);
                    }

                    // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2014/201410/20141026


                    alertDialog.setPositiveButton("OK",
                            new xDialogInterface_OnClickListener
                            {
                                yield = delegate
                                {
                                    Console.WriteLine(" alertDialog.setPositiveButton");
                                    value = global::System.Windows.Forms.DialogResult.OK;
                                    //sync.Set();
                                }
                            }
                        );

                    // skip icons?
                    //alertDialog.setIcon(android.R.drawable.star_off);
                    var dialog = alertDialog.create();

                    dialog.setOnDismissListener(
                        new xDialogInterface_OnDismissListener
                        {
                            yield = delegate
                            {
                                Console.WriteLine("  dialog.setOnDismissListener");
                                sync.Set();

                                if (ui)
                                    throw null;
                            }
                        }
                    );

                    dialog.show();


                    // http://stackoverflow.com/questions/13974661/runonuithread-vs-looper-getmainlooper-post-in-android
                    // http://developer.android.com/reference/android/os/Looper.html



                    //sync.Set();
                }
            );




            // need to poll? discard?


            if (ui)
            {
                try
                {
                    // loop until we throw null
                    // where is it thrown?
                    android.os.Looper.loop();
                }
                catch
                {
                }
            }
            else
            {
                sync.WaitOne();
            }

            Console.WriteLine("exit MessageBox.Show " + new { ui, value });
            return value;
        }
		public ApplicationSurface(RenderingContextView v, Button button_set_min_filter, Button button_set_mag_filter, Activity OwnerActivity)
		{
			v.onsurface +=
			 gl =>
			 {
				 //var __gl = (ScriptCoreLib.Android.__WebGLRenderingContext)(object)gl;

				 #region fields
				 /**
                     * Store the model matrix. This matrix is used to move models from object space (where each model can be thought
                     * of being located at the center of the universe) to world space.
                     */
				 float[] mModelMatrix = new float[16];

				 /**
                  * Store the view matrix. This can be thought of as our camera. This matrix transforms world space to eye space;
                  * it positions things relative to our eye.
                  */
				 float[] mViewMatrix = new float[16];

				 /** Store the projection matrix. This is used to project the scene onto a 2D viewport. */
				 float[] mProjectionMatrix = new float[16];

				 /** Allocate storage for the final combined matrix. This will be passed into the shader program. */
				 float[] mMVPMatrix = new float[16];

				 /** Store the accumulated rotation. */
				 float[] mAccumulatedRotation = new float[16];

				 /** Store the current rotation. */
				 float[] mCurrentRotation = new float[16];

				 /** A temporary matrix. */
				 float[] mTemporaryMatrix = new float[16];

				 /** 
                  * Stores a copy of the model matrix specifically for the light position.
                  */
				 float[] mLightModelMatrix = new float[16];

				 /** Store our model data in a float buffer. */
				 FloatBuffer mCubePositions;
				 FloatBuffer mCubeNormals;
				 FloatBuffer mCubeTextureCoordinates;
				 FloatBuffer mCubeTextureCoordinatesForPlane;

				 /** This will be used to pass in the transformation matrix. */
				 ScriptCoreLib.JavaScript.WebGL.WebGLUniformLocation mMVPMatrixHandle;

				 /** This will be used to pass in the modelview matrix. */
				 ScriptCoreLib.JavaScript.WebGL.WebGLUniformLocation mMVMatrixHandle;

				 /** This will be used to pass in the light position. */
				 ScriptCoreLib.JavaScript.WebGL.WebGLUniformLocation mLightPosHandle;

				 /** This will be used to pass in the texture. */
				 ScriptCoreLib.JavaScript.WebGL.WebGLUniformLocation mTextureUniformHandle;

				 /** This will be used to pass in model position information. */
				 int mPositionHandle;

				 /** This will be used to pass in model normal information. */
				 int mNormalHandle;

				 /** This will be used to pass in model texture coordinate information. */
				 int mTextureCoordinateHandle;

				 /** How many bytes per float. */
				 int mBytesPerFloat = 4;

				 /** Size of the position data in elements. */
				 int mPositionDataSize = 3;

				 /** Size of the normal data in elements. */
				 int mNormalDataSize = 3;

				 /** Size of the texture coordinate data in elements. */
				 int mTextureCoordinateDataSize = 2;

				 /** Used to hold a light centered on the origin in model space. We need a 4th coordinate so we can get translations to work when
                  *  we multiply this by our transformation matrices. */
				 float[] mLightPosInModelSpace = new float[] { 0.0f, 0.0f, 0.0f, 1.0f };

				 /** Used to hold the current position of the light in world space (after transformation via model matrix). */
				 float[] mLightPosInWorldSpace = new float[4];

				 /** Used to hold the transformed position of the light in eye space (after transformation via modelview matrix) */
				 float[] mLightPosInEyeSpace = new float[4];

				 /** This is a handle to our cube shading program. */
				 ScriptCoreLib.JavaScript.WebGL.WebGLProgram mProgramHandle;

				 /** This is a handle to our light point program. */
				 ScriptCoreLib.JavaScript.WebGL.WebGLProgram mPointProgramHandle;

				 /** These are handles to our texture data. */
				 ScriptCoreLib.JavaScript.WebGL.WebGLTexture mBrickDataHandle;
				 ScriptCoreLib.JavaScript.WebGL.WebGLTexture mGrassDataHandle;

				 #endregion

				 #region ontouchmove
				 // These still work without volatile, but refreshes are not guaranteed to happen.					
				 /* volatile */
				 float mDeltaX = 0;
				 /* volatile */
				 float mDeltaY = 0;

				 v.ontouchmove +=
					 (x, y) =>
					 {
						 mDeltaX += x;
						 mDeltaY += y;
					 };
				 #endregion

				 #region Define points for a cube.

				 // X, Y, Z
				 float[] cubePositionData =
			{
					 // In OpenGL counter-clockwise winding is default. This means that when we look at a triangle, 
					 // if the points are counter-clockwise we are looking at the "front". If not we are looking at
					 // the back. OpenGL has an optimization where all back-facing triangles are culled, since they
					 // usually represent the backside of an object and aren't visible anyways.

					 // Front face
					 -1.0f, 1.0f, 1.0f,
					-1.0f, -1.0f, 1.0f,
					1.0f, 1.0f, 1.0f,
					-1.0f, -1.0f, 1.0f,
					1.0f, -1.0f, 1.0f,
					1.0f, 1.0f, 1.0f,

					 // Right face
					 1.0f, 1.0f, 1.0f,
					1.0f, -1.0f, 1.0f,
					1.0f, 1.0f, -1.0f,
					1.0f, -1.0f, 1.0f,
					1.0f, -1.0f, -1.0f,
					1.0f, 1.0f, -1.0f,

					 // Back face
					 1.0f, 1.0f, -1.0f,
					1.0f, -1.0f, -1.0f,
					-1.0f, 1.0f, -1.0f,
					1.0f, -1.0f, -1.0f,
					-1.0f, -1.0f, -1.0f,
					-1.0f, 1.0f, -1.0f,

					 // Left face
					 -1.0f, 1.0f, -1.0f,
					-1.0f, -1.0f, -1.0f,
					-1.0f, 1.0f, 1.0f,
					-1.0f, -1.0f, -1.0f,
					-1.0f, -1.0f, 1.0f,
					-1.0f, 1.0f, 1.0f,

					 // Top face
					 -1.0f, 1.0f, -1.0f,
					-1.0f, 1.0f, 1.0f,
					1.0f, 1.0f, -1.0f,
					-1.0f, 1.0f, 1.0f,
					1.0f, 1.0f, 1.0f,
					1.0f, 1.0f, -1.0f,

					 // Bottom face
					 1.0f, -1.0f, -1.0f,
					1.0f, -1.0f, 1.0f,
					-1.0f, -1.0f, -1.0f,
					1.0f, -1.0f, 1.0f,
					-1.0f, -1.0f, 1.0f,
					-1.0f, -1.0f, -1.0f,
			};

				 // X, Y, Z
				 // The normal is used in light calculations and is a vector which points
				 // orthogonal to the plane of the surface. For a cube model, the normals
				 // should be orthogonal to the points of each face.
				 float[] cubeNormalData =
			{
					 // Front face
					 0.0f, 0.0f, 1.0f,
					0.0f, 0.0f, 1.0f,
					0.0f, 0.0f, 1.0f,
					0.0f, 0.0f, 1.0f,
					0.0f, 0.0f, 1.0f,
					0.0f, 0.0f, 1.0f,

					 // Right face 
					 1.0f, 0.0f, 0.0f,
					1.0f, 0.0f, 0.0f,
					1.0f, 0.0f, 0.0f,
					1.0f, 0.0f, 0.0f,
					1.0f, 0.0f, 0.0f,
					1.0f, 0.0f, 0.0f,

					 // Back face 
					 0.0f, 0.0f, -1.0f,
					0.0f, 0.0f, -1.0f,
					0.0f, 0.0f, -1.0f,
					0.0f, 0.0f, -1.0f,
					0.0f, 0.0f, -1.0f,
					0.0f, 0.0f, -1.0f,

					 // Left face 
					 -1.0f, 0.0f, 0.0f,
					-1.0f, 0.0f, 0.0f,
					-1.0f, 0.0f, 0.0f,
					-1.0f, 0.0f, 0.0f,
					-1.0f, 0.0f, 0.0f,
					-1.0f, 0.0f, 0.0f,

					 // Top face 
					 0.0f, 1.0f, 0.0f,
					0.0f, 1.0f, 0.0f,
					0.0f, 1.0f, 0.0f,
					0.0f, 1.0f, 0.0f,
					0.0f, 1.0f, 0.0f,
					0.0f, 1.0f, 0.0f,

					 // Bottom face 
					 0.0f, -1.0f, 0.0f,
					0.0f, -1.0f, 0.0f,
					0.0f, -1.0f, 0.0f,
					0.0f, -1.0f, 0.0f,
					0.0f, -1.0f, 0.0f,
					0.0f, -1.0f, 0.0f
			};

				 // S, T (or X, Y)
				 // Texture coordinate data.
				 // Because images have a Y axis pointing downward (values increase as you move down the image) while
				 // OpenGL has a Y axis pointing upward, we adjust for that here by flipping the Y axis.
				 // What's more is that the texture coordinates are the same for every face.
				 float[] cubeTextureCoordinateData =
			{
					 // Front face
					 0.0f, 0.0f,
					0.0f, 1.0f,
					1.0f, 0.0f,
					0.0f, 1.0f,
					1.0f, 1.0f,
					1.0f, 0.0f,

					 // Right face 
					 0.0f, 0.0f,
					0.0f, 1.0f,
					1.0f, 0.0f,
					0.0f, 1.0f,
					1.0f, 1.0f,
					1.0f, 0.0f,

					 // Back face 
					 0.0f, 0.0f,
					0.0f, 1.0f,
					1.0f, 0.0f,
					0.0f, 1.0f,
					1.0f, 1.0f,
					1.0f, 0.0f,

					 // Left face 
					 0.0f, 0.0f,
					0.0f, 1.0f,
					1.0f, 0.0f,
					0.0f, 1.0f,
					1.0f, 1.0f,
					1.0f, 0.0f,

					 // Top face 
					 0.0f, 0.0f,
					0.0f, 1.0f,
					1.0f, 0.0f,
					0.0f, 1.0f,
					1.0f, 1.0f,
					1.0f, 0.0f,

					 // Bottom face 
					 0.0f, 0.0f,
					0.0f, 1.0f,
					1.0f, 0.0f,
					0.0f, 1.0f,
					1.0f, 1.0f,
					1.0f, 0.0f
			};

				 // S, T (or X, Y)
				 // Texture coordinate data.
				 // Because images have a Y axis pointing downward (values increase as you move down the image) while
				 // OpenGL has a Y axis pointing upward, we adjust for that here by flipping the Y axis.
				 // What's more is that the texture coordinates are the same for every face.
				 float[] cubeTextureCoordinateDataForPlane =
			{
					 // Front face
					 0.0f, 0.0f,
					0.0f, 25.0f,
					25.0f, 0.0f,
					0.0f, 25.0f,
					25.0f, 25.0f,
					25.0f, 0.0f,

					 // Right face 
					 0.0f, 0.0f,
					0.0f, 25.0f,
					25.0f, 0.0f,
					0.0f, 25.0f,
					25.0f, 25.0f,
					25.0f, 0.0f,

					 // Back face 
					 0.0f, 0.0f,
					0.0f, 25.0f,
					25.0f, 0.0f,
					0.0f, 25.0f,
					25.0f, 25.0f,
					25.0f, 0.0f,

					 // Left face 
					 0.0f, 0.0f,
					0.0f, 25.0f,
					25.0f, 0.0f,
					0.0f, 25.0f,
					25.0f, 25.0f,
					25.0f, 0.0f,

					 // Top face 
					 0.0f, 0.0f,
					0.0f, 25.0f,
					25.0f, 0.0f,
					0.0f, 25.0f,
					25.0f, 25.0f,
					25.0f, 0.0f,

					 // Bottom face 
					 0.0f, 0.0f,
					0.0f, 25.0f,
					25.0f, 0.0f,
					0.0f, 25.0f,
					25.0f, 25.0f,
					25.0f, 0.0f
			};
				 #endregion

				 #region  Initialize the buffers.
				 mCubePositions = ByteBuffer.allocateDirect(cubePositionData.Length * mBytesPerFloat)
				 .order(ByteOrder.nativeOrder()).asFloatBuffer();
				 mCubePositions.put(cubePositionData).position(0);

				 mCubeNormals = ByteBuffer.allocateDirect(cubeNormalData.Length * mBytesPerFloat)
				 .order(ByteOrder.nativeOrder()).asFloatBuffer();
				 mCubeNormals.put(cubeNormalData).position(0);

				 mCubeTextureCoordinates = ByteBuffer.allocateDirect(cubeTextureCoordinateData.Length * mBytesPerFloat)
				 .order(ByteOrder.nativeOrder()).asFloatBuffer();
				 mCubeTextureCoordinates.put(cubeTextureCoordinateData).position(0);

				 mCubeTextureCoordinatesForPlane = ByteBuffer.allocateDirect(cubeTextureCoordinateDataForPlane.Length * mBytesPerFloat)
				 .order(ByteOrder.nativeOrder()).asFloatBuffer();
				 mCubeTextureCoordinatesForPlane.put(cubeTextureCoordinateDataForPlane).position(0);
				 #endregion


				 // Set the background clear color to black.
				 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);

				 // Use culling to remove back faces.
				 gl.enable(gl.CULL_FACE);

				 // Enable depth testing
				 gl.enable(gl.DEPTH_TEST);

				 // Enable texture mapping
				 gl.enable(gl.TEXTURE_2D);

				 #region setLookAtM
				 // Position the eye in front of the origin.
				 float eyeX = 0.0f;
				 float eyeY = 0.0f;
				 float eyeZ = -0.5f;

				 // We are looking toward the distance
				 float lookX = 0.0f;
				 float lookY = 0.0f;
				 float lookZ = -5.0f;

				 // Set our up vector. This is where our head would be pointing were we holding the camera.
				 float upX = 0.0f;
				 float upY = 1.0f;
				 float upZ = 0.0f;

				 // Set the view matrix. This matrix can be said to represent the camera position.
				 // NOTE: In OpenGL 1, a ModelView matrix is used, which is a combination of a model and
				 // view matrix. In OpenGL 2, we can keep track of these matrices separately if we choose.
				 Matrix.setLookAtM(mViewMatrix, 0, eyeX, eyeY, eyeZ, lookX, lookY, lookZ, upX, upY, upZ);
				 #endregion


				 #region mProgramHandle
				 mProgramHandle = gl.createProgram(
				  new Shaders.per_pixel_tex_and_lightVertexShader(),
				  new Shaders.per_pixel_tex_and_lightFragmentShader()
				 );

				 gl.bindAttribLocation(mProgramHandle, 0, "a_Position");
				 gl.bindAttribLocation(mProgramHandle, 1, "a_Color");
				 gl.bindAttribLocation(mProgramHandle, 2, "a_TexCoordinate");

				 gl.linkProgram(mProgramHandle);
				 #endregion

				 // Define a simple shader program for our point.

				 #region mPointProgramHandle
				 mPointProgramHandle = gl.createProgram(
					 new Shaders.pointVertexShader(),
					 new Shaders.pointFragmentShader()
				 );

				 gl.bindAttribLocation(mPointProgramHandle, 0, "a_Position");

				 gl.linkProgram(mPointProgramHandle);
				 #endregion


				 #region loadTexture
				 Func<android.graphics.Bitmap, ScriptCoreLib.JavaScript.WebGL.WebGLTexture> loadTexture = (bitmap) =>
				 {
					 var textureHandle = gl.createTexture();

					 // Bind to the texture in OpenGL
					 gl.bindTexture(gl.TEXTURE_2D, textureHandle);

					 // Set filtering
					 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, (int)gl.NEAREST);
					 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, (int)gl.NEAREST);

					 // Load the bitmap into the bound texture.
					 GLUtils.texImage2D((int)gl.TEXTURE_2D, 0, bitmap, 0);

					 // Recycle the bitmap, since its data has been loaded into OpenGL.
					 bitmap.recycle();


					 return textureHandle;
				 };
				 #endregion

				 #region openFileFromAssets
				 Func<string, InputStream> openFileFromAssets = (string spath) =>
				 {
					 InputStream value = null;
					 try
					 {
						 value = OwnerActivity.getResources().getAssets().open(spath);
					 }
					 catch
					 {

					 }
					 return value;

				 };
				 #endregion


				 // cant we use knownAssets yet?
				 var stone_wall_public_domain = android.graphics.BitmapFactory.decodeStream(
					 openFileFromAssets("assets/AndroidOpenGLESLesson6Activity/stone_wall_public_domain.png")
				 );


				 var noisy_grass_public_domain = android.graphics.BitmapFactory.decodeStream(
					 openFileFromAssets("assets/AndroidOpenGLESLesson6Activity/noisy_grass_public_domain.png")
				 );

				 // Load the texture
				 mBrickDataHandle = loadTexture(
					 stone_wall_public_domain
				 );

				 gl.generateMipmap(gl.TEXTURE_2D);


				 mGrassDataHandle = loadTexture(
				   noisy_grass_public_domain
				 );

				 gl.generateMipmap(gl.TEXTURE_2D);



				 // Initialize the accumulated rotation matrix
				 Matrix.setIdentityM(mAccumulatedRotation, 0);

				 #region onresize
				 v.onresize +=
					 (width, height) =>
					 {
						 // Set the OpenGL viewport to the same size as the surface.
						 gl.viewport(0, 0, width, height);

						 // Create a new perspective projection matrix. The height will stay the same
						 // while the width will vary as per aspect ratio.
						 float ratio = (float)width / height;
						 float left = -ratio;
						 float right = ratio;
						 float bottom = -1.0f;
						 float top = 1.0f;
						 float near = 1.0f;
						 float far = 1000.0f;

						 Matrix.frustumM(mProjectionMatrix, 0, left, right, bottom, top, near, far);
					 };
				 #endregion


				 #region TEXTURE_MIN_FILTER
				 button_set_min_filter.AtClick(
					 delegate
					 {
						 var builder = new AlertDialog.Builder(OwnerActivity);


						 builder.setTitle("Set TEXTURE_MIN_FILTER!");
						 builder.setItems(
							 new[] {
									"NEAREST",
									"LINEAR",
									"NEAREST_MIPMAP_NEAREST",
									"NEAREST_MIPMAP_LINEAR",
									"LINEAR_MIPMAP_NEAREST",
									"LINEAR_MIPMAP_LINEAR",
								},
							 item =>
							 {

								 v.queueEvent(
									 delegate
									 {
										 int filter;

										 if (item == 0)
										 {
											 filter = (int)gl.NEAREST;
										 }
										 else if (item == 1)
										 {
											 filter = (int)gl.LINEAR;
										 }
										 else if (item == 2)
										 {
											 filter = (int)gl.NEAREST_MIPMAP_NEAREST;
										 }
										 else if (item == 3)
										 {
											 filter = (int)gl.NEAREST_MIPMAP_LINEAR;
										 }
										 else if (item == 4)
										 {
											 filter = (int)gl.LINEAR_MIPMAP_NEAREST;
										 }
										 else // if (item == 5)
										 {
											 filter = (int)gl.LINEAR_MIPMAP_LINEAR;
										 }

										 if (mBrickDataHandle != null)
											 if (mGrassDataHandle != null)
											 {
												 gl.bindTexture(gl.TEXTURE_2D, mBrickDataHandle);
												 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);
												 gl.bindTexture(gl.TEXTURE_2D, mGrassDataHandle);
												 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);

											 }
									 }
								 );
							 }
						 );


						 var dialog = builder.create();

						 dialog.setOwnerActivity(OwnerActivity);
						 dialog.show();


					 }
					 );
				 #endregion

				 #region TEXTURE_MAG_FILTER
				 button_set_mag_filter.AtClick(
					 delegate
					 {
						 var builder = new AlertDialog.Builder(OwnerActivity);

						 builder.setTitle("Set TEXTURE_MAG_FILTER");
						 builder.setItems(
							 new[]{
									"GL_NEAREST",
									"GL_LINEAR"
								},
							 item =>
							 {


								 v.queueEvent(
									 delegate
									 {
										 int filter;

										 if (item == 0)
										 {
											 filter = (int)gl.NEAREST;
										 }
										 else // if (item == 1)
										 {
											 filter = (int)gl.LINEAR;
										 }

										 if (mBrickDataHandle != null)
											 if (mGrassDataHandle != null)
											 {
												 gl.bindTexture(gl.TEXTURE_2D, mBrickDataHandle);
												 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
												 gl.bindTexture(gl.TEXTURE_2D, mGrassDataHandle);
												 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
											 }

									 }
								 );
							 }
						 );

						 var dialog = builder.create();

						 dialog.setOwnerActivity(OwnerActivity);
						 dialog.show();
					 }
				 );
				 #endregion




				 #region onframe
				 v.onframe +=
					 delegate
					 {
						 var sw = Stopwatch.StartNew();

						 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

						 // Do a complete rotation every 10 seconds.
						 long time = SystemClock.uptimeMillis() % 10000L;
						 long slowTime = SystemClock.uptimeMillis() % 100000L;
						 float angleInDegrees = (360.0f / 10000.0f) * ((int)time);
						 float slowAngleInDegrees = (360.0f / 100000.0f) * ((int)slowTime);

						 var program = mProgramHandle;
						 // Set our per-vertex lighting program.
						 gl.useProgram(program);

						 var uniforms = program.Uniforms(gl);

						 // Set program handles for cube drawing.
						 mMVPMatrixHandle = gl.getUniformLocation(program, "u_MVPMatrix");
						 mMVMatrixHandle = gl.getUniformLocation(program, "u_MVMatrix");
						 mLightPosHandle = gl.getUniformLocation(program, "u_LightPos");
						 mTextureUniformHandle = gl.getUniformLocation(program, "u_Texture");

						 mPositionHandle = gl.getAttribLocation(program, "a_Position");
						 mNormalHandle = gl.getAttribLocation(program, "a_Normal");
						 mTextureCoordinateHandle = gl.getAttribLocation(program, "a_TexCoordinate");

						 // Calculate position of the light. Rotate and then push into the distance.
						 Matrix.setIdentityM(mLightModelMatrix, 0);
						 Matrix.translateM(mLightModelMatrix, 0, 0.0f, 0.0f, -2.0f);
						 Matrix.rotateM(mLightModelMatrix, 0, angleInDegrees, 0.0f, 1.0f, 0.0f);
						 Matrix.translateM(mLightModelMatrix, 0, 0.0f, 0.0f, 3.5f);

						 Matrix.multiplyMV(mLightPosInWorldSpace, 0, mLightModelMatrix, 0, mLightPosInModelSpace, 0);
						 Matrix.multiplyMV(mLightPosInEyeSpace, 0, mViewMatrix, 0, mLightPosInWorldSpace, 0);

						 // Draw a cube.
						 // Translate the cube into the screen.
						 Matrix.setIdentityM(mModelMatrix, 0);
						 Matrix.translateM(mModelMatrix, 0, 0.0f, 0.8f, -3.5f);

						 // Set a matrix that contains the current rotation.
						 Matrix.setIdentityM(mCurrentRotation, 0);
						 Matrix.rotateM(mCurrentRotation, 0, mDeltaX, 0.0f, 1.0f, 0.0f);
						 Matrix.rotateM(mCurrentRotation, 0, mDeltaY, 1.0f, 0.0f, 0.0f);
						 mDeltaX = 0.1f;
						 mDeltaY = 0.1f;

						 // Multiply the current rotation by the accumulated rotation, and then set the accumulated rotation to the result.
						 Matrix.multiplyMM(mTemporaryMatrix, 0, mCurrentRotation, 0, mAccumulatedRotation, 0);
						 java.lang.System.arraycopy(mTemporaryMatrix, 0, mAccumulatedRotation, 0, 16);

						 // Rotate the cube taking the overall rotation into account.     	
						 Matrix.multiplyMM(mTemporaryMatrix, 0, mModelMatrix, 0, mAccumulatedRotation, 0);
						 java.lang.System.arraycopy(mTemporaryMatrix, 0, mModelMatrix, 0, 16);

						 // Set the active texture unit to texture unit 0.
						 gl.activeTexture(gl.TEXTURE0);

						 // Bind the texture to this unit.
						 gl.bindTexture(gl.TEXTURE_2D, mBrickDataHandle);

						 // Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
						 gl.uniform1i(mTextureUniformHandle, 0);

						 // Pass in the texture coordinate information
						 mCubeTextureCoordinates.position(0);

						 opengl.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, (int)gl.FLOAT, false,
								 0, mCubeTextureCoordinates);

						 #region drawCube
						 Action drawCube =
							 delegate
							 {
								 // Pass in the position information
								 mCubePositions.position(0);
								 opengl.glVertexAttribPointer(mPositionHandle, mPositionDataSize, (int)gl.FLOAT, false,
										 0, mCubePositions);

								 gl.enableVertexAttribArray((uint)mPositionHandle);

								 // Pass in the normal information
								 mCubeNormals.position(0);
								 opengl.glVertexAttribPointer(mNormalHandle, mNormalDataSize, (int)gl.FLOAT, false,
										 0, mCubeNormals);

								 gl.enableVertexAttribArray((uint)mNormalHandle);

								 // This multiplies the view matrix by the model matrix, and stores the result in the MVP matrix
								 // (which currently contains model * view).
								 Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mModelMatrix, 0);

								 // Pass in the modelview matrix.
								 gl.uniformMatrix4fv(mMVMatrixHandle, false, mMVPMatrix);

								 // This multiplies the modelview matrix by the projection matrix, and stores the result in the MVP matrix
								 // (which now contains model * view * projection).        
								 Matrix.multiplyMM(mTemporaryMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
								 java.lang.System.arraycopy(mTemporaryMatrix, 0, mMVPMatrix, 0, 16);

								 // Pass in the combined matrix.
								 gl.uniformMatrix4fv(mMVPMatrixHandle, false, mMVPMatrix);

								 // Pass in the light position in eye space.        
								 gl.uniform3f(mLightPosHandle, mLightPosInEyeSpace[0], mLightPosInEyeSpace[1], mLightPosInEyeSpace[2]);

								 // Draw the cube.k
								 gl.drawArrays(gl.TRIANGLES, 0, 36);
							 };
						 #endregion

						 drawCube();

						 // Draw a plane
						 Matrix.setIdentityM(mModelMatrix, 0);
						 Matrix.translateM(mModelMatrix, 0, 0.0f, -2.0f, -5.0f);
						 Matrix.scaleM(mModelMatrix, 0, 25.0f, 1.0f, 25.0f);
						 Matrix.rotateM(mModelMatrix, 0, slowAngleInDegrees, 0.0f, 1.0f, 0.0f);

						 // Set the active texture unit to texture unit 0.
						 gl.activeTexture(gl.TEXTURE0);

						 // Bind the texture to this unit.
						 gl.bindTexture(gl.TEXTURE_2D, mGrassDataHandle);

						 // Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.
						 gl.uniform1i(mTextureUniformHandle, 0);

						 // Pass in the texture coordinate information
						 mCubeTextureCoordinatesForPlane.position(0);
						 opengl.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, (int)gl.FLOAT, false,
								 0, mCubeTextureCoordinatesForPlane);

						 gl.enableVertexAttribArray((uint)mTextureCoordinateHandle);

						 drawCube();


						 #region drawLight
						 Action drawLight =
							 delegate
							 {
								 var pointMVPMatrixHandle = gl.getUniformLocation(mPointProgramHandle, "u_MVPMatrix");
								 var pointPositionHandle = gl.getAttribLocation(mPointProgramHandle, "a_Position");

								 // Pass in the position.
								 gl.vertexAttrib3f((uint)pointPositionHandle, mLightPosInModelSpace[0], mLightPosInModelSpace[1], mLightPosInModelSpace[2]);

								 // Since we are not using a buffer object, disable vertex arrays for this attribute.
								 gl.disableVertexAttribArray((uint)pointPositionHandle);

								 // Pass in the transformation matrix.
								 Matrix.multiplyMM(mMVPMatrix, 0, mViewMatrix, 0, mLightModelMatrix, 0);
								 Matrix.multiplyMM(mTemporaryMatrix, 0, mProjectionMatrix, 0, mMVPMatrix, 0);
								 java.lang.System.arraycopy(mTemporaryMatrix, 0, mMVPMatrix, 0, 16);

								 gl.uniformMatrix4fv(pointMVPMatrixHandle, false, mMVPMatrix);

								 // Draw the point.
								 gl.drawArrays(gl.POINTS, 0, 1);
							 };
						 #endregion

						 // Draw a point to indicate the light.
						 gl.useProgram(mPointProgramHandle);
						 drawLight();

						 sw.Stop();
						 OwnerActivity.runOnUiThread(
							 delegate
							 {
								 // Caused by: java.lang.ArithmeticException: divide by zero
								 // at AndroidOpenGLESLesson6Activity.Shaders.ApplicationSurface___c__DisplayClass0_4.__ctor_b__14(ApplicationSurface___c__DisplayClass0_4.java:28)
								 // ... 20 more
								 //Force finishing activity AndroidOpenGLESLesson6Activity.Activities /.AndroidOpenGLESLesson6Activity

								 OwnerActivity.setTitle(
									 "" + new { sw.ElapsedMilliseconds, fps = 1000.0 / sw.ElapsedMilliseconds });

							 }
						 );

					 };
				 #endregion

			 };

		}
示例#4
0
        void ProcessCollisions()
        {
            bool gameOver = false;
            int ai = 0;
            // check which asteroids are colliding with bullets
            while (ai < myAsteroids.Count)
            {
                Asteroid asteroid = myAsteroids[ai];
                int asteroidRadiusSquare = 16 * (1 << asteroid.Size);
                asteroidRadiusSquare *= asteroidRadiusSquare;
                bool collisionFound = false;
                for (int bi = 0; bi < myBullets.Count; bi++)
                {
                    PhysicsObject bullet = myBullets[bi];
                    Vector4f v = bullet.Location - asteroid.PhysicsObject.Location;
                    if (v.LengthSquare < asteroidRadiusSquare)
                    {
                        // remove the asteroid and bullet
                        collisionFound = true;
                        myAsteroids.RemoveAt(ai);
                        myBullets.RemoveAt(bi);

                        // split the asteroid into two if it's not tiny
                        if (asteroid.Size > 0)
                        {
                            Asteroid one = CreateAsteroid();
                            Asteroid two = CreateAsteroid();
                            one.Size = two.Size = asteroid.Size - 1;
                            one.CreationTime = two.CreationTime = asteroid.CreationTime;
                            one.PhysicsObject.Location = two.PhysicsObject.Location = asteroid.PhysicsObject.Location;
                            myAsteroids.Add(one);
                            myAsteroids.Add(two);
                        }
                        break;
                    }
                }

                // see if the asteroid is hitting the ship
                Vector4f sv = myShip.Location - asteroid.PhysicsObject.Location;
                if (sv.LengthSquare < asteroidRadiusSquare && System.Environment.TickCount - asteroid.CreationTime > AsteroidGracePeriod)
                    gameOver = true;

                // dont increment if we removed the asteroid
                if (!collisionFound)
                    ai++;
            }

            // if there zero asteroids, add one
            if (myAsteroids.Count == 0)
            {
                // reset the timer
                //myAsteroidTimer.Enabled = false;
                //myAsteroidTimer.Enabled = true;
                myAsteroids.Add(CreateAsteroid());
            }

            // show the gamer over form if the ship exploded
            if (gameOver)
            {
                if (!mIsDialogShowing)
                {
                    mIsDialogShowing = true;
                    mHandler.post(() =>
                    {
                        var b = new AlertDialog.Builder(this);
                        b.setTitle("Game Over!");
                        b.setMessage("Try again?");
                        b.setPositiveButton(global::[email protected], (d, which) => { mIsDialogShowing = false; ResetGame(); });
                        b.setNegativeButton(global::[email protected], (d, which) => { mIsDialogShowing = false; finish(); });
                        b.setCancelable(false);
                        b.create().show();
                    });
                }
            }
        }
示例#5
0
        public DialogResult ShowDialog()
        {
            this.InternalSetContext(
                global::ScriptCoreLib.Android.ThreadLocalContextReference.CurrentContext
            );

            // X:\jsc.svn\examples\java\android\forms\FormsMessageBox\FormsMessageBox\Library\ApplicationControl.cs
            // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2014/201410/20141025
            // X:\jsc.svn\examples\java\android\Test\TestAlertDialog\TestAlertDialog\ApplicationActivity.cs

            var value = default(global::System.Windows.Forms.DialogResult);
            var alertDialog = new AlertDialog.Builder(ScriptCoreLib.Android.ThreadLocalContextReference.CurrentContext);

            alertDialog.setTitle(this.Text);



            // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2014/201410/20141026

            //E/AndroidRuntime( 1380): Caused by: java.lang.NoSuchMethodError: android.app.AlertDialog$Builder.setOnDismissListener
            //E/AndroidRuntime( 1380):        at ScriptCoreLib.Android.BCLImplementation.System.Windows.Forms.__Form.ShowDialog(__Form.java:110)

            // ?
            // alertDialog.setOnDismissListener(
            //    new xDialogInterface_OnDismissListener()
            //);

            //alertDialog.setPositiveButton("OK",
            //        new xDialogInterface_OnClickListener
            //{
            //    yield = delegate
            //    {
            //        value = global::System.Windows.Forms.DialogResult.OK;
            //    }
            //}
            //    );

            alertDialog.setView(this.InternalGetContainer());

            // skip icons?
            //alertDialog.setIcon(android.R.drawable.star_off);
            var dialog = alertDialog.create();

            dialog.setOnDismissListener(
               new xDialogInterface_OnDismissListener()
            );

            dialog.show();

            // http://stackoverflow.com/questions/13974661/runonuithread-vs-looper-getmainlooper-post-in-android
            // http://developer.android.com/reference/android/os/Looper.html

            __dismissOnClose(dialog);

            try
            {
                // loop until we throw null
                android.os.Looper.loop();
            }
            catch
            {
            }

            return value;
        }
        private void button1_Click(object sender, EventArgs e)
        {
            // http://stackoverflow.com/questions/2028697/dialogs-alertdialogs-how-to-block-execution-while-dialog-is-up-net-style
            // http://mindfiremobile.wordpress.com/2014/04/21/displaying-alert-dialog-in-android-using-xamarin/

            //button1.Text = "Clicked!";

            // X:\jsc.svn\examples\java\android\forms\FormsMessageBox\FormsMessageBox\ApplicationActivity.cs
            // X:\jsc.svn\examples\java\android\Test\TestAlertDialog\TestAlertDialog\ApplicationActivity.cs
            var alertDialog = new AlertDialog.Builder(ScriptCoreLib.Android.ThreadLocalContextReference.CurrentContext);

            alertDialog.setTitle("Reset...");
            alertDialog.setMessage("Are you sure?");

            alertDialog.setOnDismissListener(
                new xDialogInterface_OnDismissListener
                {
                    yield = delegate
                    {
                        throw null;
                    }
                }
            );

            alertDialog.setPositiveButton("OK",
                new xOnClickListener
            {
                yield = delegate
                {
                    button1.Text = "clicked! " + new
                    {


                        Thread.CurrentThread.ManagedThreadId
                    };



                }
            }

                );

            // skip icons?
            //alertDialog.setIcon(android.R.drawable.star_off);

            // can we do async yet?
            alertDialog.create().show();

            // http://stackoverflow.com/questions/13974661/runonuithread-vs-looper-getmainlooper-post-in-android

            //android.os.Looper.getMainLooper().loop();

            // http://developer.android.com/reference/android/os/Looper.html

            try
            {
                // loop until we throw null
                android.os.Looper.loop();
            }
            catch
            {

            }

            button1.Text = "clicked! after looper " + new
            {


                Thread.CurrentThread.ManagedThreadId
            };

            //alertDialog.create().show();


        }
        // http://www.codeproject.com/Tips/623446/Style-Any-Activity-as-an-Alert-Dialog-in-Android
        // android:theme="@android:style/Theme.Holo.Dialog"



        protected override void onCreate(global::android.os.Bundle savedInstanceState)
        {
            ScriptCoreLib.Android.ThreadLocalContextReference.CurrentContext = this;

            // X:\jsc.svn\examples\java\android\forms\AndroidFormsActivity\AndroidFormsActivity\ApplicationActivity.cs

            // cmd /K c:\util\android-sdk-windows\platform-tools\adb.exe logcat
            // Camera PTP

            // http://developer.android.com/guide/topics/ui/notifiers/notifications.html

            base.onCreate(savedInstanceState);

            var sv = new ScrollView(this);
            var ll = new LinearLayout(this);
            ll.setOrientation(LinearLayout.VERTICAL);
            sv.addView(ll);


            var b = new android.widget.Button(this);

            // jsc is doing the wrong thing here
            var SDK_INT = android.os.Build.VERSION.SDK_INT;

            b.setText("Notify! " + new { SDK_INT, android.os.Build.VERSION.SDK });
            int counter = 0;



            // http://stackoverflow.com/questions/12900795/how-to-get-a-pin-number-password-keyboard-in-android
            //var t = new EditText(this);
            //t.setInputType(android.text.InputType.TYPE_NUMBER_VARIATION_PASSWORD);
            //t.setTransformationMethod(android.text.method.PasswordTransformationMethod.getInstance());
            //ll.addView(t);

            // ScriptCoreLib.Ultra ?
            b.AtClick(
                delegate
            {
                counter++;

                // X:\jsc.svn\examples\javascript\android\Test\TestPINDialog\TestPINDialog\ApplicationWebService.cs

                var alertDialog = new AlertDialog.Builder(this);

                alertDialog.setTitle("Hello world");
               


                alertDialog.setPositiveButton("OK",
               new xOnClickListener
                {
                    yield = delegate
                    {
                        b.setText("clicked! " + new { id = Thread.currentThread().getId() });
                    }
                }

               );


                var cc = new AndroidFormsActivity.ApplicationControl();


                //ScriptCoreLib.Extensions.Android.AndroidFormsExtensions.AttachTo(
                //    cc, 

                // X:\jsc.svn\core\ScriptCoreLibAndroid.Windows.Forms\ScriptCoreLibAndroid.Windows.Forms\Extensions\Android\AndroidFormsExtensions.cs

                __Control _cc = cc;

                _cc.InternalSetContext(this);

                alertDialog.setView(_cc.InternalGetElement());


                // skip icons?
                //alertDialog.setIcon(android.R.drawable.star_off);

                // can we do async yet?
                alertDialog.create().show();
            }
            );

            ll.addView(b);

            this.setContentView(sv);

            // X:\jsc.svn\examples\java\android\HelloOpenGLES20Activity\HelloOpenGLES20Activity\ScriptCoreLib.Android\Shader.cs

            // Error	1	'FormsMessageBox.Activities.ApplicationActivity' does not contain a definition for 'ShowLongToast' and no extension method 'ShowLongToast' accepting a first argument of type 'FormsMessageBox.Activities.ApplicationActivity' could be found (are you missing a using directive or an assembly reference?)	X:\jsc.svn\examples\java\android\FormsMessageBox\FormsMessageBox\ApplicationActivity.cs	80	18	FormsMessageBox
            //this.ShowLongToast("http://jsc-solutions.net");


        }
        protected override void onCreate(global::android.os.Bundle savedInstanceState)
        {
            // cmd /K c:\util\android-sdk-windows\platform-tools\adb.exe logcat
            // Camera PTP

            // http://developer.android.com/guide/topics/ui/notifiers/notifications.html

            base.onCreate(savedInstanceState);

            var sv = new ScrollView(this);
            var ll = new LinearLayout(this);
            ll.setOrientation(LinearLayout.VERTICAL);
            sv.addView(ll);


            var b = new Button(this);

            // jsc is doing the wrong thing here
            var SDK_INT = android.os.Build.VERSION.SDK_INT;

            b.setText("Notify! " + new { SDK_INT, android.os.Build.VERSION.SDK });
            int counter = 0;



            // http://stackoverflow.com/questions/12900795/how-to-get-a-pin-number-password-keyboard-in-android
            //var t = new EditText(this);
            //t.setInputType(android.text.InputType.TYPE_NUMBER_VARIATION_PASSWORD);
            //t.setTransformationMethod(android.text.method.PasswordTransformationMethod.getInstance());
            //ll.addView(t);

            // ScriptCoreLib.Ultra ?
            b.AtClick(
                delegate
            {
                counter++;

                // X:\jsc.svn\examples\javascript\android\Test\TestPINDialog\TestPINDialog\ApplicationWebService.cs

                var alertDialog = new AlertDialog.Builder(this);

                alertDialog.setTitle("Authentication");
                alertDialog.setMessage("PIN1");



                var xll = new LinearLayout(this);
                xll.setOrientation(LinearLayout.VERTICAL);

                var xt = new EditText(this);

                //http://stackoverflow.com/questions/6443286/type-number-variation-password-not-present-in-inputtype-class
                // https://groups.google.com/forum/#!topic/android-developers/UZuZjEbAnLE


                // http://kmansoft.com/2011/02/27/an-edittext-for-entering-ip-addresses/
                xt.setInputType(

                    android.text.InputType.TYPE_CLASS_NUMBER |
                    android.text.InputType.TYPE_NUMBER_VARIATION_PASSWORD);
                xt.setTransformationMethod(android.text.method.PasswordTransformationMethod.getInstance());
                xll.addView(xt);


                alertDialog.setPositiveButton("OK",
               new xOnClickListener
                {
                    yield = delegate
                    {
                        b.setText("clicked! " + new { id = Thread.currentThread().getId() });
                    }
                }

               );

                //{
                //    var xb = new Button(this);
                //    xb.setText("1");
                //    xll.addView(xb);
                //}

                //{
                //    var xb = new Button(this);
                //    xb.setText("2");
                //    xll.addView(xb);
                //}

                //{
                //    var xb = new Button(this);
                //    xb.setText("3");
                //    xll.addView(xb);
                //}



                alertDialog.setView(xll);


                // skip icons?
                //alertDialog.setIcon(android.R.drawable.star_off);

                // can we do async yet?
                alertDialog.create().show();
            }
            );

            ll.addView(b);

            this.setContentView(sv);

            // X:\jsc.svn\examples\java\android\HelloOpenGLES20Activity\HelloOpenGLES20Activity\ScriptCoreLib.Android\Shader.cs

            // Error	1	'TestPINLayoutDialog.Activities.ApplicationActivity' does not contain a definition for 'ShowLongToast' and no extension method 'ShowLongToast' accepting a first argument of type 'TestPINLayoutDialog.Activities.ApplicationActivity' could be found (are you missing a using directive or an assembly reference?)	X:\jsc.svn\examples\java\android\TestPINLayoutDialog\TestPINLayoutDialog\ApplicationActivity.cs	80	18	TestPINLayoutDialog
            //this.ShowLongToast("http://jsc-solutions.net");


        }
        /// <summary>
        /// This Method is a javascript callable method.
        /// </summary>
        /// <param name="e">A parameter from javascript.</param>
        /// <param name="y">A callback to javascript.</param>
        //public async Task<string> WebMethod2()
        public Task<string> WebMethod2()
        {
            // http://stackoverflow.com/questions/25003121/how-to-use-alertdialog-to-prompt-for-pin
            // X:\jsc.svn\examples\java\android\Test\TestAlertDialog\TestAlertDialog\ApplicationActivity.cs

            // https://android.googlesource.com/platform/frameworks/base/+/b896b9f/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
            // http://seek-for-android.googlecode.com/svn-history/r172/trunk/applications/SecureFileManager/SecurityFileManager/src/org/openintents/filemanager/FileManagerActivity.java
            // https://github.com/Paldom/PinDialog

            var c = (Activity)ScriptCoreLib.Android.ThreadLocalContextReference.CurrentContext;

            // #5 java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

            var a = new AutoResetEvent(false);

            //c.runOnUiThread(
            new { }.With(
                async delegate
                {
                    await default(HopToUIAwaitable);

                    //// the context. lets find it
                    //var alertDialogBuilder = new AlertDialog.Builder(c);


                    //LayoutInflater inflater = LayoutInflater.from(c);

                    // https://github.com/chinloong/Android-PinView/blob/master/res/layout/activity_pin_entry_view.xml
                    // http://lifehacker.com/three-ways-to-improve-your-androids-lock-screen-securi-1293317441

                    var alertDialog = new AlertDialog.Builder(c);

                    alertDialog.setTitle("Authentication");
                    alertDialog.setMessage("PIN1");



                    var xll = new LinearLayout(c);
                    xll.setOrientation(LinearLayout.VERTICAL);

                    var xt = new EditText(c);

                    //http://stackoverflow.com/questions/6443286/type-number-variation-password-not-present-in-inputtype-class
                    // https://groups.google.com/forum/#!topic/android-developers/UZuZjEbAnLE


                    // http://kmansoft.com/2011/02/27/an-edittext-for-entering-ip-addresses/
                    xt.setInputType(

                        android.text.InputType.TYPE_CLASS_NUMBER |
                        android.text.InputType.TYPE_NUMBER_VARIATION_PASSWORD);
                    xt.setTransformationMethod(android.text.method.PasswordTransformationMethod.getInstance());
                    xll.addView(xt);

                    // set button
                    alertDialog.setPositiveButton("OK",
                   new xOnClickListener
                    {
                        yield = delegate
                        {
                            // I/System.Console(23890): OK {{ ManagedThreadId = 1 }}
                            Console.WriteLine(
                                "OK " +
                     new { Thread.CurrentThread.ManagedThreadId }

                                );

                            a.Set();
                        }
                    }

                   );

                    //{
                    //    var xb = new Button(this);
                    //    xb.setText("1");
                    //    xll.addView(xb);
                    //}

                    //{
                    //    var xb = new Button(this);
                    //    xb.setText("2");
                    //    xll.addView(xb);
                    //}

                    //{
                    //    var xb = new Button(this);
                    //    xb.setText("3");
                    //    xll.addView(xb);
                    //}



                    alertDialog.setView(xll);


                    // skip icons?
                    //alertDialog.setIcon(android.R.drawable.star_off);

                    // can we do async yet?
                    alertDialog.create().show();

                }
            );


            a.WaitOne();

            // report service thread
            return new { Thread.CurrentThread.ManagedThreadId }.ToString().AsResult();
        }