1 package com.example.furt.myapplication;
3 import android.app.FragmentManager;
4 import android.content.Context;
5 import android.content.Intent;
6 import android.content.res.Configuration;
7 import android.os.Bundle;
8 import android.support.v4.app.FragmentActivity;
9 import android.util.DisplayMetrics;
10 import android.util.TypedValue;
11 import android.view.Gravity;
12 import android.view.Menu;
13 import android.view.MenuItem;
14 import android.view.MotionEvent;
15 import android.view.ScaleGestureDetector;
16 import android.view.ViewGroup;
17 import android.view.ViewTreeObserver;
18 import android.widget.RelativeLayout;
19 import android.widget.ScrollView;
20 import android.widget.Toast;
22 import java.sql.Timestamp;
24 import static java.lang.Thread.sleep;
26 public class DrawActivity extends FragmentActivity {
28 static RelativeLayout globalHP; //layout delle ipotesi cancellate
29 static ScaleGestureDetector scaleGestureDetector; //zoom listener
30 static float spaceSize; //dimensione della spaziatura tra i sottoalberi
31 static float textSize=40; //dimensione del font iniziale
32 static Node selectedNode; //Node su cui è attualmente il focus
33 static Node copiedNode;//nodo copiato
34 static boolean addFakes;//booleano che segnala se bisogna aggiungere delle regole fake
35 static Border[] b; //bordi per le borderedTextView
36 static FragmentManager fragmentManager;//per i dialog
37 static Node rootNode; //radice dell'albero corrente
38 static ScrollView scroll; //Vertical ScrollView contenente l'albero
39 static int nmoves=0;//numero di mosse
40 static int nerrors=0;//nomero di errori
41 static long startTime;//tempo di inizio dell'esercizio
42 static RelativeLayout globalR; //layout globale contenente l'albero
43 static int globalId =10; //variabile incrementale per l'assegnazione di ID univoci
44 static DisplayMetrics v = new DisplayMetrics();//altezza lunghezza e densità dello schermo
46 //Informazioni per la comunicazione client-server: username, password, nome dell'esercizio e chiave di sessione.
47 static String user=null;
48 static String pass=null;
49 static String sessionKey=null;
50 static String nomeEs=null;
53 protected void onCreate(Bundle savedInstanceState) {
54 //routine standard per la create
55 super.onCreate(savedInstanceState);
56 setContentView(R.layout.activity_my);
58 //recupero e setto le variabili globali
59 getWindowManager().getDefaultDisplay().getMetrics(v); //getMetrics() inserisce nella variabile V i dati metrici (altezza,larghezza,densità...) dello schermo del dispositivo
60 globalHP = (RelativeLayout) findViewById(R.id.hpscroll);
61 globalR = (RelativeLayout) findViewById(R.id.global);
62 spaceSize = 2*(textSize/v.density); //lo spazio tra due sottoalberi è di due caratteri vuoti
63 fragmentManager=getFragmentManager();
64 copiedNode=null; //inizialmente non ci sono ovviamente sottoalberi copiati
65 scroll=(ScrollView)findViewById(R.id.vscroll);
68 b[0]=new Border(BorderedTextView.BORDER_TOP);
70 //Recupero i dati passati dall'Intent: username, password, nome dell'esercizio da visualizzare e chiave di sessione
71 Bundle dati=getIntent().getExtras();
72 nomeEs=dati.getString("nomeEs");
73 user=dati.getString("user");
74 pass=dati.getString("pass");
75 sessionKey=dati.getString("sessionKey");
77 //Creazione dell'albero: setto il rootNode e creo la Formula di partenza (F)
78 if(!populateTree()) //populateTree() ha fallito: file dell'esercizio corrotto.
81 //Creazione dell'albero: setto i campi della view
82 BorderedTextView rootView=new BorderedTextView(this);
83 rootView.setId(globalId);
86 addFakes=false; //di default non vengono aggiunte regole false
87 rootNode.setView(rootView,globalR); //il rootNode viene legato al globalLayout attuale e alla TextView creata
88 rootNode.handler=new touchnodeHandler(rootNode);
89 rootNode.longHandler=new longnodeHandler(rootNode);
90 rootNode.hasFocus=true; //di default, la radice ha inizialmente il focus.
93 //imposto il listener per il pinch zoom
94 scaleGestureDetector = new ScaleGestureDetector(this, new simpleOnScaleGestureListener());
97 public void onConfigurationChanged(Configuration configuration) //rotazione dello schermo: restore dell'albero
99 super.onConfigurationChanged(configuration);
100 getWindowManager().getDefaultDisplay().getMetrics(v);
101 DrawActivity.rootNode.Clean();
102 DrawActivity.startDraw();
104 public static void startDraw()
106 RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
107 final int halfScreen=Math.round((v.widthPixels / 2) - rootNode.getBaseWidth() / 2); //calcolo la metà dello schermo per il calcolo dei margins della scrollView
108 int leftSubTree=(Math.round(rootNode.getLeftOffset() - rootNode.getUpLine() / 2 + (rootNode.getBaseWidth() / 2)) + 40); //sottoalbero sinistro del rootNode più un padding di 40px
109 lp.setMargins(Math.max(halfScreen,leftSubTree),0, 0, 0);
110 lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, rootNode.view.getId());
111 rootNode.view.setLayoutParams(lp);
112 rootNode.view.setBorders(b);
113 rootNode.view.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
114 rootNode.view.setWidth(Math.round(rootNode.getLineWidth())); //setto la larghezza della view al contenuto della linea
115 rootNode.view.setGravity(Gravity.CENTER); //formula al centro della sua overline
116 rootNode.view.setText(rootNode.F.toString()); //setta il contenuto della formula
117 globalR.addView(rootNode.view);
118 //inserisco un listener a rootView da attivare quando sono state fissate le coordinate nel RelativeLayout
119 rootNode.view.getViewTreeObserver().addOnGlobalLayoutListener(
120 new ViewTreeObserver.OnGlobalLayoutListener()
123 public void onGlobalLayout()
125 globalR.setPadding(0,0,(int)Math.max(rootNode.getRightOffset(),halfScreen),0);
126 globalR.getLayoutParams().height=(int)Math.max((v.heightPixels),(rootNode.getMaxHeight()+rootNode.getMaxHeight()*0.10)); //altezza della view=max(h_screen,h_tree). Aggiungo un 10% all'altezza dell'albero per approssimazione dei calcoli.
127 globalR.requestLayout(); //aggiorna i parametri e le dimensioni del RelativeLayout
128 if (rootNode.getMaxHeight()<v.heightPixels/2) //se l'albero non ha raggiunto almeno la metà dello schermo scrollo la view fino in fondo per visualizzarlo interamente
129 scroll.fullScroll(ScrollView.FOCUS_DOWN);
130 rootNode.view.setOnClickListener(rootNode.handler);
131 rootNode.view.setOnLongClickListener(rootNode.longHandler);
132 rootNode.view.getViewTreeObserver().removeOnGlobalLayoutListener(this); //rimuove il listener per evitare che la funzione parta nuovamente
138 public void onBackPressed() {
139 //abbandona esercizio e torna alla view con la lista degli esercizi
140 Intent i = new Intent(globalHP.getContext(), aggiornamento.class);
141 i.putExtra("user", user);
142 i.putExtra("pass", pass);
143 i.putExtra("sessionKey", sessionKey);
144 i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
145 globalHP.getContext().startActivity(i);
149 public boolean onCreateOptionsMenu(Menu menu) {
150 // Inflate the menu; this adds items to the action bar if it is present.
151 getMenuInflater().inflate(R.menu.my, menu);
156 public boolean onTouchEvent(MotionEvent event) {
157 // TODO Auto-generated method stub
158 scaleGestureDetector.onTouchEvent(event);
164 public boolean dispatchTouchEvent(MotionEvent event) {
165 super.dispatchTouchEvent(event);
166 return (scaleGestureDetector.onTouchEvent(event));
170 public boolean onOptionsItemSelected(MenuItem item) {
171 int id = item.getItemId();
173 { //abbandona esercizio e torna alla view con la lista degli esercizi
174 Intent i = new Intent(globalHP.getContext(), aggiornamento.class);
175 i.putExtra("user", user);
176 i.putExtra("pass", pass);
177 i.putExtra("sessionKey", sessionKey);
178 i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
179 globalHP.getContext().startActivity(i);
186 public class simpleOnScaleGestureListener extends
187 ScaleGestureDetector.SimpleOnScaleGestureListener {
190 public boolean onScale(ScaleGestureDetector detector) {
191 float factor=detector.getScaleFactor();
192 if (textSize>65 && factor>1) //font troppo grande: impedisco aumento
194 if (textSize<15 && factor<1) //font troppo piccolo: impedisco riduzione
196 rootNode.Refactor(); //risetta i campi dell'albero a FIELD_UNSET
197 RelativeLayout.LayoutParams lp=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
198 DrawActivity.spaceSize=(DrawActivity.spaceSize*factor);
199 DrawActivity.textSize=(DrawActivity.textSize*factor);
200 int halfScreen=Math.round((v.widthPixels / 2)-rootNode.getBaseWidth()/2);
201 int leftSubTree=(Math.round(rootNode.getLeftOffset() - rootNode.getUpLine() / 2 + (rootNode.getBaseWidth() / 2)) + 40);
202 globalR.setPadding(0,0,(int)Math.max(rootNode.getRightOffset(),halfScreen),0);
203 lp.setMargins(Math.max(halfScreen,leftSubTree),0, 0, 0);
204 lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, rootNode.view.getId());
205 rootNode.view.setLayoutParams(lp);
206 rootNode.view.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
207 rootNode.view.setWidth(Math.round(rootNode.getLineWidth())); //setto la larghezza della view al contenuto della linea
208 rootNode.Resize(); //ricorsivamente sistema i fontsize, le larghezze e le posizioni delle view nell'albero
212 public static void finishedTree(Context context) {
213 if (!rootNode.isCorrect()) {
214 Toast.makeText(context, "Esercizio errato! Ricontrolla i passaggi fatti e riprova", Toast.LENGTH_LONG).show();
216 long endTime = time();
217 int second= (int) ((endTime-startTime)/1000);
218 int minute=second/60;
219 Toast.makeText(context, "Esercizio completato in " + Integer.toString(nmoves) + " mosse!", Toast.LENGTH_LONG).show();
222 } catch (InterruptedException e) {
225 Toast.makeText(context, "Hai commesso " + Integer.toString(nerrors) + " errori!", Toast.LENGTH_LONG).show();
228 } catch (InterruptedException e) {
231 Toast.makeText(context, "Numero nodi dell'albero: " + Integer.toString(rootNode.count()), Toast.LENGTH_LONG).show();
234 } catch (InterruptedException e) {
237 Toast.makeText(context, "Tempo impiegato: " + Integer.toString(minute) + " minuti e " + Integer.toString(second-(minute*60)) + " secondi", Toast.LENGTH_LONG).show();
238 //aggiungo l'esercizio al database
239 int voto=valutazione.voto(nomeEs,nmoves,second,rootNode.count(),nerrors);
240 personalDBHelper db = new personalDBHelper(context);
241 db.add(user, nomeEs, MD5.digest(nomeEs), 0.0, voto, 0);
243 Intent i = new Intent(context, aggiornamento.class);
244 i.putExtra("user", user);
245 i.putExtra("pass", pass);
246 i.putExtra("sessionKey", sessionKey);
247 i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
248 context.startActivity(i);
251 public boolean populateTree() {
253 rootNode = parser.root(nomeEs);
256 Toast.makeText(this, "Errore nell'apertura del file", Toast.LENGTH_LONG).show();
257 Intent i = new Intent(this, aggiornamento.class);
258 i.putExtra("user", user);
259 i.putExtra("pass", pass);
260 i.putExtra("sessionKey", sessionKey);
261 i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
262 this.startActivity(i);
265 for (Hypothesis h:rootNode.NodeHP)
269 public static long time()
271 java.util.Date date= new java.util.Date();
272 Timestamp now=new Timestamp(date.getTime());
273 return now.getTime();