Commits

Romain Vernoux committed 489cba4

handling UI runtime changes

Comments (0)

Files changed (7)

AndroidManifest.xml

       package="jp.co.itpl.ocamlandroid"
       android:versionCode="1"
       android:versionName="1.0">
-    <application android:icon="@drawable/icon" android:label="@string/app_name">
+    <application android:icon="@drawable/icon" 
+    			 android:label="@string/app_name">
         <activity android:name=".MainActivity"
                   android:label="@string/app_name">
             <intent-filter>
                 <category android:name="android.intent.category.LAUNCHER" />
             </intent-filter>
         </activity>
+        <activity
+        	android:theme="@style/MyTheme"
+        	android:name=".About">
+        	
+        </activity>
 
     </application>
     <uses-sdk android:minSdkVersion="3" />

res/layout/about.xml

 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-	android:orientation="vertical" android:layout_width="fill_parent"
-	android:layout_height="fill_parent"
-	android:gravity="top"
-	>
+	android:orientation="vertical" 
+	android:layout_width="fill_parent"
+	android:layout_height="wrap_content"
+	android:padding="10dip">
 
-	<TextView android:id="@+id/main" android:layout_width="fill_parent"
-		android:layout_height="wrap_content" android:text="@string/app_name"
-		android:textStyle="bold" android:textSize="20sp" android:gravity="center" />
+	<TextView 
+		android:id="@+id/main" 
+		android:layout_width="fill_parent"
+		android:layout_height="wrap_content" 
+		android:text="@string/app_name"
+		android:textStyle="bold" 
+		android:textSize="20sp" 
+		android:gravity="center" />
 
-	<ImageView android:src="@drawable/icon" android:layout_width="fill_parent"
+	<ImageView android:src="@drawable/camel_light" 
+		android:layout_width="fill_parent"
+		android:layout_height="wrap_content"
+		android:layout_margin="10dip" 
+		android:gravity="center" />
+
+	<TextView 
+		android:layout_width="fill_parent"
 		android:layout_height="wrap_content" 
-		android:gravity="center"
-		/>
-
-	<TextView android:layout_width="fill_parent"
-		android:layout_height="wrap_content" android:text="@string/copyright"
+		android:text="@string/copyright"
 		android:gravity="center" />
 
 </LinearLayout>

res/layout/main.xml

 							    android:layout_width="fill_parent" 
 							    android:layout_height="wrap_content"
 							    android:layout_marginBottom="10dip"
+							    android:lineSpacingMultiplier="1.2"
 							    />
 						</ScrollView>
 					</LinearLayout>

res/values/strings.xml

 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-    <string name="app_name">OCaml toplevel on Android</string>
+    <string name="app_name">OCaml Toplevel for Android</string>
     <string name='copy'>Copy Text</string>
     <string name='clear'>Clear View</string>
     <string name="about">About</string>
     <string name="copy_howto">Touch &amp; drag on the text to copy</string>
-    <string name='copyright'>Copyright &#169; 2010 by Keigo IMAI\n
-Copyright &#169; 1995-2010 by INRIA\n
-The source code of this program is fully available at:\n
-http://bitbucket.org/keigoi/ocaml-toplevel-android\n
-This program includes compiled code of the Objective Caml system 3.12.\n
-The Library part is modified (see above URL for details) and the Compiler part is not modified.\n
-The license of each part is described in detail at:\n
-http://caml.inria.fr/ocaml/license.en.html\n
-The icon is from:\n
-http://animal.myds.jp/</string>
+    <string name='copyright'>Copyright &#169; 2011 Keigo IMAI\n
+Copyright &#169; 2011 Romain VERNOUX\n
+Copyright &#169; 1995-2010 by INRIA\n\n
+
+This program includes compiled code of Objective Caml 3.12.\n\n
+
+Please contact us to report bugs, ask for features or if you have any question.\n\n
+
+&lt;vernoux.romain@gmail.com&gt;\n
+&lt;Twitter/Romain360&gt;
+</string>
 </resources>

res/values/styles.xml

+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+	<style name="MyTheme" parent="@android:style/Theme.Dialog">
+		
+	</style>
+</resources>

src/jp/co/itpl/ocamlandroid/About.java

+package jp.co.itpl.ocamlandroid;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.Window;
+
+public class About extends Activity {
+
+	public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        this.requestWindowFeature(Window.FEATURE_NO_TITLE);
+        setContentView(R.layout.about);
+        
+    }
+	
+}

