]> matita.cs.unibo.it Git - logicplayer.git/blob - mainActivity/src/com/example/furt/myapplication/DrawActivity.java
fea3a50c84a2b1bf50434e05d84480600f3c0d1c
[logicplayer.git] / mainActivity / src / com / example / furt / myapplication / DrawActivity.java
1 package com.example.furt.myapplication;
2
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;
21
22 import java.sql.Timestamp;
23 import java.util.ArrayList;
24
25 public class DrawActivity extends FragmentActivity {
26
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
44
45     static String user=null;
46     static String pass=null;
47     static String sessionKey=null;
48     static String nomeEs=null;
49
50     @Override
51     protected void onCreate(Bundle savedInstanceState) {
52         //routine standard per la create
53         super.onCreate(savedInstanceState);
54         setContentView(R.layout.activity_my);
55
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();
62         copiedNode=null;
63         scroll=(ScrollView)findViewById(R.id.vscroll);
64         startTime=time();
65         b=new Border[1];
66         b[0]=new Border(BorderedTextView.BORDER_TOP);
67         b[0].setWidth(2);
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");
73
74         //Creazione dell'albero: setto il rootNode e creo la Formula di partenza (F)
75         if(!populateTree())
76             return;
77
78         //Creazione dell'albero: setto i campi della view
79         BorderedTextView rootView=new BorderedTextView(this);
80         rootView.setId(globalId);
81         globalId++;
82         selectedNode=null;
83         addFakes=false; //di default non vengono aggiunte regole false
84         rootNode.setView(rootView,globalR);
85         rootNode.handler=new touchnodeHandler(rootNode);
86         startDraw();
87
88         //imposto il listener per il pinch zoom
89         scaleGestureDetector = new ScaleGestureDetector(this, new simpleOnScaleGestureListener());
90     }
91     @Override
92     public void onConfigurationChanged(Configuration configuration) //rotazione dello schermo: restore dell'albero
93     {
94         super.onConfigurationChanged(configuration);
95         getWindowManager().getDefaultDisplay().getMetrics(v);
96         DrawActivity.rootNode.Clean();
97         DrawActivity.startDraw();
98     }
99     public static void startDraw()
100     {
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()
116                 {
117                     @Override
118                     public void onGlobalLayout()
119                     {
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
128                         rootNode.Draw();
129
130                     }
131                 });
132     }
133     @Override
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);
137         return true;
138     }
139
140     @Override
141     public boolean onTouchEvent(MotionEvent event) {
142         // TODO Auto-generated method stub
143         scaleGestureDetector.onTouchEvent(event);
144         return true;
145     }
146
147
148     @Override
149     public boolean dispatchTouchEvent(MotionEvent event) {
150         super.dispatchTouchEvent(event);
151         return (scaleGestureDetector.onTouchEvent(event));
152     }
153
154     @Override
155     public boolean onOptionsItemSelected(MenuItem item) {
156         int id = item.getItemId();
157         if(id==R.id.action_paste) //incolla sottoalbero
158         {
159             if (DrawActivity.copiedNode == null) //non ci sono nodi da copiare
160                 return true;
161             else if (!checkHP(DrawActivity.copiedNode, DrawActivity.selectedNode)) //ipotesi incompatibili: impossibile incollare in questo punto
162                 return true;
163             else {
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();
171             }
172         }
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);
181         }
182         return true;
183     }
184
185
186     public boolean checkHP(Node source,Node target) //controlla se le ipotesi di source sono compatibili per una copia in target
187     {
188         boolean found=false;
189         if (!source.F.toString().equals(target.F.toString())) //se i nodi non hanno la stessa formula la copia è automaticamente impossibile
190             return false;
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).
194                     found = true;
195                     break;
196                 }
197             }
198             if (!found)
199                 return false;
200             else found=false;
201         }
202         return true;
203     }
204
205     public Node duplicateNode(Node src) //metodo di supporto che duplica un nodo
206     {
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));
212         }
213         return tmp;
214     }
215
216     public class simpleOnScaleGestureListener extends
217             ScaleGestureDetector.SimpleOnScaleGestureListener {
218
219         @Override
220         public boolean onScale(ScaleGestureDetector detector) {
221             float factor=detector.getScaleFactor();
222             if (textSize>65 && factor>1) //font troppo grande: impedisco aumento
223                 return true;
224             if (textSize<15 && factor<1) //font troppo piccolo: impedisco riduzione
225                 return true;
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
239             return true;
240         }
241     }
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();
245         } else {
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);
257             nmoves = 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);
264         }
265     }
266     public boolean populateTree() {
267
268         rootNode = parser.root(nomeEs);
269         if(rootNode==null)
270         {
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);
278             return false;
279         }
280         for (Hypothesis h:rootNode.NodeHP)
281             h.fromNode=rootNode;
282         return true;
283     }
284     public static long time()
285     {
286         java.util.Date date= new java.util.Date();
287         Timestamp now=new Timestamp(date.getTime());
288         return now.getTime();
289     }
290
291 }
292