/*
* File: TICO.java
* This file is part of Tico, an application to create and perform
* interactive communication boards to be used by people with
* severe motor disabilities.
*
* Author: Eduardo Ferrer
*
* Date: Nov, 2011
*
* Company: Dept. of Computer Sciences and Systems Engineering, Universidad de Zaragoza, Spain
*
*
* License:
* 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 .
*/
package android.TICO;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Display;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.Window;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.HorizontalScrollView;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import java.io.File;
import java.io.IOException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Element;
//import org.xml.sax.SAXException;
import configuration.SetupScreen;
import configuration.TSetup;
import android.graphics.Color;
//import android.graphics.Rect;
//import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.GradientDrawable;
import android.TICO.AsyncTasks.playSentence;
import android.TICO.AsyncTasks.playSound;
import android.TICO.Views.*;
/**
* The class that defines the main activity of Tico Interpreter.
*/
public class TICO extends Activity {
/** Called when the activity is first created. */
int LayoutVisible=0;
int initialBoard=0;
String fileName;
String url;
File root=Environment.getExternalStorageDirectory();
int tableroAnterior=-1;
//objeto gestor de las celdas acumuladas
accumulated_cells accumulated;
RelativeLayout layPGeneral;
RelativeLayout layPLandscape;
LinearLayout ticoLayout;
control_area/*RelativeLayout*/ controlLayout;
control_area /*RelativeLayout*/ controlLayoutLandscape;
NodeList boards;
NodeList boardsLandscape;
//tamanyos de las distintas partes que conforman la pantalla portrait
RelativeLayout.LayoutParams panelSize;
RelativeLayout.LayoutParams accumulatedSize;
RelativeLayout.LayoutParams controlSize;
//tamanyos en Landscape
RelativeLayout.LayoutParams panelSizeLandscape;
RelativeLayout.LayoutParams accumulatedSizeLandscape;
RelativeLayout.LayoutParams controlSizeLandscape;
//celdas de control
/* private cell inicio;
private cell inicioLandscape;
private cell volver;
private cell volverLandscape;
private cell leer;
private cell leerLandscape;
private cell borrar1;
private cell borrar1Landscape;
private cell borrarTodas;
private cell borrarTodasLandscape;*/
//datos de la pantalla del dispositivo
Display displayActual;
DisplayMetrics metrics;
protected PowerManager.WakeLock wakelock;
PowerManager pm;
//tareas asincronas
playSound reproductorSonido=null;
playSentence reproductorFrase=null;
automaticScan barredor;
int[] vectorOrderedCells;
textArea[] vectorTextAreas;
AlertDialog alertPrincipal;
//recursos pasados en el xml config.xml, publico y estatico para el acceso general
public static Resources res;
//para escaneo automatico la vista (celda) que esta seleccionada en este momento
int vistaActual;
HorizontalScrollView scroll;
HorizontalScrollView scrollLandscape;
private Intent intent;
private boolean backEnabled=true;
private long backEventTime=0;
//codigos de tipo int para opciones e intents
private static final int SETUP=123;
private static final int VIDEO=223;
private static final int ABRIR=0;
private static final int CONFIGURACION=1;
private static final int ACCIONES=2;
private static final int READ=3;
private static final int REMOVE_CELL=4;
private static final int REMOVE_ALL_CELLS=5;
private static final int AYUDA=6;
private static final int EXIT=7;
private static final int BACK=8;
private static final int HOME=9;
private static final int RESOLUTIONS=10;
//cuando dejamos en segundo plano la pantalla se podrá apagar automaticamente
protected void onResume(){
super.onResume();
if(!wakelock.isHeld()) this.wakelock.acquire();
}
public void onSaveInstanceState(Bundle icicle) {
super.onSaveInstanceState(icicle);
if(wakelock.isHeld()) this.wakelock.release();
}
/**
* Change the orientation of interpreter
* when the orientation of the device changes if it's necessary.
*/
@Override
public void onConfigurationChanged(Configuration newConfig) {
//paramos el barrido automatico si esta activado
if(barredor!=null){
barredor.cancel(true);
barredor=null;
}
super.onConfigurationChanged(newConfig);
if(controlLayout!=null && LayoutVisible>=0){ //ya tenemos creado un proyecto
displayActual.getMetrics(metrics);
if(metrics.heightPixels>metrics.widthPixels){
//cambiamos a Portrait
//ponemos todas las celdas de control que vamos a mostrar a su imagen principal
for(int i=0;i<5;i++){
((cell)controlLayout.getChildAt(i)).showMainCell();
}
ticoLayout.removeAllViews();
ticoLayout.addView(scroll);
ticoLayout.addView(layPGeneral);
ticoLayout.addView(controlLayout);
try {
if(boards.getLength()>0)
MostrarPanel(layPGeneral,boards,accumulated,LayoutVisible);
else //solo se ha definido tableros en landscape y cargamos de ahi
MostrarPanel(layPGeneral,boardsLandscape,accumulated,LayoutVisible);
} catch (OutOfMemoryError e) {
// TODO Auto-generated catch block
outOfMemoryRecover();
e.printStackTrace();
//reactivamos los botones
listenersOn();
}catch(NullPointerException e){
readErrorRecover();
//reactivamos los botones
listenersOn();
}
catch(Exception e){
readErrorRecover();
//reactivamos los botones
listenersOn();
}
}
else{
//cambiamos a Landscape
//ponemos todas las celdas de control a su imagen principal
for(int i=0;i<5;i++){
((cell)controlLayoutLandscape.getChildAt(i)).showMainCell();
}
ticoLayout.removeAllViews();
ticoLayout.addView(scrollLandscape);
ticoLayout.addView(layPLandscape);
ticoLayout.addView(controlLayoutLandscape);
try {
if(boardsLandscape.getLength()>0)
MostrarPanel(layPLandscape,boardsLandscape,accumulated,LayoutVisible);
else //solo se han definido los tableros en portrait
MostrarPanel(layPLandscape,boards,accumulated,LayoutVisible);
} catch (OutOfMemoryError e) {
// TODO Auto-generated catch block
outOfMemoryRecover();
e.printStackTrace();
//reactivamos los botones
listenersOn();
}catch(NullPointerException e){
readErrorRecover();
//reactivamos los botones
listenersOn();
}
catch(Exception e){
readErrorRecover();
//reactivamos los botones
listenersOn();
}
}
}
}
/**************************************************************************************************************************************/
/**
* Redefine the behavior of the back button
* for back in the boards
*/
//reescribimos el uso del back button
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0 && !event.isLongPress()) {
if(event.getEventTime()>backEventTime){
if(accumulated!=null && backEnabled){
if(metrics.heightPixels>metrics.widthPixels){//portrait
if(controlLayout!=null) controlLayout.volver().performClick();//if(controlLayout.volver()!=null) controlLayout.volver().performClick();
}else{//landscape
if(controlLayoutLandscape!=null) controlLayoutLandscape.volver().performClick();//if(volverLandscape!=null) volverLandscape.performClick();
}
}
backEventTime=SystemClock.uptimeMillis();
}
return true;
}
if(keyCode==KeyEvent.KEYCODE_BACK) return true;
return super.onKeyDown(keyCode, event);
}
/**********************************************************************************************************************************/
/**
* onCreate behavior of the main activity of
* the interpreter.
* It calls to the activity fileDialog for
* select the .tcoa file.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//quitar barra de titulo
requestWindowFeature(Window.FEATURE_NO_TITLE);
//quitar barra de estado (bateria, hora...)
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
//configurar los botones fisicos de sonido al audio multimedia
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
res=getResources();//<-----una sola vez
alertPrincipal=new AlertDialog.Builder(this).create();//creamos ya el dialogo de error al que llamaremos en caso
//de encontrar alguno (sin inicializar mensajes)
//bloqueamos el brillo de pantalla para que no se apague
pm=(PowerManager)getSystemService(Context.POWER_SERVICE);
this.wakelock=pm.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK, "bloqueoBrillo");
this.wakelock.acquire();
setLayoutSizes();
try {
TSetup.load(getApplicationContext()); //leemos el archivo de configuracion tico.conf, en caso de error lo creamos
} catch (ParserConfigurationException e) {
TSetup.createInitialConfig(getApplicationContext());
} catch (IOException e) {
// TODO Auto-generated catch block
TSetup.createInitialConfig(getApplicationContext());
} catch (Exception e) {
// TODO Auto-generated catch block
TSetup.createInitialConfig(getApplicationContext());
}
//llamamos a fileDialog
intent=new Intent(TICO.this,fileDialog.class);
startActivityForResult(intent,1);
setContentView(R.layout.main);
}
/**************************************************************************************************************************************/
/**
* Redefine the behavior of the onActivityResult
* for the results of activities fileDialog,
* SetupScreen and videoPlayer.
* @param requestCode The integer request code originally supplied to startActivityForResult(), allowing you to identify who this result came from.
* @param resultCode The integer result code returned by the child activity through its setResult().
* @param data An Intent, which can return result data to the caller (various data can be attached to Intent "extras").
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch(requestCode) {
case (1) : {
//Todo correcto
if (resultCode == Activity.RESULT_OK) {
LayoutVisible=-1;
setContentView(R.layout.loading);
//recuperamos el fichero con el proyecto de la activity fileDialog
url = data.getStringExtra("fichero");
new loadingProject().execute();
}else{
refresh();
}
break;
}
case(SETUP) :
refresh();
break;
case(VIDEO) :
refresh();
break;
}
}
/******************************************************************************************************************************************/
/**
* Shows the correct board on the screen
* @param layP The RelativeLayout
where we load the board.
* @param boards The NodeList
with all the boards definition.
* @param accumulated The accumulated_cells
where we accumulate the sentence.
* @param i The int that identificates the board to show.
*/
public void MostrarPanel(final RelativeLayout layP,final NodeList boards, final accumulated_cells accumulated, int i)
throws OutOfMemoryError,NullPointerException,Exception{
//para evitar clicks compulsivos desactivamos los botones mientras cargamos el panel
listenersOff();
//paramos, si existe, el barrido del anterior tablero
if(barredor!=null){
barredor.cancel(true);
barredor=null;
for(int cont=0;cont<5;cont++){
((cell)controlLayout.getChildAt(cont)).showMainCell();
((cell)controlLayoutLandscape.getChildAt(cont)).showMainCell();
}
}
layP.removeAllViews();
System.gc();//garbage collector
Node board=boards.item(i);
NodeList orderedCells=null;
NodeList modelList = ((Element)board).getElementsByTagName("model");
Element model = (Element)modelList.item(0);
NodeList attributesList = model.getElementsByTagName("attributes");
Element attributes = (Element)attributesList.item(0);
NodeList attributeBoard = attributes.getChildNodes();
float panelHeight=100;
float panelWidth=100;
int resizeStyle=1;
String imagePanelURL=null;
int backgroundColorP=res.getColor(R.color.background_default_color);
int gradientP=Color.TRANSPARENT;
for(int ii=0;ii=0){
cellView.setAlternateFrameSize(frameAlternateSize);
}
if(soundURL!=null){
cellView.setSound(soundURL);
}
if(videoURL!=null){
cellView.setVideo(videoURL);
}
if(orderedCells!=null){
int cont=0;
while(cont< orderedCells.getLength() && !((Element)orderedCells.item(cont)).getTextContent().equals(id) ){
cont++;
}
if(contpreviousLength){
accumulated.accumulatedCells.removeViewAt(previousLength);
}
if(accumulated.accumulatedCellsLandscape.getChildCount()>previousLength){
accumulated.accumulatedCellsLandscape.removeViewAt(previousLength);
}
accumulated.imagesVector[previousLength]=null;
accumulated.imagesVectorLandscape[previousLength]=null;
accumulated.soundsVector[previousLength]=null;
accumulated.length=previousLength;
System.gc();//garbage collector
//MENSAJE
alertPrincipal.setTitle(res.getString(R.string.error));
alertPrincipal.setMessage("Problema de memoria al acumular celda.\nNo se ha podido acumular\nPruebe a tener menos celdas en el panel o poner imagenes menos pesadas");
alertPrincipal.setButton(res.getString(R.string.accept),new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
alertPrincipal.show();
e.printStackTrace();
}
}
//reproduccion de sonido
if(cellView.getSound()!=null){
if(reproductorFrase!=null){
reproductorFrase.cancel(true);
reproductorFrase=null;
}
reproductorSonido=new playSound();
reproductorSonido.execute(cellView.getSound());
}
//reproduccion de video
if(cellView.getVideo()!=null){
intent=new Intent(getApplicationContext(),videoPlayer.class);
intent.putExtra("ruta",cellView.getVideo());
startActivityForResult(intent,VIDEO);
//paramos el barrido progresivo si esta activado
if(barredor!=null){
barredor.cancel(true);
barredor=null;
for(int cont=0;cont<5;cont++){
((cell)controlLayout.getChildAt(cont)).showMainCell();
((cell)controlLayoutLandscape.getChildAt(cont)).showMainCell();
}
}
}
//si navega entre distintos tableros
if(cellView.getDestiny()>=0){
tableroAnterior=LayoutVisible;
LayoutVisible=cellView.getDestiny();
try {
MostrarPanel(layP,boards,accumulated, LayoutVisible);
} catch (OutOfMemoryError e) {
outOfMemoryRecover();
e.printStackTrace();
//reactivamos los botones
listenersOn();
}catch(NullPointerException e){
readErrorRecover();
//reactivamos los botones
listenersOn();
}
catch(Exception e){
readErrorRecover();
//reactivamos los botones
listenersOn();
}
}
}
});
layP.addView(cellView);
if(ordenCelda>=0){
vectorOrderedCells[ordenCelda]=layP.indexOfChild(cellView);
}
}
//celda de control
if(componentType.equals("controllerCell")){
int action=0;
Element attributesLabel = (Element)component.getElementsByTagName("attributes").item(0);
NodeList attributesLabelList = attributesLabel.getElementsByTagName("attribute");
for(int jj=0;jj=0){
cellView.setAlternateFrameSize(frameAlternateSize);
}
if(soundAlternateURL!=null){
cellView.setSoundAlternate(soundAlternateURL);
}
if(orderedCells!=null){
int cont=0;
while(cont< orderedCells.getLength() && !((Element)orderedCells.item(cont)).getTextContent().equals(id) ){
cont++;
}
if(contmetrics.widthPixels){
controlLayout.leer().performClick();
}else{
controlLayoutLandscape.leer().performClick();//leerLandscape.performClick();
}
}
}else if (cellView.getDestiny() == 5){//Volver
if(accumulated!=null){
if(metrics.heightPixels>metrics.widthPixels){
controlLayout.volver().performClick();//volver.performClick();
}else{
controlLayoutLandscape.volver().performClick();//volverLandscape.performClick();
}
}
}else if (cellView.getDestiny() == 7){//Volver
if(accumulated!=null){
if(metrics.heightPixels>metrics.widthPixels){
controlLayout.inicio().performClick();//inicio.performClick();
}else{
controlLayoutLandscape.inicio().performClick();//inicioLandscape.performClick();
}
}
}
}
});
layP.addView(cellView);
if(ordenCelda>=0){
vectorOrderedCells[ordenCelda]=layP.indexOfChild(cellView);
}
}
//etiqueta
else if(componentType.equals("label")){
Element attributesLabel = (Element)component.getElementsByTagName("attributes").item(0);
NodeList attributesLabelList = attributesLabel.getElementsByTagName("attribute");
for(int jj=0;jj=-5){ //si no barremos celdas de control
if(metrics.heightPixels>metrics.widthPixels){//esta en portrait
controlLayout.getChildAt(vistaActual+5).performClick();
}
else{//esta en landscape
controlLayoutLandscape.getChildAt(vistaActual+5).performClick();
}
}
}
else if((vistaActual=0)){
layP.getChildAt(vectorOrderedCells[vistaActual]).performClick();
}
//}
}
});
//iniciamos el barrido
barredor=new automaticScan();
barredor.execute(layP);
}
//reactivamos los botones
listenersOn();
}
/***************************************************************************************************************************************************/
/**
* AsyncTask for unzip and loading of the .tcoa file
*
* The result Element contains the xml structure of the .tcoa file
*/
private class loadingProject extends AsyncTask {
protected Element doInBackground(Void... urls) {
try{
//paramos el barredor si esta en marcha
if(barredor!=null){
barredor.cancel(true);
barredor=null;
}
//liberamos la memoria de imagenes
layPGeneral=null;
layPLandscape=null;
controlLayout=null;
controlLayoutLandscape=null;
accumulated=null;
System.gc();
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder= factory.newDocumentBuilder();
File filezip = new File(url);
File tempDirectory=new File(root+"/TMPtico");
tempDirectory.mkdir();
readProject.loadZip(filezip, tempDirectory);
File file=new File(tempDirectory + "/project.xml");
//Layout de la pantalla completa
ticoLayout=new LinearLayout(getApplicationContext());
ticoLayout.setOrientation(LinearLayout.VERTICAL);
//anyadimos imagenes de control
controlLayout=new control_area(getApplicationContext(),controlSize);
/* controlLayout=new RelativeLayout(getApplicationContext());
controlLayout.setLayoutParams(controlSize);
controlLayout.setBackgroundColor(res.getColor(R.color.bars_background_color));
*/
controlLayoutLandscape=new control_area(getApplicationContext(),controlSizeLandscape);
/* controlLayoutLandscape=new RelativeLayout(getApplicationContext());
controlLayoutLandscape.setLayoutParams(controlSizeLandscape);
controlLayoutLandscape.setBackgroundColor(res.getColor(R.color.bars_background_color));
*/
//Layout de las celdas acumuladas portrait
RelativeLayout accumulatedCells=new RelativeLayout(getApplicationContext());
accumulatedCells.setLayoutParams(accumulatedSize);
accumulatedCells.setBackgroundColor(res.getColor(R.color.bars_background_color));
scroll=new HorizontalScrollView(getApplicationContext());
scroll.setLayoutParams(accumulatedSize);
scroll.addView(accumulatedCells);
//Layout de las celdas acumuladas Landscape
RelativeLayout accumulatedCellsLandscape=new RelativeLayout(getApplicationContext());
accumulatedCellsLandscape.setLayoutParams(accumulatedSizeLandscape);
accumulatedCellsLandscape.setBackgroundColor(res.getColor(R.color.bars_background_color));
scrollLandscape=new HorizontalScrollView(getApplicationContext());
scrollLandscape.setLayoutParams(accumulatedSizeLandscape);
scrollLandscape.addView(accumulatedCellsLandscape);
//objeto gestor de las celdas acumuladas
accumulated=new accumulated_cells(accumulatedCells,accumulatedCellsLandscape);
accumulatedCells.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//reproduccion de sonido de la frase
if(reproductorSonido!=null){ //cancelamos reproduccion de sonido
reproductorSonido.cancel(true);
reproductorSonido=null;
}
if(reproductorFrase!=null){ //cancelamos reproduccion de frase anterior
reproductorFrase.cancel(true);
reproductorFrase=null;
}
reproductorFrase=new playSentence();
reproductorFrase.execute(accumulated);//reproductorFrase.execute();
}
});
//listener de las celdas acumuladas en landscape
accumulated.accumulatedCellsLandscape.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
//reproduccion de sonido de la frase acumulada
if(reproductorSonido!=null){//cancelamos reproduccion de sonido
reproductorSonido.cancel(true);
reproductorSonido=null;
}
if(reproductorFrase!=null){ //cancelamos reproduccion de frase anterior
reproductorFrase.cancel(true);
reproductorFrase=null;
}
reproductorFrase=new playSentence();
reproductorFrase.execute(accumulated);//reproductorFrase.execute();
}
});
//Leemos el xml con el proyecto
Document doc = builder.parse(file);
Element raiz=doc.getDocumentElement();
return raiz;
}catch(Exception E){
//si hay excepcion devolvemos null
return null;
}
}
@Override
protected void onPostExecute(Element raiz) {
if(raiz==null){ //fallo al leer el proyecto
setContentView(R.layout.main);
layPGeneral=null;
layPLandscape=null;
controlLayout=null;
controlLayoutLandscape=null;
accumulated=null;
alertPrincipal.setTitle(res.getString(R.string.error));
alertPrincipal.setMessage(res.getString(R.string.format_error));
alertPrincipal.setButton(res.getString(R.string.accept),new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
alertPrincipal.show();
}
else{//lectura correcta hasta ahora
NamedNodeMap raizatr=raiz.getAttributes();
if(raizatr.getNamedItem("orientation") != null){
if(raizatr.getNamedItem("orientation").getNodeValue().equals("portrait")){
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}else{ //equals("landscape")
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
}else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
boards = raiz.getElementsByTagName("board");
boardsLandscape = raiz.getElementsByTagName("boardLandscape");
//detectar panel inicial
try{
if(boards!=null){
LayoutVisible=0;
while(LayoutVisible=boards.getLength()) LayoutVisible=0;
initialBoard=LayoutVisible;
}else{
LayoutVisible=0;
while(LayoutVisible=boardsLandscape.getLength()) LayoutVisible=0;
initialBoard=LayoutVisible;
}
}catch(Exception e){
readErrorRecover();
return;
}
displayActual.getMetrics(metrics);
//Mostramos el panel inicial
layPGeneral=new RelativeLayout(getApplicationContext());
layPGeneral.setLayoutParams(panelSize);
layPLandscape=new RelativeLayout(getApplicationContext());
layPLandscape.setLayoutParams(panelSizeLandscape);
try {
if(metrics.heightPixels>metrics.widthPixels){ //portrait
ticoLayout.addView(scroll);
ticoLayout.addView(layPGeneral);
ticoLayout.addView(controlLayout);
setContentView(ticoLayout);
tableroAnterior=-1;
if(boards.getLength()>0)
MostrarPanel(layPGeneral,boards,accumulated, LayoutVisible);
else //solo se han definido paneles en landscape
MostrarPanel(layPGeneral,boardsLandscape,accumulated,LayoutVisible);
}else{ //landscape
ticoLayout.addView(scrollLandscape);
ticoLayout.addView(layPLandscape);
ticoLayout.addView(controlLayoutLandscape);
setContentView(ticoLayout);
if(boardsLandscape.getLength()>0)MostrarPanel(layPLandscape,boardsLandscape,accumulated, LayoutVisible);
else //solo se han definido tableros en portrait
MostrarPanel(layPLandscape,boards,accumulated,LayoutVisible);
}
} catch (OutOfMemoryError e) {
// TODO Auto-generated catch block
outOfMemoryRecover();
e.printStackTrace();
//reactivamos los botones
listenersOn();
return;
}catch(NullPointerException e){
readErrorRecover();
//reactivamos los botones
listenersOn();
return;
}
catch(Exception e){
readErrorRecover();
//reactivamos los botones
listenersOn();
return;
}
//anyadimos acciones a los botones de control
controlLayout.inicio().setOnClickListener(new View.OnClickListener() {//inicio.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tableroAnterior=LayoutVisible;
LayoutVisible=initialBoard;
try{
if(metrics.heightPixels>metrics.widthPixels){
if(boards.getLength()>0) MostrarPanel(layPGeneral,boards,accumulated,LayoutVisible);
else //solo hemos definido paneles en landscape
MostrarPanel(layPGeneral,boardsLandscape,accumulated,LayoutVisible);
}
else{
if(boardsLandscape.getLength()>0)MostrarPanel(layPLandscape,boardsLandscape,accumulated,LayoutVisible);
else //solo hemos definido paneles en portrait
MostrarPanel(layPLandscape,boards,accumulated,LayoutVisible);
}
} catch (OutOfMemoryError e) {
// TODO Auto-generated catch block
outOfMemoryRecover();
e.printStackTrace();
//reactivamos los botones
listenersOn();
}catch(NullPointerException e){
readErrorRecover();
//reactivamos los botones
listenersOn();
}
catch(Exception e){
readErrorRecover();
//reactivamos los botones
listenersOn();
}
//despues del click en barrido volvemos a la celda principal
if(TSetup.getSelectionMode().equals("automatic")) controlLayout.inicio().showMainCell();
}
});
controlLayout.volver().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(tableroAnterior>=0){
int aux=tableroAnterior;
tableroAnterior=LayoutVisible;
LayoutVisible=aux;
try {
if(metrics.heightPixels>metrics.widthPixels){//portrait
if(boards.getLength()>0)
MostrarPanel(layPGeneral,boards,accumulated,LayoutVisible);
else //solo hemos definido paneles en landscape
MostrarPanel(layPGeneral,boardsLandscape,accumulated,LayoutVisible);
}
else{//landscape
if(boardsLandscape.getLength()>0) MostrarPanel(layPLandscape,boardsLandscape,accumulated,LayoutVisible);
else //solo hemos definido paneles en portrait
MostrarPanel(layPLandscape,boards,accumulated,LayoutVisible);
}
} catch (OutOfMemoryError e) {
// TODO Auto-generated catch block
outOfMemoryRecover();
//reactivamos los botones
listenersOn();
}catch(NullPointerException e){
readErrorRecover();
//reactivamos los botones
listenersOn();
}
catch(Exception e){
readErrorRecover();
//reactivamos los botones
listenersOn();
}
//si esta en automatico despues de pulsar deseleccionamos la celda de control
if(TSetup.getSelectionMode().equals("automatic")) controlLayout.volver().showMainCell();
}
}
});
controlLayout.borrar1().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
accumulated.deleteCell();
//movemos el scroll para que se vea la última celda añadida (si no entra en pantalla)
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
scroll.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
}
}, 100L);
}
});
controlLayout.borrarTodas().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
accumulated.deleteAllCells();
}
});
controlLayout.leer().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(reproductorSonido!=null){
reproductorSonido.cancel(true);
reproductorSonido=null;
}
if(reproductorFrase!=null){
reproductorFrase.cancel(true);
reproductorFrase=null;
}
reproductorFrase=new playSentence();
reproductorFrase.execute(accumulated);//reproductorFrase.execute();
}
});
//anyadimos acciones a los botones de control Landscape
controlLayoutLandscape.inicio().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tableroAnterior=LayoutVisible;
LayoutVisible=initialBoard;
try{
if(metrics.heightPixels>metrics.widthPixels){//portrait
if(boards.getLength()>0) MostrarPanel(layPGeneral,boards,accumulated,LayoutVisible);
else//solo hemos definido tableros en landscape
MostrarPanel(layPGeneral,boardsLandscape,accumulated,LayoutVisible);
}
else{//landscape
if(boardsLandscape.getLength()>0) MostrarPanel(layPLandscape,boardsLandscape,accumulated,LayoutVisible);
else//solo hemos definido tableros en portrait
MostrarPanel(layPLandscape,boards,accumulated,LayoutVisible);
}
} catch (OutOfMemoryError e) {
// TODO Auto-generated catch block
outOfMemoryRecover();
e.printStackTrace();
//reactivamos los botones
listenersOn();
}catch(NullPointerException e){
readErrorRecover();
//reactivamos los botones
listenersOn();
}
catch(Exception e){
readErrorRecover();
//reactivamos los botones
listenersOn();
}
//si esta en automatico despues de pulsar deseleccionamos la celda de control
if(TSetup.getSelectionMode().equals("automatic")) controlLayoutLandscape.inicio().showMainCell();
}
});
controlLayoutLandscape.volver().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(tableroAnterior>=0){
int aux=tableroAnterior;
tableroAnterior=LayoutVisible;
LayoutVisible=aux;
try{
if(metrics.heightPixels>metrics.widthPixels){//portrait
if(boards.getLength()>0)MostrarPanel(layPGeneral,boards,accumulated,LayoutVisible);
else//solo hemos definido tableros en landscape
MostrarPanel(layPGeneral,boardsLandscape,accumulated,LayoutVisible);
}
else{//landscape
if(boardsLandscape.getLength()>0)MostrarPanel(layPLandscape,boardsLandscape,accumulated,LayoutVisible);
else//solo hemos definido tableros en portrait
MostrarPanel(layPLandscape,boards,accumulated,LayoutVisible);
}
} catch (OutOfMemoryError e) {
// TODO Auto-generated catch block
outOfMemoryRecover();
e.printStackTrace();
//reactivamos los botones
listenersOn();
}catch(NullPointerException e){
readErrorRecover();
//reactivamos los botones
listenersOn();
}
catch(Exception e){
readErrorRecover();
//reactivamos los botones
listenersOn();
}
//si esta en automatico despues de pulsar deseleccionamos la celda de control
if(TSetup.getSelectionMode().equals("automatic")) controlLayoutLandscape.volver().showMainCell();
}
}
});
controlLayoutLandscape.borrar1().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
accumulated.deleteCell();
//movemos el scroll para que se vea la última celda añadida (si no entra en pantalla)
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
scroll.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
}
}, 100L);
}
});
controlLayoutLandscape.borrarTodas().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
accumulated.deleteAllCells();
}
});
controlLayoutLandscape.leer().setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(reproductorSonido!=null){
reproductorSonido.cancel(true);
reproductorSonido=null;
}
if(reproductorFrase!=null){
reproductorFrase.cancel(true);
reproductorFrase=null;
}
reproductorFrase=new playSentence();
reproductorFrase.execute(accumulated);//reproductorFrase.execute();
}
});
}
}
}
/****************************************************************************************************************************************/
/**
* AsyncTask for the automatic scan behavior
*
* @param vistas RelativeLayout
panel that contains the cells to scanning
* @param values[0] cell
new cell to scan (publishProgress)
* @param values[1] cell
last cell scanned (publishProgress)
*/
//Ejecucion en paralelo de el barrido automático
protected class automaticScan extends AsyncTask{
@Override
protected Void doInBackground(RelativeLayout... vistas){
//ponemos la vista a un valor que no hace nada si pulsamos
vistaActual=-6;
//esperamos un segundo para dar tiempo a que se cierre la anterior ejecucion de automaticScan
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if(TSetup.getControlScanning().equals("first")){ //si escaneamos primero celdas de control
vistaActual=-5;
}
else{
vistaActual=0;
}
boolean seguir=true;
cell aux;
cell ant=null;
while(seguir){
if(vistaActual>=vectorOrderedCells.length){
if(!TSetup.getControlScanning().equals("no_scanning")){
vistaActual=-5;
}else if(vectorOrderedCells.length>0){//hay celdas en el tablero y no escaneamos las de control inferiores
vistaActual=0;
}else{//no hay ninguna celda para escanear y salimos
vistaActual=-6;//para que no haga nada al hacer click
return null;
}
}
if(isCancelled()){
publishProgress(null,ant);
return null;
}
if(vistaActual>=0){ //estamos en el panel
if(vectorOrderedCells[vistaActual]>=0){
aux=(cell)(vistas[0].getChildAt(vectorOrderedCells[vistaActual]));
if(aux.getOrdered()){
//reproducimos sonido alternativo
if(TSetup.getAlternativeSound() && (reproductorFrase==null || reproductorFrase.getStatus()!=Status.RUNNING) && aux.alternativeSoundURL!=null && !aux.alternativeSoundURL.equals("")){
if(reproductorSonido!=null) reproductorSonido.cancel(true);
reproductorSonido=new playSound();
reproductorSonido.execute(aux.getSoundAlternate());
}
publishProgress(aux,ant);
try {
Thread.sleep((long)TSetup.getScanWaitTime());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
seguir=false;
}
ant=aux;
}
}
}else{
if(metrics.heightPixels>metrics.widthPixels){ //portrait
aux=(cell)(controlLayout.getChildAt(vistaActual+5));
}
else{//esta en landscape
aux=(cell)(controlLayoutLandscape.getChildAt(vistaActual+5));
}
publishProgress(aux,ant);
try {
Thread.sleep((long)TSetup.getScanWaitTime());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
seguir=false;
}
ant=aux;
}
vistaActual++;
}
return null;
}
/**
* @param values[0] cell
new cell to scan (publishProgress)
* @param values[1] cell
last cell scanned (publishProgress)
*/
@Override
protected void onProgressUpdate( final cell... values) {
super.onProgressUpdate(values);
if(isCancelled()){
for(int i=0;i<5;i++){
((cell)controlLayout.getChildAt(i)).showMainCell();
}
return;
}
if(values[1]!=null){
values[1].showMainCell();
}
values[0].showAlternateCell();
}
}
/**************************************************************************************************************************************************/
/**
* Defines the sizes of the different layouts in the main TICO Activity
* in function of the screen size and the horientation
* Defines size for boards panel, accumulated images panel and the control panel for the 2 horientations
* The sizes are refreshed in the variables panelSize
accumulatedSize
controlSize
* panelSizeLandscape
accumulatedSizeLandscape
controlSizeLandscape
*/
private void setLayoutSizes(){
displayActual = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
metrics=new DisplayMetrics();
displayActual.getMetrics(metrics);
//Si esta en portrait
if(metrics.heightPixels>metrics.widthPixels){
panelSize = new RelativeLayout.LayoutParams(metrics.widthPixels,metrics.heightPixels*res.getInteger(R.integer.tamanyo_panel_porcien_portrait)/100);
accumulatedSize = new RelativeLayout.LayoutParams(metrics.widthPixels,metrics.heightPixels*res.getInteger(R.integer.tamanyo_barras_porcien_portrait)/100);
controlSize = new RelativeLayout.LayoutParams(metrics.widthPixels,metrics.heightPixels*res.getInteger(R.integer.tamanyo_barras_porcien_portrait)/100);
int auxOrientation=this.getRequestedOrientation();
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
displayActual.getMetrics(metrics);
panelSizeLandscape = new RelativeLayout.LayoutParams(metrics.widthPixels,metrics.heightPixels*res.getInteger(R.integer.tamanyo_panel_porcien_landscape)/100);
accumulatedSizeLandscape = new RelativeLayout.LayoutParams(metrics.widthPixels,metrics.heightPixels*res.getInteger(R.integer.tamanyo_barras_porcien_landscape)/100);
controlSizeLandscape = new RelativeLayout.LayoutParams(metrics.widthPixels,metrics.heightPixels*res.getInteger(R.integer.tamanyo_barras_porcien_landscape)/100);
setRequestedOrientation(auxOrientation);
}
//si esta en landscape
else{
panelSizeLandscape = new RelativeLayout.LayoutParams(metrics.widthPixels,metrics.heightPixels*res.getInteger(R.integer.tamanyo_panel_porcien_landscape)/100);
accumulatedSizeLandscape = new RelativeLayout.LayoutParams(metrics.widthPixels,metrics.heightPixels*res.getInteger(R.integer.tamanyo_barras_porcien_landscape)/100);
controlSizeLandscape = new RelativeLayout.LayoutParams(metrics.widthPixels,metrics.heightPixels*res.getInteger(R.integer.tamanyo_barras_porcien_landscape)/100);
int auxOrientation=this.getRequestedOrientation();
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
displayActual.getMetrics(metrics);
panelSize = new RelativeLayout.LayoutParams(metrics.widthPixels,metrics.heightPixels*res.getInteger(R.integer.tamanyo_panel_porcien_portrait)/100);
accumulatedSize = new RelativeLayout.LayoutParams(metrics.widthPixels,metrics.heightPixels*res.getInteger(R.integer.tamanyo_barras_porcien_portrait)/100);
controlSize = new RelativeLayout.LayoutParams(metrics.widthPixels,metrics.heightPixels*res.getInteger(R.integer.tamanyo_barras_porcien_portrait)/100);
setRequestedOrientation(auxOrientation);
}
displayActual.getMetrics(metrics);
}
/*********************************************************************************************************************************************/
//menus
/**
* Defines the options menu shown by clicking menu button
*/
//mostrar menu
@Override
public boolean onCreateOptionsMenu(Menu menu){
super.onCreateOptionsMenu(menu);
SubMenu sm;
menu.add(0,ABRIR,0,R.string.abrir);
menu.add(0,CONFIGURACION,0,R.string.configuracion);
sm=menu.addSubMenu(0,ACCIONES,0,R.string.acciones);
sm.add(0,READ,0,R.string.read);
sm.add(0,REMOVE_CELL,0,R.string.remove_cell);
sm.add(0,REMOVE_ALL_CELLS,0,R.string.remove_all_cells);
sm.add(0,BACK,0,R.string.back);
sm.add(0,HOME,0,R.string.home);
sm.add(0,RESOLUTIONS,0,R.string.get_resolutions);
menu.add(0,AYUDA,0,R.string.ayuda);
menu.add(0,EXIT,0,R.string.exit);
return true;
}
/**********************************************************************************************************************************/
//acciones del menu
/**
* Defines the behavior when selected a MenuItem
* @param item The selected MenuItem
*/
@Override
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()){
case ABRIR: //abrir
if(barredor!=null){
barredor.cancel(true);
barredor=null;
for(int cont=0;cont<5;cont++){
((cell)controlLayout.getChildAt(cont)).showMainCell();
((cell)controlLayoutLandscape.getChildAt(cont)).showMainCell();
}
}
intent=new Intent(TICO.this,fileDialog.class);
startActivityForResult(intent,1);
return true;
case CONFIGURACION: //configuracion
if(barredor!=null){
barredor.cancel(true);
barredor=null;
for(int cont=0;cont<5;cont++){
((cell)controlLayout.getChildAt(cont)).showMainCell();
((cell)controlLayoutLandscape.getChildAt(cont)).showMainCell();
}
}
intent=new Intent(TICO.this,SetupScreen.class);
startActivityForResult(intent,SETUP);
return true;
case READ: //leer frase
if(accumulated!=null){
if(metrics.heightPixels>metrics.widthPixels){//portrait
controlLayout.leer().performClick();
}else{//landscape
controlLayoutLandscape.leer().performClick();
}
}
return true;
case REMOVE_CELL: //borrar celda
if(accumulated!=null) accumulated.deleteCell();
return true;
case REMOVE_ALL_CELLS: //borrar todas las celdas
if(accumulated!=null) accumulated.deleteAllCells();
return true;
case AYUDA: //ayuda
AlertDialog alert=new AlertDialog.Builder(this).create();
alert.setTitle(res.getString(R.string.about));
alert.setMessage(res.getString(R.string.info_help));
alert.setButton(res.getString(R.string.accept), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
alert.show();
return true;
case EXIT: //salir
finish();
case BACK: //volver
if(accumulated!=null){
if(metrics.heightPixels>metrics.widthPixels){//portrait
controlLayout.volver().performClick();
}else{//landscape
controlLayoutLandscape.volver().performClick();
}
}
return true;
case HOME: //Inicio
if(accumulated!=null){//si hay cargado un proyecto
if(metrics.heightPixels>metrics.widthPixels){//portrait
controlLayout.inicio().performClick();
}else{//landscape
controlLayoutLandscape.inicio().performClick();
}
}
return true;
case RESOLUTIONS: //Resoluciones
AlertDialog alert2=new AlertDialog.Builder(this).create();
alert2.setTitle(res.getString(R.string.resolutions));
alert2.setMessage(res.getString(R.string.current_resolution)+"\n "+res.getString(R.string.width)+":"+metrics.widthPixels+" "+res.getString(R.string.height)+ ":" + metrics.heightPixels
+"\n"+res.getString(R.string.board_resolution)+" portrait\n "+res.getString(R.string.width)+":"+panelSize.width+" "+res.getString(R.string.height)+":"+panelSize.height
+"\n"+res.getString(R.string.board_resolution)+" landscape\n "+res.getString(R.string.width)+":"+panelSizeLandscape.width+" "+res.getString(R.string.height)+":"+panelSizeLandscape.height);
alert2.setButton(res.getString(R.string.accept), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
alert2.show();
return true;
}
return true;
}
/***********************************************************************************************************************************/
/**
* Redefines the onDestroy behavior of the main activity
* Removes the temp directory
*/
//cuando la activity es destruida borra la carpeta temporal
@Override
public void onDestroy(){
//paramos el barredor si esta en marcha
if(barredor!=null){
barredor.cancel(true);
barredor=null;
}
super.onDestroy();
//quitamos el bloqueo de brillo de pantall
if(wakelock.isHeld()) wakelock.release();
if(playSound.mp!=null) playSound.mp.stop();
File root = Environment.getExternalStorageDirectory();
File tempDirectory=new File(root+"/TMPtico");
readProject.borrarTmp(tempDirectory);
android.os.Process.killProcess(android.os.Process.myPid());
}
/*******************************************************************************************************************************************/
/**
* Refresh the current board
*/
private void refresh(){
if(accumulated!=null){ //si no no hay cargado ningun proyecto y no refrescamos
try{
if(metrics.heightPixels>metrics.widthPixels){//portrait
if(boards.getLength()>0) MostrarPanel(layPGeneral,boards,accumulated, LayoutVisible);
else //solo se han definido paneles en landscape
MostrarPanel(layPGeneral,boardsLandscape,accumulated,LayoutVisible);
}else{ //landscape
if(boardsLandscape.getLength()>0)MostrarPanel(layPLandscape,boardsLandscape,accumulated, LayoutVisible);
else //solo se han definido tableros en portrait
MostrarPanel(layPLandscape,boards,accumulated,LayoutVisible);
}
} catch (OutOfMemoryError e) {
// TODO Auto-generated catch block
outOfMemoryRecover();
e.printStackTrace();
//reactivamos los botones
listenersOn();
}catch(NullPointerException e){
readErrorRecover();
//reactivamos los botones
listenersOn();
}
catch(Exception e){
readErrorRecover();
//reactivamos los botones
listenersOn();
}
}
}
/*********************************************************************************************************************************************/
/**
* Recover the application of a outOfMemoryError and shows a message
*/
private void outOfMemoryRecover(){
layPGeneral.removeAllViews();
layPLandscape.removeAllViews();
AlertDialog alert=new AlertDialog.Builder(this).create();
alert.setTitle(res.getString(R.string.error));
alert.setMessage(res.getString(R.string.memory_problem_panel));
alert.setButton(res.getString(R.string.accept), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
alert.show();
System.gc();//garbage collector
}
/********************************************************************************************************************************/
/**
* Recover the application of a Exception and shows a message with the defined
* AlertDialog alertPrincipal
*/
private void readErrorRecover(){
alertPrincipal.setTitle(res.getString(R.string.error));
alertPrincipal.setMessage(res.getString(R.string.read_error));
alertPrincipal.setButton(res.getString(R.string.accept),new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
alertPrincipal.show();
setContentView(R.layout.main);
layPGeneral=null;
layPLandscape=null;
controlLayout=null;
controlLayoutLandscape=null;
accumulated=null;
}
/***********************************************************************************************************************************/
private void listenersOff(){
backEnabled=false;
if(controlLayout!=null) controlLayout.listenersOff();
if(controlLayoutLandscape!=null) controlLayout.listenersOff();
}
private void listenersOn(){
//backEnabled=true;
if(controlLayout!=null) controlLayout.listenersOn();
if(controlLayoutLandscape!=null) controlLayout.listenersOn();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
backEnabled=true;
}
}, 100L);//tiempo minimo de espera al cargar un panel para la siguiente orden de control
}
}