src/jp/co/itpl/ocamlandroid/MainActivity.java

  - Scrolling in println
  
  04/03/11
- - Tabs implementation (main.xml has been deeply changed)
+ - Tabs implementation (main.xml has been deeply modified)
 
+ 05/03/11
+ - Output layout (println has been modified)
+ 
+ 06/03/11
+ - Handling UI runtime changes.
+ - Updating the "About" screen
+ 
 */
 
 /*   TO DO
 import java.io.InputStream;
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
-import java.nio.CharBuffer;
 
 import android.app.Activity;
-import android.app.Dialog;
+import android.content.Context;
+import android.content.Intent;
 import android.os.AsyncTask;
 import android.os.Bundle;
+import android.text.Html;
 import android.util.Log;
-import android.view.KeyEvent;
 import android.view.Menu;
 import android.view.MenuItem;
-import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.OnClickListener;
+import android.view.inputmethod.InputMethodManager;
 import android.widget.Button;
 import android.widget.EditText;
 import android.widget.ScrollView;
 import android.widget.TabHost;
 import android.widget.TabHost.TabSpec;
 import android.widget.TextView;
-import android.widget.Toast;
 
 public class MainActivity extends Activity {
-	public static final int MENU_COPY = 1;
-	public static final int MENU_CLEAR = 2;
-	public static final int MENU_ABOUT = 3;
+	public static final int MENU_CLEAR = 1;
+	public static final int MENU_ABOUT = 2;
+	public static final int FROM_TOPLEVEL = 1;
+	public static final int FROM_USER = 2;
+	public static final String TOPLEVEL_START_TAG = "";
+	public static final String TOPLEVEL_END_TAG = "";
+	public static final String USER_START_TAG = "<b>";
+	public static final String USER_END_TAG = "</b>";
 	public static final String TAG = "ocaml-android";
 	
 	private TabHost tabHost;
 	private Button compile_button;
 	private Button clear_button;
 	private EditText edit;
-	private TextView outView; 
+	private static TextView outView; 
+	private static String output_text = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"; //Static makes Android resurrect it properly on configuration changes.
 	private ScrollView scrollView;
-	volatile PrintWriter out = null;
+	private PrintWriter out = null;
 	private InputStream in = null;
+	private OcamlTop toplevel = null;
+	private BackThread backThread = null;
+
 	
 	
 	
 		
 		tabHost.addTab(spec1);
 		tabHost.addTab(spec2);
+		
+		tabHost.setCurrentTab(1);
 		// TabView implementation end
 		
 		outView = (TextView) findViewById(R.id.output);
 		scrollView = (ScrollView) findViewById(R.id.scrollview);
-		
-		/* NOT ANYMORE
-		edit = (EditText)findViewById(R.id.input);
-		edit.setOnEditorActionListener(new TextView.OnEditorActionListener() {
-			public boolean onEditorAction(TextView view, int arg1, KeyEvent arg2) {
-				if(out!=null && !"".equals(view.getText().toString().trim())) {
-					String line = view.getText().toString()+"\n";
-					println(line);
-					out.println(line);
-					out.flush();
-					view.setText("");
-				}
-				return true;
-			}
-		}); 
-		edit.requestFocus();
-		*/
-		
 		edit = (EditText) findViewById(R.id.input);
 		compile_button = (Button) findViewById(R.id.compile_button);
 		clear_button = (Button) findViewById(R.id.clear_button);
 				public void onClick(View arg0) {
 					// TODO Auto-generated method stub
 					if(out!=null && !"".equals(edit.getText().toString().trim())) {
+						
+						// Hide the soft Keyboard manually
+						InputMethodManager mgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+						mgr.hideSoftInputFromWindow(edit.getWindowToken(), 0);
+						//
+						
+						tabHost.setCurrentTab(1);
 						String line = edit.getText().toString()+"\n";
-						println(line);
+						println(line, FROM_USER);
 						out.println(line);
 						out.flush();
 						
 				}
 		);
 		
+		println("",FROM_USER); // Causes the view to display the old text after a orientation change.
 		
-		new BackThread().execute(); 
+		backThread = new BackThread();
+		backThread.execute();
+					
 	}
 	
