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;
23 import java.util.ArrayList;
25 public class DrawActivity extends FragmentActivity {
27 static RelativeLayout globalHP; //layout delle ipotesi cancellate
28 static ScaleGestureDetector scaleGestureDetector; //zoom listener
29 static float spaceSize; //dimensione della spaziatura tra i sottoalberi
30 static float textSize=40; //dimensione del font iniziale
31 static Node selectedNode; //Node su cui è attualmente il focus
32 static Node copiedNode;//nodo copiato
33 static boolean addFakes;//booleano che segnala se bisogna aggiungere delle regole fake
34 static Border[] b; //bordi per le borderedTextView
35 static FragmentManager fragmentManager;//per i dialog
36 static Node rootNode; //radice dell'albero corrente
37 static ScrollView scroll;
38 static int nmoves=0;//numero di mosse
39 static int nerrors=0;//nomero di errori
40 static long startTime;//tempo di inizio dell'esercizio
41 static RelativeLayout globalR; //layout globale contenente l'albero
42 static int globalId =10; //variabile incrementale per l'assegnazione di ID univoci
43 static DisplayMetrics v = new DisplayMetrics();//altezza lunghezza e densità dello schermo
45 static String user=null;
46 static String pass=null;
47 static String sessionKey=null;
48 static String nomeEs=null;
51 protected void onCreate(Bundle savedInstanceState) {
52 //routine standard per la create
53 super.onCreate(savedInstanceState);
54 setContentView(R.layout.activity_my);
56 //recupero e setto le variabili globali
57 getWindowManager().getDefaultDisplay().getMetrics(v);
58 globalHP = (RelativeLayout) findViewById(R.id.hpscroll);
59 globalR = (RelativeLayout) findViewById(R.id.global);
60 spaceSize = 2*(textSize/v.density);
61 fragmentManager=getFragmentManager();
63 scroll=(ScrollView)findViewById(R.id.vscroll);
66 b[0]=new Border(BorderedTextView.BORDER_TOP);
68 Bundle dati=getIntent().getExtras();
69 nomeEs=dati.getString("nomeEs");
70 user=dati.getString("user");
71 pass=dati.getString("pass");
72 sessionKey=dati.getString("sessionKey");
74 //Creazione dell'albero: setto il rootNode e creo la Formula di partenza (F)
78 //Creazione dell'albero: setto i campi della view
79 BorderedTextView rootView=new BorderedTextView(this);
80 rootView.setId(globalId);
83 addFakes=false; //di default non vengono aggiunte regole false
84 rootNode.setView(rootView,globalR);
85 rootNode.handler=new touchnodeHandler(rootNode);
88 //imposto il listener per il pinch zoom
89 scaleGestureDetector = new ScaleGestureDetector(this, new simpleOnScaleGestureListener());
92 public void onConfigurationChanged(Configuration configuration) //rotazione dello schermo: restore dell'albero
94 super.onConfigurationChanged(configuration);
95 getWindowManager().getDefaultDisplay().getMetrics(v);
96 DrawActivity.rootNode.Clean();
97 DrawActivity.startDraw();
99 public static void startDraw()
101 RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
102 final int halfScreen=Math.round((v.widthPixels / 2) - rootNode.getBaseWidth() / 2); //calcolo la metà dello schermo per il calcolo dei margins della scrollView
103 int leftSubTree=(Math.round(rootNode.getLeftOffset() - rootNode.getUpLine() / 2 + (rootNode.getBaseWidth() / 2)) + 40); //sottoalbero sinistro del rootNode più un padding di 40px
104 lp.setMargins(Math.max(halfScreen,leftSubTree),0, 0, 0);
105 lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, rootNode.view.getId());
106 rootNode.view.setLayoutParams(lp);
107 rootNode.view.setBorders(b);
108 rootNode.view.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
109 rootNode.view.setWidth(Math.round(rootNode.getLineWidth())); //setto la larghezza della view al contenuto della linea
110 rootNode.view.setGravity(Gravity.CENTER); //formula al centro della sua overline
111 rootNode.view.setText(rootNode.F.toString()); //setta il contenuto della formula
112 globalR.addView(rootNode.view);
113 //inserisco un listener a rootView da attivare quando sono state fissate le coordinate nel RelativeLayout
114 rootNode.view.getViewTreeObserver().addOnGlobalLayoutListener(
115 new ViewTreeObserver.OnGlobalLayoutListener()
118 public void onGlobalLayout()
120 globalR.setPadding(0,0,(int)Math.max(rootNode.getRightOffset(),halfScreen),0);
121 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.
122 globalR.requestLayout(); //aggiorna i parametri e le dimensioni del RelativeLayout
123 if (rootNode.treeHeight()< 3)
124 scroll.fullScroll(ScrollView.FOCUS_DOWN);
125 rootNode.view.setOnClickListener(rootNode.handler);
126 rootNode.hasFocus=true; //di default, la radice ha inizialmente il focus.
127 rootNode.view.getViewTreeObserver().removeOnGlobalLayoutListener(this); //rimuove il listener per evitare che la funzione parta nuovamente
134 public boolean onCreateOptionsMenu(Menu menu) {
135 // Inflate the menu; this adds items to the action bar if it is present.
136 getMenuInflater().inflate(R.menu.my, menu);
141 public boolean onTouchEvent(MotionEvent event) {
142 // TODO Auto-generated method stub
143 scaleGestureDetector.onTouchEvent(event);
149 public boolean dispatchTouchEvent(MotionEvent event) {
150 super.dispatchTouchEvent(event);
151 return (scaleGestureDetector.onTouchEvent(event));
155 public boolean onOptionsItemSelected(MenuItem item) {
156 int id = item.getItemId();
157 if(id==R.id.action_paste) //incolla sottoalbero
159 if (DrawActivity.copiedNode == null) //non ci sono nodi da copiare
161 else if (!checkHP(DrawActivity.copiedNode, DrawActivity.selectedNode)) //ipotesi incompatibili: impossibile incollare in questo punto
164 Node tmp = duplicateNode(DrawActivity.copiedNode); //duplica il nodo copiato
165 DrawActivity.selectedNode.ruleName=tmp.ruleName;
166 DrawActivity.selectedNode.Children = new ArrayList<Node>();
167 for (Node c:tmp.Children)
168 DrawActivity.selectedNode.addChild(c); //incolla il sottoalbero del nodo copiato nella posizione richiesta
169 DrawActivity.rootNode.Clean();
170 DrawActivity.startDraw();
173 else if(id==R.id.abandon)
174 { //abbandona esercizio e torna alla view con la lista degli esercizi
175 Intent i = new Intent(globalHP.getContext(), aggiornamento.class);
176 i.putExtra("user", user);
177 i.putExtra("pass", pass);
178 i.putExtra("sessionKey", sessionKey);
179 i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
180 globalHP.getContext().startActivity(i);
186 public boolean checkHP(Node source,Node target) //controlla se le ipotesi di source sono compatibili per una copia in target
189 if (!source.F.toString().equals(target.F.toString())) //se i nodi non hanno la stessa formula la copia è automaticamente impossibile
191 for (Hypothesis sourceHp:source.NodeHP) {
192 for (Hypothesis destHp : target.NodeHP) {
193 if (destHp.HP.toString().equals(sourceHp.HP.toString())) { //per ogni ipotesi nel nodo sorgente cerco se è disponibile nel nodo destinazione: in caso affermativo, proseguo il ciclo (found=true).
205 public Node duplicateNode(Node src) //metodo di supporto che duplica un nodo
207 Node tmp=new Node(src.F);
208 tmp.addHPList(src.NodeHP);
209 tmp.ruleName=src.ruleName;
210 for (Node n:src.Children) {
211 tmp.addChild(duplicateNode(n));
216 public class simpleOnScaleGestureListener extends
217 ScaleGestureDetector.SimpleOnScaleGestureListener {
220 public boolean onScale(ScaleGestureDetector detector) {
221 float factor=detector.getScaleFactor();
222 if (textSize>65 && factor>1) //font troppo grande: impedisco aumento
224 if (textSize<15 && factor<1) //font troppo piccolo: impedisco riduzione
226 rootNode.Refactor(); //risetta i campi dell'albero a FIELD_UNSET
227 RelativeLayout.LayoutParams lp=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
228 DrawActivity.spaceSize=(DrawActivity.spaceSize*factor);
229 DrawActivity.textSize=(DrawActivity.textSize*factor);
230 int halfScreen=Math.round((v.widthPixels / 2)-rootNode.getBaseWidth()/2);
231 int leftSubTree=(Math.round(rootNode.getLeftOffset() - rootNode.getUpLine() / 2 + (rootNode.getBaseWidth() / 2)) + 40);
232 globalR.setPadding(0,0,(int)Math.max(rootNode.getRightOffset(),halfScreen),0);
233 lp.setMargins(Math.max(halfScreen,leftSubTree),0, 0, 0);
234 lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, rootNode.view.getId());
235 rootNode.view.setLayoutParams(lp);
236 rootNode.view.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
237 rootNode.view.setWidth(Math.round(rootNode.getLineWidth())); //setto la larghezza della view al contenuto della linea
238 rootNode.Resize(); //ricorsivamente sistema i fontsize, le larghezze e le posizioni delle view nell'albero
242 public static void finishedTree(Context context) {
243 if (!rootNode.isCorrect()) {
244 Toast.makeText(context, "Esercizio errato! Ricontrolla i passaggi fatti e riprova", Toast.LENGTH_LONG).show();
246 long endTime = time();
247 int second= (int) ((endTime-startTime)/1000);
248 int minute=second/60;
249 Toast.makeText(context, "Esercizio completato in " + Integer.toString(nmoves) + " mosse!", Toast.LENGTH_LONG).show();
250 Toast.makeText(context, "Hai commesso " + Integer.toString(nerrors) + " errori!", Toast.LENGTH_LONG).show();
251 Toast.makeText(context, "Numero nodi dell'albero: " + Integer.toString(rootNode.count()), Toast.LENGTH_LONG).show();
252 Toast.makeText(context, "Tempo impiegato: " + Integer.toString(minute) + " minuti e " + Integer.toString(second-(minute*60)) + " secondi", Toast.LENGTH_LONG).show();
253 //aggiungo l'esercizio al database
254 int voto=valutazione.voto(nomeEs,nmoves,second,rootNode.count(),nerrors);
255 personalDBHelper db = new personalDBHelper(context);
256 db.add(user, nomeEs, MD5.digest(nomeEs), 0.0, voto, 0);
258 Intent i = new Intent(context, aggiornamento.class);
259 i.putExtra("user", user);
260 i.putExtra("pass", pass);
261 i.putExtra("sessionKey", sessionKey);
262 i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
263 context.startActivity(i);
266 public boolean populateTree() {
268 rootNode = parser.root(nomeEs);
271 Toast.makeText(this, "Errore nell'apertura del file", Toast.LENGTH_LONG).show();
272 Intent i = new Intent(this, aggiornamento.class);
273 i.putExtra("user", user);
274 i.putExtra("pass", pass);
275 i.putExtra("sessionKey", sessionKey);
276 i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
277 this.startActivity(i);
280 for (Hypothesis h:rootNode.NodeHP)
284 public static long time()
286 java.util.Date date= new java.util.Date();
287 Timestamp now=new Timestamp(date.getTime());
288 return now.getTime();