Commits

Romain Vernoux  committed fcdf219

Code editor implementation + major bugs fixes + new logo

  • Participants
  • Parent commits 489cba4

Comments (0)

Files changed (6)

File res/drawable/icon.png

Old
Old image
New
New image

File res/layout/about.xml

 <?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+	android:layout_width="wrap_content"
+	android:layout_height="wrap_content">
+<LinearLayout 
 	android:orientation="vertical" 
 	android:layout_width="fill_parent"
 	android:layout_height="wrap_content"
 		android:textSize="20sp" 
 		android:gravity="center" />
 
-	<ImageView android:src="@drawable/camel_light" 
+	<ImageView android:src="@drawable/icon" 
 		android:layout_width="fill_parent"
 		android:layout_height="wrap_content"
 		android:layout_margin="10dip" 
 		android:gravity="center" />
 
 </LinearLayout>
+</ScrollView>

File res/layout/editpanel.xml

+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+  xmlns:android="http://schemas.android.com/apk/res/android"
+  android:layout_width="fill_parent"
+  android:layout_height="wrap_content">
+  <LinearLayout
+  	android:layout_width="fill_parent" 
+    android:layout_height="wrap_content" 
+    android:orientation="vertical"
+    android:layout_marginBottom="20dip"
+    android:layout_marginLeft="5dip"
+    android:layout_marginRight="5dip">
+  <TextView
+  	android:layout_width="wrap_content"
+  	android:layout_height="wrap_content"
+  	android:text="OCaml User Input:" />
+  <EditText
+    android:id="@+id/input"
+    android:layout_width="fill_parent" 
+    android:layout_height="wrap_content" />
+  <LinearLayout
+   	android:orientation="horizontal"
+   	android:layout_width="fill_parent"
+   	android:layout_height="wrap_content"
+   	android:gravity="right" >
+   	<Button
+	    android:id="@+id/clear_button"
+	    android:layout_width="wrap_content"
+	    android:layout_height="wrap_content" 
+	    android:text="Clear"/>
+   	<Button
+	    android:id="@+id/compile_button"
+	    android:layout_width="wrap_content"
+	    android:layout_height="wrap_content" 
+	    android:text="Compile"/>
+  </LinearLayout>
+  </LinearLayout>
+</LinearLayout>

File res/layout/main.xml

             
             
             		<!-- Tab 1 start -->
+            		<ScrollView
+					    	android:id="@+id/tab1"
+					    	android:layout_width="fill_parent" 
+						    android:layout_height="wrap_content" >	
 		            <LinearLayout 
-		            	android:id="@+id/tab1"
+		            	android:id="@+id/editPanelView"
 					    android:orientation="vertical"
 					    android:layout_width="fill_parent"
 					    android:layout_height="fill_parent">
-			            <EditText
-					    android:id="@+id/input"
-					    android:layout_width="fill_parent" 
-					    android:layout_height="wrap_content"
-					    android:gravity="top" 
-					    />
-					    <LinearLayout
-					    	android:orientation="horizontal"
-					    	android:layout_width="fill_parent"
-					    	android:layout_height="wrap_content"
-					    	android:gravity="right">
-					    	<Button
-							    android:id="@+id/clear_button"
-							    android:layout_width="wrap_content"
-							    android:layout_height="wrap_content" 
-							    android:text="Clear"/>
-					    	<Button
-							    android:id="@+id/compile_button"
-							    android:layout_width="wrap_content"
-							    android:layout_height="wrap_content" 
-							    android:text="Compile"/>
-					    </LinearLayout>
 					    
-		            </LinearLayout>
+					</LinearLayout>    
+					    
+					</ScrollView>    
+					    <!--  
+			            
+					    -->
+		         
 		            <!-- Tab 1 end -->
 		            
 		            
 					    android:layout_width="fill_parent"
 					    android:layout_height="fill_parent">
 			            <ScrollView
-							android:id="@+id/scrollview"
+							android:id="@+id/scrollview_toplevel"
 							android:layout_width="fill_parent"
 						    android:layout_height="fill_parent"
 							android:layout_marginTop="10dip"

File res/values/strings.xml

 <?xml version="1.0" encoding="utf-8"?>
 <resources>
     <string name="app_name">OCaml Toplevel for Android</string>
-    <string name='copy'>Copy Text</string>
-    <string name='clear'>Clear View</string>
+    <string name='addpanel'>Add Panel</string>
+    <string name='clear'>Clear Output</string>
     <string name="about">About</string>
-    <string name="copy_howto">Touch &amp; drag on the text to copy</string>
+    <string name="clear_toast">Output cleared by user</string>
     <string name='copyright'>Copyright &#169; 2011 Keigo IMAI\n
 Copyright &#169; 2011 Romain VERNOUX\n
