view src/uk/ac/qmul/eecs/ccmi/activities/CcmiEditorAppActivity.java @ 1:66b3a838feca logging tip

Added logging of user interaction
author Fiore Martin <fiore@eecs.qmul.ac.uk>
date Tue, 12 Feb 2013 15:31:48 +0000
parents e0ee6ac3a45f
children
line wrap: on
line source
/*  
 CCmI Diagram Editor for Android 
  
 Copyright (C) 2012  Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)

 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package uk.ac.qmul.eecs.ccmi.activities;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;

import uk.ac.qmul.eecs.ccmi.accessibility.AccessibilityService;
import uk.ac.qmul.eecs.ccmi.accessibility.AccessibilityService.SoundEvent;
import uk.ac.qmul.eecs.ccmi.accessibility.AccessibleDialogBuilder;
import uk.ac.qmul.eecs.ccmi.utilities.ILogger;
import uk.ac.qmul.eecs.ccmi.xmlparser.Diagram;
import android.content.Intent;
import android.content.res.AssetManager;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.TextView;

/**
 * 
 * The main activity. It displays the diagram through the hierarchical view 
 * of the <a href="http://ccmi.eecs.qmul.ac.uk"> CCmI Diagram Editor </a>      
 *
 */
public class CcmiEditorAppActivity extends AccessibleActivity implements 
		OnItemClickListener, OnItemLongClickListener, TreeNavigation.Updateable {
	private final static int OPEN_REQUEST = 1;
	private final static int SAVE_REQUEST = 2;
	private final static String CCMI_EXTENSION = ".ccmi";
	
	private Diagram diagram;
	private TreeNavigation navigation; 
	
	private String file;
	private InputStream in;
	
	public String getName(){
		return "";
	}
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
        
		list.setOnItemClickListener(this);
		list.setOnItemLongClickListener(this);
		

		ILogger.log("--- APPLICATION STARTED ---");
		
		
		/* init assets */
		AssetManager assetManager = getAssets();
		try {
			file = assetManager.list("diagrams")[0];
			in = assetManager.open("diagrams/"+file);
			readXML(in);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	/* create a new list and display it */
	@Override
	public void update(){
		/* header */
		setHeaderText(navigation.getCurrentItemName());
		/* list */
		ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.list_item_1,navigation.getCurrentChildList());
		list.setAdapter(adapter);
	}
	
	/*----- listeners to implement the navigation ----*/
	@Override
	public void onItemClick(AdapterView<?> av, View v, int pos, long id) {
		ILogger.logTap(((TextView)v).getText());
		if(!navigation.goNext(pos)){
			accessibilityService.playSound(AccessibilityService.SoundEvent.V_ERROR);
			ILogger.logError("end of tree");
			return;
		}
		accessibilityService.playSound(AccessibilityService.SoundEvent.V_EXPAND);
		accessibilityService.speak("displaying " + getHeaderText());
		ILogger.logActivity(getHeaderText());
	}
	
	/**
	 * The activity listens to long clicks performed on the list view.
	 * 
	 * When a user long clicks an item, a dialog is displayed accordingly. For example if the types of nodes and 
	 * edges are listed when the user long clicks, then a dialog for insertion of a new node or edge is displayed.    
	 */
	@Override
	public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
		ILogger.logLongTap(((TextView)view).getText());
		boolean doneSomething = navigation.getController().performEditAction(parent, view, position, id, this);
		if(!doneSomething){
			accessibilityService.playSound(AccessibilityService.SoundEvent.V_ERROR);
			ILogger.logError("no action available on this item");
		}
		return doneSomething;
	}

	/**
	 * When the back button is pressed the activity will cursor back in the tree 
	 * view, which means the parent of the currently displayed items will be displayed
	 * together with its siblings. 
	 */
	@Override
	public void onBackPressed() {
		ILogger.logTap("back");
		if(navigation.goPrevious()){
			accessibilityService.playSound(SoundEvent.V_COLLAPSE);
			accessibilityService.speak("Displaying "+getHeaderText());
			ILogger.logActivity(getHeaderText());
			update();
		}else{
			accessibilityService.playSound(SoundEvent.V_EDITING_MODE, true);
			dialogBuilder.displayDialog(R.layout.alert_dialog_confirm_exit,"Exit Dialog",new AccessibleDialogBuilder.ButtonClickListener() {
				@Override
				public void onClick(View v, DialogFragment dialogFragment, String tag) {
					if("EXIT".equals(v.getTag())){
						ILogger.logButton("exit");
						accessibilityService.speak(getResources().getString(R.string.exitMessage));
						ILogger.log("--- EXIT ---");
						ILogger.dispose();
						finish();
					}else if("CANCEL".equals(v.getTag())){
						ILogger.logButton("cancel");
						accessibilityService.playSound(SoundEvent.V_CANCEL);
						accessibilityService.speak("Cancel");
						accessibilityService.stopSound();
						dialogFragment.dismiss();
					}else if("OPEN".equals(v.getTag())){
						ILogger.logButton("open");
						/* start the activity to open a file */
						Intent intent = new Intent(CcmiEditorAppActivity.this, FileSelectorActivity.Open.class);
						intent.putExtra("extension", CCMI_EXTENSION);
						startActivityForResult(intent,OPEN_REQUEST);
						dialogFragment.dismiss();
					}else if("SAVE".equals(v.getTag())){
						ILogger.logButton("save");
						Intent intent = new Intent(CcmiEditorAppActivity.this, FileSelectorActivity.Save.class);
						intent.putExtra("extension", CCMI_EXTENSION);
						startActivityForResult(intent,SAVE_REQUEST);
						dialogFragment.dismiss();
					}
				}
			});
		}
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if(resultCode == RESULT_OK){
			if(requestCode == OPEN_REQUEST){			
				try {
					InputStream in = new FileInputStream(new File(data.getData().getPath()));
					readXML(in);
					ILogger.logActivity(navigation.getCurrentPath());
				} catch (Exception e) {
					accessibilityService.playSound(SoundEvent.V_ERROR);
					accessibilityService.speak("File could not be open");
				} 
			}else if(requestCode == SAVE_REQUEST){
				try {
					String filePath = data.getData().getPath();
					String diagramName = data.getData().getLastPathSegment();
					/* make sure the extension is .ccmi */
					if(!filePath.endsWith(CCMI_EXTENSION)||(CCMI_EXTENSION.equals(diagramName)))
						filePath += CCMI_EXTENSION;
					
					/* make sure diagram name doesn't have trailing .ccmi, unless the name is just ".ccmi" */
					if(diagramName.endsWith(CCMI_EXTENSION) && !(CCMI_EXTENSION.equals(diagramName))){
						diagramName = diagramName.substring(0, diagramName.length()-CCMI_EXTENSION.length());
					}
					
					diagram.setName(diagramName);
					OutputStream out = new FileOutputStream(new File(filePath));
					saveXML(out);
				} catch (Exception e) {
					accessibilityService.playSound(SoundEvent.V_ERROR);
					accessibilityService.speak("File could not be saved");
				}
			}
		}
	}

	private void saveXML(OutputStream out) throws Exception  {
		Serializer serializer = new Persister();
		serializer.write(diagram, out);
		out.close();
		navigation = new TreeNavigation(diagram,dialogBuilder,this);
		update();
		accessibilityService.playSound(SoundEvent.V_OK);
		accessibilityService.speak("Filed saved");				
	}
	
	private void readXML(InputStream in) throws Exception {
		Serializer serializer = new Persister();
		diagram = serializer.read(Diagram.class, in);
		in.close();
		navigation = new TreeNavigation(diagram,dialogBuilder,this);
		update();
	}
}