+	
+	
 	@Override
 	public void onResume() { 	
 		super.onResume();
 		IS01FullScreen.invoke();
 	}
 
-
+	@Override
+	public Object onRetainNonConfigurationInstance() {
+		return toplevel;
+	}
 	
 	
 
-	public void println(String line) { 
+	public void println(String line, int origin) { 
 		Log.d(TAG, "console output:"+line);
-		outView.setText(outView.getText().toString().concat(line));
+		if(origin == FROM_USER){
+			output_text = output_text.concat(USER_START_TAG).concat(line).concat(USER_END_TAG).replace("\n", "<br />");
+		}
+		else {
+			output_text = output_text.concat(TOPLEVEL_START_TAG).concat(line).concat(TOPLEVEL_END_TAG).replace("\n", "<br />");
+		}
+		Log.d(TAG,output_text);
+		outView.setText(Html.fromHtml(output_text));
 		scrollView.post(new Runnable() { 
 		    public void run() { 
 		        scrollView.smoothScrollTo(0, outView.getHeight()); 
 		    } 
 		}); 
-		//edit.requestFocus();
 	}
 
 	private void clear() { 
 	public boolean onCreateOptionsMenu(Menu menu) { 
 		super.onCreateOptionsMenu(menu);
 
-		menu.add(Menu.NONE, MENU_COPY, Menu.NONE, R.string.copy);
 		menu.add(Menu.NONE, MENU_CLEAR, Menu.NONE, R.string.clear);
 		menu.add(Menu.NONE, MENU_ABOUT, Menu.NONE, R.string.about).setIcon(
 				R.drawable.ic_menu_info_details);
 		return true;
 	}
 
-	private void showAboutDialog() {
-		final Dialog dialog = new Dialog(MainActivity.this) {
-			@Override
-			public boolean onTouchEvent(MotionEvent event) {
-				this.dismiss();
-				return true;
-			}
-
-		};
-		dialog.setContentView(R.layout.about);
-		dialog.show();
-	}
-
+	
 	@Override
 	public boolean onOptionsItemSelected(MenuItem item) { 
 		switch (item.getItemId()) {
-		case MENU_COPY:
-			try {
-				// simulate shift key down so that we can use webview's
-				// select-copy functionality
-				KeyEvent shiftPressEvent = new KeyEvent(0, 0,
-						KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_SHIFT_LEFT, 0, 0);
-				shiftPressEvent.dispatch(outView);
-				Toast.makeText(this, R.string.copy_howto, Toast.LENGTH_LONG).show();
-			} catch (Exception e) {
-				throw new AssertionError(e);
-			}
-			return true;
 		case MENU_CLEAR:
 			clear();
 			return true;
 		case MENU_ABOUT:
-			showAboutDialog();
+			Intent intent_about = new Intent(MainActivity.this, About.class);
+			startActivity(intent_about);
 			return true;
 		default:
 			return super.onOptionsItemSelected(item);
 	}
 	
 	private class BackThread extends AsyncTask<Void,String,Void> { // NEW
-
+				
+				
 		@Override
 		protected void onPreExecute(){
 			try {
-				OcamlTop ocaml = new OcamlTop(MainActivity.this);
-				in = ocaml.stream.getInputStream();
+				OcamlTop ocaml = (OcamlTop) getLastNonConfigurationInstance();
+				if(ocaml == null) {
+					toplevel = new OcamlTop(MainActivity.this);
+					Log.d(TAG,"New Toplevel created");
+				}
+				else {
+					toplevel = ocaml;
+					Log.d(TAG,"Old Toplevel found");
+				}
+				in = toplevel.stream.getInputStream();
 				
 				out = new PrintWriter(new OutputStreamWriter(
-						ocaml.stream.getOutputStream(), "utf-8"));
+						toplevel.stream.getOutputStream(), "utf-8"));
 			} catch (IOException e) {
 				Log.e(TAG, "error in main", e);
 			}
 										 
 				}
 			} catch (IOException e) {
-				Log.e("ocaml-android", "reading stdout/stderr error", e); //FIXME
+				Log.e(TAG, "reading stdout/stderr error", e); //FIXME
 			}
+			
 			return null;  
 		}
 			
 		@Override
 		protected void onProgressUpdate(String... strings){
-			println(strings[0]);
+			println(strings[0],FROM_TOPLEVEL);
 		}
 	}
+
 	
 }