-Copyright &#169; 1995-2010 by INRIA\n\n
+Copyright &#169; 1995-2011 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;
+&lt;Twitter.com/Romain360&gt;
 </string>
 </resources>

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

  
  06/03/11
  - Handling UI runtime changes.
- - Updating the "About" screen
+ - Updating the "About" screen.
  
+ 07/03/11
+ - EditPanel system
+ - Orientation change bug fixed
+ - Logo
 */
 
 /*   TO DO
  
- - Cleaning
- - Orientation Changes are crashing the app (we have to keep the Backthread alive during such process) 
- - Fix the Copy Function
+ - Clean the mess
+ - Menu icons
+ - Copy to clipboard function
 
 */
 
  Compile button 
  	-> Is the toplevel "compiling" or "executing" ? I'm not sure.
  
- Copy Function
- 	-> Is it still useful ?
  */
 
 
 import android.os.Bundle;
 import android.text.Html;
 import android.util.Log;
+import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.Button;
 import android.widget.EditText;
+import android.widget.LinearLayout;
 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_ADDPANEL = 0;
 	public static final int MENU_CLEAR = 1;
 	public static final int MENU_ABOUT = 2;
 	public static final int FROM_TOPLEVEL = 1;
 	public static final String TAG = "ocaml-android";
 	
 	private TabHost tabHost;
-	private Button compile_button;
-	private Button clear_button;
-	private EditText edit;
 	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;
+	private static String output_text = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"; //Static is to avoid painful java stuff on orientation changes
+	private ScrollView scrollView_toplevel;
+	private ScrollView scrollView_editor;
 	private PrintWriter out = null;
 	private InputStream in = null;
 	private OcamlTop toplevel = null;
 	private BackThread backThread = null;
+	private LinearLayout editPanelView = null;
+	private int editPanel_number;
 
 	
 	
 		super.onCreate(savedInstanceState);
 		setContentView(R.layout.main);
 		
-		// TabView implementation start
+		
 		tabHost=(TabHost)findViewById(R.id.tabhost);
 		tabHost.setup();
-
 		TabSpec spec1=tabHost.newTabSpec("Tab 1");
 		spec1.setIndicator("Code Editor",getResources().getDrawable(R.drawable.ide_tab));
 		spec1.setContent(R.id.tab1);
-		
 		TabSpec spec2=tabHost.newTabSpec("Tab 2");
 		spec2.setIndicator("OCaml Toplevel",getResources().getDrawable(R.drawable.toplevel_tab));
 		spec2.setContent(R.id.tab2);
-		
 		tabHost.addTab(spec1);
 		tabHost.addTab(spec2);
-		
 		tabHost.setCurrentTab(1);
-		// TabView implementation end
 		
 		outView = (TextView) findViewById(R.id.output);
-		scrollView = (ScrollView) findViewById(R.id.scrollview);
-		edit = (EditText) findViewById(R.id.input);
-		compile_button = (Button) findViewById(R.id.compile_button);
-		clear_button = (Button) findViewById(R.id.clear_button);
+		scrollView_toplevel = (ScrollView) findViewById(R.id.scrollview_toplevel);
+		scrollView_editor = (ScrollView) findViewById(R.id.tab1);
+		editPanelView = (LinearLayout) findViewById(R.id.editPanelView);
+		editPanel_number = 1;
+		
+		Object[] tab = (Object[]) getLastNonConfigurationInstance();
+		if (tab == null){ // The application has just been launched by the user
+			addEditPanel();
+		}
+		else { // The application just resumed from an orientation change
+			for (int k = 1; k < tab.length-1; k++){
+				addEditPanel();
+				((EditText) findViewById(10*k)).setText((String)tab[k]);
+			}
+			tabHost.setCurrentTab((Integer) tab[tab.length-1]);
+		}
+		
+		
+		
+		println("",FROM_USER); // Causes the view to display the old text after a orientation change.
+		
+		backThread = new BackThread();
+		backThread.execute();
+					
+	}
+	
+	
+	
+	@Override
+	public void onResume() { 	
+		super.onResume();
+		IS01FullScreen.invoke();
+	}
+
+	@Override
+	public Object onRetainNonConfigurationInstance() {
+		// We will save 3 things for the next instance : the current toplevel, the texts in the editPanels and the current tab.
+		Object[] tab = new Object[editPanel_number+1];
+		tab[0] = toplevel;
+		for(int k = 1; k <= tab.length-2; k++){
+			tab[k] = ((EditText) findViewById(10*k)).getText().toString();
+		}
+		tab[tab.length-1] = tabHost.getCurrentTab();
+		return tab;
+	}
+	
+	public void addEditPanel() {
+		LayoutInflater vi = (LayoutInflater) MainActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+		LinearLayout layout = (LinearLayout) vi.inflate(R.layout.editpanel, null);
+		
+		
+		EditText edit = (EditText) layout.findViewById(R.id.input);
+		Button compile_button = (Button) layout.findViewById(R.id.compile_button);
+		Button clear_button = (Button) layout.findViewById(R.id.clear_button);
+		edit.setId(10*editPanel_number+0);
+		compile_button.setId(10*editPanel_number+1);
+		clear_button.setId(10*editPanel_number+2);
+		// For instance, the compile_button in the third editPanel has ID = 3*10+1 = 21 where 3 stands for "third panel" and "1" for "compile_button".
+		
 		
 		
 		compile_button.setOnClickListener(
 				@Override
 				public void onClick(View arg0) {
 					// TODO Auto-generated method stub
-					if(out!=null && !"".equals(edit.getText().toString().trim())) {
+					if(out!=null && !"".equals(((EditText) findViewById(arg0.getId()-1)).getText().toString().trim())) {
 						
 						// Hide the soft Keyboard manually
 						InputMethodManager mgr = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
-						mgr.hideSoftInputFromWindow(edit.getWindowToken(), 0);
+						mgr.hideSoftInputFromWindow(((EditText) findViewById(arg0.getId()-1)).getWindowToken(), 0);
 						//
 						
 						tabHost.setCurrentTab(1);
-						String line = edit.getText().toString()+"\n";
+						String line = ((EditText) findViewById(arg0.getId()-1)).getText().toString()+"\n";
 						println(line, FROM_USER);
 						out.println(line);
 						out.flush();
 					@Override
 					public void onClick(View arg0) {
 						// TODO Auto-generated method stub
-						edit.setText("");
+						((EditText) findViewById(arg0.getId()-2)).setText("");
 					}
 					
 				}
 		);
 		
-		println("",FROM_USER); // Causes the view to display the old text after a orientation change.
+		tabHost.setCurrentTab(0);
+		editPanelView.addView(layout);
+		scrollView_editor.post(new Runnable() { 
+		    public void run() { 
+		        scrollView_editor.smoothScrollTo(0, editPanelView.getHeight()); 
+		    } 
+		}); 
 		
-		backThread = new BackThread();
-		backThread.execute();
-					
+		edit.requestFocus();
+		editPanel_number ++;
 	}
 	
-	
-	
-	@Override
-	public void onResume() { 	
-		super.onResume();
-		IS01FullScreen.invoke();
-	}
-
-	@Override
-	public Object onRetainNonConfigurationInstance() {
-		return toplevel;
-	}
-	
-	
 
 	public void println(String line, int origin) { 
 		Log.d(TAG, "console output:"+line);
 		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() { 
+		scrollView_toplevel.post(new Runnable() { 
 		    public void run() { 
-		        scrollView.smoothScrollTo(0, outView.getHeight()); 
+		        scrollView_toplevel.smoothScrollTo(0, outView.getHeight()); 
 		    } 
 		}); 
 	}
 
 	private void clear() { 
 		Log.d(TAG, "console clear");
-		outView.setText("");
+		output_text = "";
+		println("# ", FROM_TOPLEVEL);
+		Toast.makeText(MainActivity.this, R.string.clear_toast, Toast.LENGTH_SHORT).show();
 	}
 	
 	@Override
 	public boolean onCreateOptionsMenu(Menu menu) { 
 		super.onCreateOptionsMenu(menu);
-
+		
+		menu.add(Menu.NONE, MENU_ADDPANEL, Menu.NONE, R.string.addpanel);
 		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);
+		menu.add(Menu.NONE, MENU_ABOUT, Menu.NONE, R.string.about)
+		    .setIcon(android.R.drawable.ic_menu_info_details);
+		
 		return true;
 	}
 
 	@Override
 	public boolean onOptionsItemSelected(MenuItem item) { 
 		switch (item.getItemId()) {
+		case MENU_ADDPANEL:
+			addEditPanel();
+			return true;
 		case MENU_CLEAR:
 			clear();
 			return true;
 		@Override
 		protected void onPreExecute(){
 			try {
-				OcamlTop ocaml = (OcamlTop) getLastNonConfigurationInstance();
-				if(ocaml == null) {
+				Object[] tab = (Object[]) getLastNonConfigurationInstance();
+				if(tab == null) {
 					toplevel = new OcamlTop(MainActivity.this);
 					Log.d(TAG,"New Toplevel created");
 				}
 				else {
-					toplevel = ocaml;
+					toplevel = (OcamlTop) tab[0];
 					Log.d(TAG,"Old Toplevel found");
 				}
 				in = toplevel.stream.getInputStream();