--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+ <classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="src" path="gen"/>
+ <classpathentry kind="output" path="bin/classes"/>
+</classpath>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>mainActivity</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>com.android.ide.eclipse.adt.ApkBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
--- /dev/null
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.7
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.7
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.furt.myapplication" >
+ <uses-sdk
+ android:minSdkVersion="19"
+ android:targetSdkVersion="19" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/def"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name=".mainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name=".DrawActivity"
+ android:label="@string/app_name"
+ android:configChanges="orientation|screenSize">
+
+ </activity>
+ <service
+ android:name=".MyService"
+ android:exported="false"/>
+ <activity
+ android:name=".download_page"
+ android:label="@string/listEs" >
+ </activity>
+ <activity
+ android:name=".aggiornamento"
+ android:label="@string/app_name" >
+ </activity>
+ <activity
+ android:name=".recuperaPass"
+ android:label="@string/app_name" >
+ </activity>
+ </application>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+</manifest>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.furt.myapplication" >
+ <uses-sdk
+ android:minSdkVersion="19"
+ android:targetSdkVersion="19" />
+ <uses-permission android:name="android.permission.INTERNET" />
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/def"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name=".mainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ <activity
+ android:name=".DrawActivity"
+ android:label="@string/app_name"
+ android:configChanges="orientation|screenSize">
+
+ </activity>
+ <service
+ android:name=".MyService"
+ android:exported="false"/>
+ <activity
+ android:name=".download_page"
+ android:label="@string/listEs" >
+ </activity>
+ <activity
+ android:name=".aggiornamento"
+ android:label="@string/app_name" >
+ </activity>
+ <activity
+ android:name=".recuperaPass"
+ android:label="@string/app_name" >
+ </activity>
+ </application>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+ <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+</manifest>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+</lint>
\ No newline at end of file
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-19
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/dlglobal">
+
+ <Button
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="aggiorna"
+ android:paddingRight="10dp"
+ android:layout_marginRight="10dp"
+ android:id="@+id/aggiorna" />
+
+ <Button
+ style="?android:attr/buttonStyleSmall"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="logout"
+ android:id="@+id/logout"
+ android:layout_alignParentTop="true"
+ android:layout_toRightOf="@+id/aggiorna"
+ android:layout_toEndOf="@+id/aggiorna" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/startEs"
+ android:text="Lista degli Esercizi:"
+ android:textSize="30sp"
+ android:layout_below="@+id/aggiorna"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true" />
+
+</RelativeLayout>
\ No newline at end of file
--- /dev/null
+<RelativeLayout
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <ScrollView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/scrollView3">
+ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ tools:context=".activity_login">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Inserisci le tue credenziali:"
+ android:id="@+id/login"/>
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/invia"
+ android:id="@+id/logout"
+ android:layout_below="@+id/oldPass"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="61dp"
+ android:width="120dp" />
+
+ <EditText
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inputType="textPassword"
+ android:ems="10"
+ android:id="@+id/oldPass"
+ android:hint="@string/pass"
+ android:layout_below="@+id/userId"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentEnd="true"
+ android:layout_marginTop="29dp"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true" />
+ <EditText
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inputType="textEmailAddress"
+ android:ems="10"
+ android:id="@+id/userId"
+ android:hint="nome.cognome@studio.unibo.it"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:layout_marginTop="31dp"
+ android:layout_alignRight="@+id/oldPass"
+ android:layout_alignEnd="@+id/oldPass"
+ android:autoText="false" />
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/registrati"
+ android:id="@+id/button2"
+ android:layout_below="@+id/logout"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="31dp"
+ android:width="120dp" />
+ </RelativeLayout>
+ </ScrollView>
+</RelativeLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:background="@android:color/holo_blue_light"
+ android:id="@+id/hpscroll"
+ android:layout_height="wrap_content"
+ tools:context=".MyActivity">
+ </RelativeLayout>
+ <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:id="@+id/vscroll"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_height="fill_parent"
+ android:fillViewport="false"
+ tools:context=".MainActivity">
+
+ <HorizontalScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/window"
+ android:fillViewport="true">
+ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="wrap_content"
+ android:layout_height="7000dp"
+ android:id="@+id/global"
+ tools:context=".MyActivity">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true" />
+ </RelativeLayout>
+ </HorizontalScrollView>
+ </ScrollView>
+</LinearLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical" android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/glob_agg">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/aggiornamento"
+ android:textSize="20sp"
+ android:id="@+id/loading"
+ android:layout_gravity="center_horizontal"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="192dp" />
+
+ <ProgressBar
+ style="?android:attr/progressBarStyleLarge"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/progressBar"
+ android:layout_marginTop="39dp"
+ android:layout_centerHorizontal="true" />
+
+</RelativeLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <ListView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/listView"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true" />
+
+</RelativeLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<RelativeLayout
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_height="fill_parent"
+ android:fillViewport="false"
+ tools:context=".recuperaPass">
+ <RelativeLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Inserisci le tue credenziali:"
+ android:id="@+id/passreim"
+ android:layout_alignParentTop="true"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:textSize="24dp" />
+
+ <EditText
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inputType="textEmailAddress"
+ android:ems="10"
+ android:id="@+id/userId"
+ android:hint="nome.cognome@studio.unibo.it"
+ android:layout_below="@+id/passreim"
+ android:layout_marginTop="69dp"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentEnd="true" />
+
+ <EditText
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inputType="textPassword"
+ android:ems="10"
+ android:id="@+id/oldPass"
+ android:hint="vecchia password"
+ android:layout_below="@+id/userId"
+ android:layout_marginTop="50dp"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentEnd="true" />
+
+ <EditText
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:inputType="textPassword"
+ android:ems="10"
+ android:id="@+id/newPass"
+ android:layout_below="@+id/oldPass"
+ android:layout_marginTop="56dp"
+ android:hint="nuova password"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentRight="true"
+ android:layout_alignParentEnd="true" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Invia"
+ android:id="@+id/invia"
+ android:layout_marginTop="30dp"
+ android:width="120dp"
+ android:layout_below="@+id/newPass"
+ android:layout_centerHorizontal="true" />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="annulla"
+ android:id="@+id/annulla"
+ android:layout_below="@+id/invia"
+ android:layout_alignLeft="@+id/invia"
+ android:layout_alignStart="@+id/invia"
+ android:layout_marginTop="30dp"
+ android:width="120dp" />
+ </RelativeLayout>
+ </ScrollView>
+</RelativeLayout>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_height="fill_parent"
+ android:fillViewport="false"
+ tools:context=".MainActivity">
+
+ <HorizontalScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:id="@+id/window"
+ android:fillViewport="true">
+ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="wrap_content"
+ android:layout_height="1dp"
+ android:id="@+id/global"
+ tools:context=".MyActivity">
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true" />
+ </RelativeLayout>
+ </HorizontalScrollView>
+
+</ScrollView>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+ <HorizontalScrollView
+ android:layout_width="match_parent"
+ android:layout_height="40dp"
+ android:background="@android:color/holo_blue_light"
+ android:fillViewport="true">
+ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="wrap_content"
+ android:id="@+id/literals"
+ android:layout_height="match_parent">
+ </RelativeLayout>
+ </HorizontalScrollView>
+ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:background="@android:color/holo_orange_light"
+ android:id="@+id/operators"
+ android:layout_height="40dp"
+ tools:context=".MyActivity">
+ </RelativeLayout>
+
+ <HorizontalScrollView
+ android:layout_width="match_parent"
+ android:layout_height="100dp"
+ android:fillViewport="true">
+ <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="wrap_content"
+ android:layout_height="100dp"
+ android:id="@+id/formulaLayout"
+ tools:context=".MyActivity">
+ </RelativeLayout>
+ </HorizontalScrollView>
+</LinearLayout>
\ No newline at end of file
--- /dev/null
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/rowTextView"
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:padding="10dp"
+ android:textSize="20sp"
+ android:textColor="@android:color/black">
+</TextView>
\ No newline at end of file
--- /dev/null
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context=".MyActivity" >
+ <item android:id="@+id/recupera"
+ android:title="@string/recuperapass"
+ android:orderInCategory="100"
+ android:showAsAction="never" />
+ <item android:id="@+id/reimposta"
+ android:title="@string/reimposta"
+ android:orderInCategory="100"
+ android:showAsAction="never" />
+</menu>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+
+<menu
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context=".MyActivity" >
+ <item android:id="@+id/aggiorna"
+ android:title="@string/sync"
+ android:orderInCategory="100"
+ android:showAsAction="never" />
+ <item android:id="@+id/esci"
+ android:title="@string/esci"
+ android:orderInCategory="100"
+ android:showAsAction="never" />
+</menu>
\ No newline at end of file
--- /dev/null
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context=".MyActivity" >
+ <item android:id="@+id/action_paste"
+ android:title="Incolla sottoalbero"
+ android:orderInCategory="100"
+ android:showAsAction="never" />
+ <item android:id="@+id/abandon"
+ android:title="Abbandona esercizio"
+ android:orderInCategory="100"
+ android:showAsAction="never" />
+</menu>
--- /dev/null
+<resources>
+ <!-- Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively). -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+</resources>
--- /dev/null
+<resources>
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">LogicPlayer</string>
+ <string name="hello_world">inserisci una stringa</string>
+ <string name="action_settings">Settings</string>
+ <string name="invia">accedi</string>
+ <string name="pass">password</string>
+ <string name="sync">Aggiorna</string>
+ <string name="esci">Esci</string>
+ <string name="user">Username</string>
+ <string name="listEs">Lista esercizi:</string>
+ <string name="registrati">registrati</string>
+ <string name="recuperapass">recupera password</string>
+ <string name="first">download disponibili:</string>
+ <string name="reimposta">Reimposta password</string>
+ <string name="listaEsercizi">Lista esercizi:</string>
+ <string name="Credenziali">Inserisci le tue credenziali:</string>
+ <string name="aggiornamento">sto aggiornando</string>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!-- Base application theme. -->
+ <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+ <!-- Customize your theme here. -->
+ </style>
+
+</resources>
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.graphics.Color;
+import android.os.Bundle;
+
+public class Border {
+ private int orientation;
+ private int width;
+ private int color = Color.BLACK;
+ private int style;
+ public int getWidth() {
+ return width;
+ }
+ public void setWidth(int width) {
+ this.width = width;
+ }
+ public int getColor() {
+ return color;
+ }
+ public void setColor(int color) {
+ this.color = color;
+ }
+ public int getStyle() {
+ return style;
+ }
+ public void setStyle(int style) {
+ this.style = style;
+ }
+ public int getOrientation() {
+ return orientation;
+ }
+ public void setOrientation(int orientation) {
+ this.orientation = orientation;
+ }
+ public Border(int Style) {
+ this.style = Style;
+ }
+}
+
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.widget.TextView;
+
+public class BorderedTextView extends TextView {
+ private Paint paint = new Paint();
+ public static final int BORDER_TOP = 0x00000001;
+ public static final int BORDER_RIGHT = 0x00000002;
+ public static final int BORDER_BOTTOM = 0x00000004;
+ public static final int BORDER_LEFT = 0x00000008;
+ private Border[] borders;
+
+ public BorderedTextView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init();
+ }
+
+ public BorderedTextView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init();
+ }
+
+ public BorderedTextView(Context context) {
+ super(context);
+ init();
+ }
+ private void init(){
+ paint.setStyle(Paint.Style.STROKE);
+ paint.setColor(Color.BLACK);
+ paint.setStrokeWidth(4);
+ }
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ if(borders == null) return;
+ for(Border border : borders){
+ paint.setColor(border.getColor());
+ paint.setStrokeWidth(border.getWidth());
+
+ if(border.getStyle() == BORDER_TOP){
+ canvas.drawLine(0, 0, getWidth(), 0, paint);
+ } else
+ if(border.getStyle() == BORDER_RIGHT){
+ canvas.drawLine(getWidth(), 0, getWidth(), getHeight(), paint);
+ } else
+ if(border.getStyle() == BORDER_BOTTOM){
+ canvas.drawLine(0, getHeight(), getWidth(), getHeight(), paint);
+ } else
+ if(border.getStyle() == BORDER_LEFT){
+ canvas.drawLine(0, 0, 0, getHeight(), paint);
+ }
+ }
+ }
+
+ public Border[] getBorders() {
+ return borders;
+ }
+
+ public void setBorders(Border[] borders) {
+ this.borders = borders;
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.os.Bundle;
+
+import java.util.ArrayList;
+
+public class CopyPasteDialog extends DialogFragment {
+ static Node thisNode;
+ public CopyPasteDialog(Node n)
+ {
+ thisNode=n;
+ }
+ @Override
+ public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setMessage("Seleziona un'operazione:")
+ .setPositiveButton("Copia", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ DrawActivity.copiedNode=thisNode;
+ }
+ });
+ builder.setNeutralButton("Cancella", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ DrawActivity.selectedNode.Children = new ArrayList<Node>();
+ DrawActivity.rootNode.Clean();
+ DrawActivity.startDraw();
+ }
+ });
+ builder.setNegativeButton("Annulla", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ thisNode=null;
+ }
+ });
+ // Create the AlertDialog object and return it
+ return builder.create();
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.graphics.Color;
+import android.view.View;
+import android.widget.TextView;
+
+public class DialogTouchHandler implements View.OnClickListener{
+ Node node;
+ DialogTouchHandler(Node n)
+ {
+ node=n;
+ }
+ public void onClick(View view)
+ {
+ if (RuleDialog.selectedRule!=null)
+ if (node==RuleDialog.selectedRule)
+ return;
+ Node sel=node;
+ while(sel.Father!=null)
+ sel=sel.Father;
+ sel.view.setTextColor(Color.RED);
+ for (Node n:sel.Children)
+ n.view.setTextColor(Color.RED);
+ if (RuleDialog.selectedRule!=null)
+ {
+ RuleDialog.selectedRule.view.setTextColor(Color.BLACK);
+ for (Node n:RuleDialog.selectedRule.Children)
+ n.view.setTextColor(Color.BLACK);
+ }
+ RuleDialog.selectedRule=sel;
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.app.FragmentManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.widget.RelativeLayout;
+import android.widget.ScrollView;
+import android.widget.Toast;
+
+import java.sql.Timestamp;
+import java.util.ArrayList;
+
+public class DrawActivity extends FragmentActivity {
+
+ static RelativeLayout globalHP; //layout delle ipotesi cancellate
+ static ScaleGestureDetector scaleGestureDetector; //zoom listener
+ static float spaceSize; //dimensione della spaziatura tra i sottoalberi
+ static float textSize=40; //dimensione del font iniziale
+ static Node selectedNode; //Node su cui è attualmente il focus
+ static Node copiedNode;//nodo copiato
+ static boolean addFakes;//booleano che segnala se bisogna aggiungere delle regole fake
+ static Border[] b; //bordi per le borderedTextView
+ static FragmentManager fragmentManager;//per i dialog
+ static Node rootNode; //radice dell'albero corrente
+ static ScrollView scroll;
+ static int nmoves=0;//numero di mosse
+ static int nerrors=0;//nomero di errori
+ static long startTime;//tempo di inizio dell'esercizio
+ static RelativeLayout globalR; //layout globale contenente l'albero
+ static int globalId =10; //variabile incrementale per l'assegnazione di ID univoci
+ static DisplayMetrics v = new DisplayMetrics();//altezza lunghezza e densità dello schermo
+
+ static String user=null;
+ static String pass=null;
+ static String sessionKey=null;
+ static String nomeEs=null;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ //routine standard per la create
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_my);
+
+ //recupero e setto le variabili globali
+ getWindowManager().getDefaultDisplay().getMetrics(v);
+ globalHP = (RelativeLayout) findViewById(R.id.hpscroll);
+ globalR = (RelativeLayout) findViewById(R.id.global);
+ spaceSize = 2*(textSize/v.density);
+ fragmentManager=getFragmentManager();
+ copiedNode=null;
+ scroll=(ScrollView)findViewById(R.id.vscroll);
+ startTime=time();
+ b=new Border[1];
+ b[0]=new Border(BorderedTextView.BORDER_TOP);
+ b[0].setWidth(2);
+ Bundle dati=getIntent().getExtras();
+ nomeEs=dati.getString("nomeEs");
+ user=dati.getString("user");
+ pass=dati.getString("pass");
+ sessionKey=dati.getString("sessionKey");
+
+ //Creazione dell'albero: setto il rootNode e creo la Formula di partenza (F)
+ if(!populateTree())
+ return;
+
+ //Creazione dell'albero: setto i campi della view
+ BorderedTextView rootView=new BorderedTextView(this);
+ rootView.setId(globalId);
+ globalId++;
+ selectedNode=null;
+ addFakes=false; //di default non vengono aggiunte regole false
+ rootNode.setView(rootView,globalR);
+ rootNode.handler=new touchnodeHandler(rootNode);
+ startDraw();
+
+ //imposto il listener per il pinch zoom
+ scaleGestureDetector = new ScaleGestureDetector(this, new simpleOnScaleGestureListener());
+ }
+ @Override
+ public void onConfigurationChanged(Configuration configuration) //rotazione dello schermo: restore dell'albero
+ {
+ super.onConfigurationChanged(configuration);
+ getWindowManager().getDefaultDisplay().getMetrics(v);
+ DrawActivity.rootNode.Clean();
+ DrawActivity.startDraw();
+ }
+ public static void startDraw()
+ {
+ RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ final int halfScreen=Math.round((v.widthPixels / 2) - rootNode.getBaseWidth() / 2); //calcolo la metà dello schermo per il calcolo dei margins della scrollView
+ int leftSubTree=(Math.round(rootNode.getLeftOffset() - rootNode.getUpLine() / 2 + (rootNode.getBaseWidth() / 2)) + 40); //sottoalbero sinistro del rootNode più un padding di 40px
+ lp.setMargins(Math.max(halfScreen,leftSubTree),0, 0, 0);
+ lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, rootNode.view.getId());
+ rootNode.view.setLayoutParams(lp);
+ rootNode.view.setBorders(b);
+ rootNode.view.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
+ rootNode.view.setWidth(Math.round(rootNode.getLineWidth())); //setto la larghezza della view al contenuto della linea
+ rootNode.view.setGravity(Gravity.CENTER); //formula al centro della sua overline
+ rootNode.view.setText(rootNode.F.toString()); //setta il contenuto della formula
+ globalR.addView(rootNode.view);
+ //inserisco un listener a rootView da attivare quando sono state fissate le coordinate nel RelativeLayout
+ rootNode.view.getViewTreeObserver().addOnGlobalLayoutListener(
+ new ViewTreeObserver.OnGlobalLayoutListener()
+ {
+ @Override
+ public void onGlobalLayout()
+ {
+ globalR.setPadding(0,0,(int)Math.max(rootNode.getRightOffset(),halfScreen),0);
+ 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.
+ globalR.requestLayout(); //aggiorna i parametri e le dimensioni del RelativeLayout
+ if (rootNode.treeHeight()< 3)
+ scroll.fullScroll(ScrollView.FOCUS_DOWN);
+ rootNode.view.setOnClickListener(rootNode.handler);
+ rootNode.hasFocus=true; //di default, la radice ha inizialmente il focus.
+ rootNode.view.getViewTreeObserver().removeOnGlobalLayoutListener(this); //rimuove il listener per evitare che la funzione parta nuovamente
+ rootNode.Draw();
+
+ }
+ });
+ }
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.my, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ // TODO Auto-generated method stub
+ scaleGestureDetector.onTouchEvent(event);
+ return true;
+ }
+
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent event) {
+ super.dispatchTouchEvent(event);
+ return (scaleGestureDetector.onTouchEvent(event));
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ int id = item.getItemId();
+ if(id==R.id.action_paste) //incolla sottoalbero
+ {
+ if (DrawActivity.copiedNode == null) //non ci sono nodi da copiare
+ return true;
+ else if (!checkHP(DrawActivity.copiedNode, DrawActivity.selectedNode)) //ipotesi incompatibili: impossibile incollare in questo punto
+ return true;
+ else {
+ Node tmp = duplicateNode(DrawActivity.copiedNode); //duplica il nodo copiato
+ DrawActivity.selectedNode.ruleName=tmp.ruleName;
+ DrawActivity.selectedNode.Children = new ArrayList<Node>();
+ for (Node c:tmp.Children)
+ DrawActivity.selectedNode.addChild(c); //incolla il sottoalbero del nodo copiato nella posizione richiesta
+ DrawActivity.rootNode.Clean();
+ DrawActivity.startDraw();
+ }
+ }
+ else if(id==R.id.abandon)
+ { //abbandona esercizio e torna alla view con la lista degli esercizi
+ Intent i = new Intent(globalHP.getContext(), aggiornamento.class);
+ i.putExtra("user", user);
+ i.putExtra("pass", pass);
+ i.putExtra("sessionKey", sessionKey);
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ globalHP.getContext().startActivity(i);
+ }
+ return true;
+ }
+
+
+ public boolean checkHP(Node source,Node target) //controlla se le ipotesi di source sono compatibili per una copia in target
+ {
+ boolean found=false;
+ if (!source.F.toString().equals(target.F.toString())) //se i nodi non hanno la stessa formula la copia è automaticamente impossibile
+ return false;
+ for (Hypothesis sourceHp:source.NodeHP) {
+ for (Hypothesis destHp : target.NodeHP) {
+ 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).
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return false;
+ else found=false;
+ }
+ return true;
+ }
+
+ public Node duplicateNode(Node src) //metodo di supporto che duplica un nodo
+ {
+ Node tmp=new Node(src.F);
+ tmp.addHPList(src.NodeHP);
+ tmp.ruleName=src.ruleName;
+ for (Node n:src.Children) {
+ tmp.addChild(duplicateNode(n));
+ }
+ return tmp;
+ }
+
+ public class simpleOnScaleGestureListener extends
+ ScaleGestureDetector.SimpleOnScaleGestureListener {
+
+ @Override
+ public boolean onScale(ScaleGestureDetector detector) {
+ float factor=detector.getScaleFactor();
+ if (textSize>65 && factor>1) //font troppo grande: impedisco aumento
+ return true;
+ if (textSize<15 && factor<1) //font troppo piccolo: impedisco riduzione
+ return true;
+ rootNode.Refactor(); //risetta i campi dell'albero a FIELD_UNSET
+ RelativeLayout.LayoutParams lp=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ DrawActivity.spaceSize=(DrawActivity.spaceSize*factor);
+ DrawActivity.textSize=(DrawActivity.textSize*factor);
+ int halfScreen=Math.round((v.widthPixels / 2)-rootNode.getBaseWidth()/2);
+ int leftSubTree=(Math.round(rootNode.getLeftOffset() - rootNode.getUpLine() / 2 + (rootNode.getBaseWidth() / 2)) + 40);
+ globalR.setPadding(0,0,(int)Math.max(rootNode.getRightOffset(),halfScreen),0);
+ lp.setMargins(Math.max(halfScreen,leftSubTree),0, 0, 0);
+ lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, rootNode.view.getId());
+ rootNode.view.setLayoutParams(lp);
+ rootNode.view.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
+ rootNode.view.setWidth(Math.round(rootNode.getLineWidth())); //setto la larghezza della view al contenuto della linea
+ rootNode.Resize(); //ricorsivamente sistema i fontsize, le larghezze e le posizioni delle view nell'albero
+ return true;
+ }
+ }
+ public static void finishedTree(Context context) {
+ if (!rootNode.isCorrect()) {
+ Toast.makeText(context, "Esercizio errato! Ricontrolla i passaggi fatti e riprova", Toast.LENGTH_LONG).show();
+ } else {
+ long endTime = time();
+ int second= (int) ((endTime-startTime)/1000);
+ int minute=second/60;
+ Toast.makeText(context, "Esercizio completato in " + Integer.toString(nmoves) + " mosse!", Toast.LENGTH_LONG).show();
+ Toast.makeText(context, "Hai commesso " + Integer.toString(nerrors) + " errori!", Toast.LENGTH_LONG).show();
+ Toast.makeText(context, "Numero nodi dell'albero: " + Integer.toString(rootNode.count()), Toast.LENGTH_LONG).show();
+ Toast.makeText(context, "Tempo impiegato: " + Integer.toString(minute) + " minuti e " + Integer.toString(second-(minute*60)) + " secondi", Toast.LENGTH_LONG).show();
+ //aggiungo l'esercizio al database
+ int voto=valutazione.voto(nomeEs,nmoves,second,rootNode.count(),nerrors);
+ personalDBHelper db = new personalDBHelper(context);
+ db.add(user, nomeEs, MD5.digest(nomeEs), 0.0, voto, 0);
+ nmoves = 0;
+ Intent i = new Intent(context, aggiornamento.class);
+ i.putExtra("user", user);
+ i.putExtra("pass", pass);
+ i.putExtra("sessionKey", sessionKey);
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(i);
+ }
+ }
+ public boolean populateTree() {
+
+ rootNode = parser.root(nomeEs);
+ if(rootNode==null)
+ {
+ Toast.makeText(this, "Errore nell'apertura del file", Toast.LENGTH_LONG).show();
+ Intent i = new Intent(this, aggiornamento.class);
+ i.putExtra("user", user);
+ i.putExtra("pass", pass);
+ i.putExtra("sessionKey", sessionKey);
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ this.startActivity(i);
+ return false;
+ }
+ for (Hypothesis h:rootNode.NodeHP)
+ h.fromNode=rootNode;
+ return true;
+ }
+ public static long time()
+ {
+ java.util.Date date= new java.util.Date();
+ Timestamp now=new Timestamp(date.getTime());
+ return now.getTime();
+ }
+
+}
+
--- /dev/null
+package com.example.furt.myapplication;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public interface EliminationRule
+{
+ public String getName();
+ public Node createNodes(Formula F, askFormula ask);
+}
+
--- /dev/null
+package com.example.furt.myapplication;
+
+public interface FView
+{
+ @Override
+ public String toString();
+ public String toStringDeleted();
+ String Draw(int priority);
+ public float size();
+ public float height();
+ public float sizeDeleted();
+
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import java.util.List;
+
+public interface Formula extends FView{
+ public List<IntroductionRule> introductionRules();
+ public List<EliminationRule> EliminationRules();
+ public boolean Fill(Formula F);
+ public boolean setCursor();
+ public Formula duplicate();
+}
+
--- /dev/null
+package com.example.furt.myapplication;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FormulaAnd extends GenericFormula implements Formula
+{
+ Formula leftF;
+ Formula rightF;
+ int leftPriority;
+ int rightPriority;
+ FormulaAnd(Formula F1,Formula F2)
+ {
+ leftF=F1;
+ rightF=F2;
+ priority=15;
+ leftPriority=15;
+ rightPriority=16;
+ }
+ @Override
+ public String Draw(int p)
+ {
+ if (priority >= p)
+ return leftF.Draw(leftPriority)+"∧"+rightF.Draw(rightPriority);
+ else
+ return("(")+leftF.Draw(leftPriority)+"∧"+rightF.Draw(rightPriority)+")";
+ }
+
+ @Override
+ public List<IntroductionRule> introductionRules()
+ {
+ List<IntroductionRule> rules=new ArrayList<IntroductionRule>();
+ rules.addAll(super.introductionRules());
+ RuleIntroduction andIntroduction=new RuleIntroduction("∧i",5);
+ Node Left=new Node(leftF);
+ Node Right=new Node(rightF);
+ Node thisNode=new Node(this);
+ thisNode.addChild(Left);
+ thisNode.addChild(Right);
+ andIntroduction.tempRule=thisNode;
+ rules.add(andIntroduction);
+ return rules;
+ }
+ public List<EliminationRule> EliminationRules()
+ {
+ List<EliminationRule> nodes=new ArrayList<EliminationRule>();
+ nodes.add(new RuleAndElimination(this));
+ return nodes;
+ }
+
+ @Override
+ public boolean Fill(Formula Filler) {
+ if(leftF.toString().equals("_")) {
+ this.leftF = Filler;
+ return true;
+ }
+ else if(rightF.toString().equals("_")) {
+ this.rightF = Filler;
+ return true;
+ }
+ return leftF.Fill(Filler) || rightF.Fill(Filler);
+ }
+
+ @Override
+ public boolean setCursor() {
+ return leftF.setCursor() || rightF.setCursor();
+ }
+
+ @Override
+ public Formula duplicate() {
+ return new FormulaAnd(leftF.duplicate(),rightF.duplicate());
+ }
+}
+
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.graphics.Paint;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FormulaBOT extends GenericFormula implements Formula{
+ Paint p=new Paint();
+ FormulaBOT()
+ {
+ priority=100;
+ }
+
+ @Override
+ public String Draw(int p)
+ {
+ return "⊥";
+ }
+
+ public List<IntroductionRule> introductionRules(){
+ List<IntroductionRule> nodes=new ArrayList<IntroductionRule>();
+ return nodes;
+ }
+ public List<EliminationRule> EliminationRules()
+ {
+ List<EliminationRule> nodes=new ArrayList<EliminationRule>();
+ nodes.add(new RuleBotElimination(this));
+ return nodes;
+ }
+
+ @Override
+ public boolean Fill(Formula F) {
+ return false;
+ }
+
+ @Override
+ public boolean setCursor() {
+ return false;
+ }
+
+ @Override
+ public Formula duplicate() {
+ return new FormulaBOT();
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FormulaImpl extends GenericFormula implements Formula
+{
+ Formula leftF;
+ Formula rightF;
+ int leftPriority;
+ int rightPriority;
+ FormulaImpl(Formula F1,Formula F2)
+ {
+ priority=10;
+ leftF=F1;
+ rightF=F2;
+ leftPriority=11;
+ rightPriority=10;
+ }
+ @Override
+ public String Draw(int p)
+ {
+ if (priority >= p)
+ return leftF.Draw(leftPriority)+"⇒"+rightF.Draw(rightPriority);
+ else
+ return("(")+leftF.Draw(leftPriority)+"⇒"+rightF.Draw(rightPriority)+")";
+ }
+
+ public List<IntroductionRule> introductionRules(){
+ List<IntroductionRule> nodes=new ArrayList<IntroductionRule>();
+ nodes.addAll(super.introductionRules());
+ RuleIntroduction implIntro=new RuleIntroduction("⇒i",10);
+ Node ImplN=new Node(rightF);
+ List<Formula> implHP=new ArrayList<Formula>();
+ implHP.add(leftF);
+ ImplN.addHPFormula(implHP,true);
+ Node thisNode=new Node(this);
+ thisNode.addChild(ImplN);
+ implIntro.tempRule=thisNode;
+ nodes.add(implIntro);
+ return nodes;
+ }
+ public List<EliminationRule> EliminationRules()
+ {
+ List<EliminationRule> nodes=new ArrayList<EliminationRule>();
+ nodes.add(new RuleImplElimination(this));
+ return nodes;
+ }
+ @Override
+ public boolean Fill(Formula Filler) {
+ if(leftF.toString().equals("_")) {
+ this.leftF = Filler;
+ return true;
+ }
+ else if(rightF.toString().equals("_")) {
+ this.rightF = Filler;
+ return true;
+ }
+ return leftF.Fill(Filler) || rightF.Fill(Filler);
+ }
+
+ @Override
+ public boolean setCursor() {
+ return leftF.setCursor() || rightF.setCursor();
+ }
+
+ @Override
+ public Formula duplicate() {
+ return new FormulaImpl(leftF.duplicate(),rightF.duplicate());
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.graphics.Paint;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FormulaNot extends GenericFormula implements Formula{
+ Paint p=new Paint();
+ Formula Operand;
+ int priority;
+ int argPriority;
+ FormulaNot(Formula F)
+ {
+ Operand=F;
+ priority=20;
+ argPriority=100;
+ }
+ @Override
+ public String Draw(int p)
+ {
+ if (priority >= p)
+ return "¬"+Operand.Draw(20);
+ else
+ return("¬("+Operand.Draw(20)+")");
+ }
+
+ public List<IntroductionRule> introductionRules(){
+ List<IntroductionRule> nodes=new ArrayList<IntroductionRule>();
+ RuleIntroduction notIntro=new RuleIntroduction("¬i",4);
+ Node notN=new Node(new FormulaBOT());
+ List<Formula> notHP=new ArrayList<Formula>();
+ notHP.add(Operand);
+ notN.addHPFormula(notHP,true);
+ Node thisNode=new Node(this);
+ thisNode.addChild(notN);
+ notIntro.tempRule=thisNode;
+ nodes.add(notIntro);
+ return nodes;
+ }
+ public List<EliminationRule> EliminationRules()
+ {
+ List<EliminationRule> nodes=new ArrayList<EliminationRule>();
+ nodes.add(new RuleNotElimination(this));
+ return nodes;
+ }
+
+ @Override
+ public boolean Fill(Formula Filler) {
+ if(Operand.toString().equals("_")) {
+ Operand = Filler;
+ return true;
+ }
+ return Operand.Fill(Filler);
+ }
+
+ @Override
+ public boolean setCursor() {
+ return Operand.setCursor();
+ }
+
+ @Override
+ public Formula duplicate() {
+ return new FormulaNot(Operand.duplicate());
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.example.furt.myapplication;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FormulaOr extends GenericFormula implements Formula
+{
+ Formula leftF;
+ Formula rightF;
+ int leftPriority;
+ int rightPriority;
+ FormulaOr(Formula F1,Formula F2)
+ {
+ priority=13;
+ leftF=F1;
+ rightF=F2;
+ leftPriority=13;
+ rightPriority=14;
+ }
+
+ @Override
+ public String Draw(int p)
+ {
+ if (priority >= p)
+ return leftF.Draw(leftPriority)+"∨"+rightF.Draw(rightPriority);
+ else
+ return("(")+leftF.Draw(leftPriority)+"∨"+rightF.Draw(rightPriority)+")";
+ }
+
+ public List<IntroductionRule> introductionRules(){
+ List<IntroductionRule> nodes=new ArrayList<IntroductionRule>();
+ nodes.addAll(super.introductionRules());
+ RuleIntroduction orIntroductionLeft=new RuleIntroduction("∨i(L)",6);
+ Node orLeft=new Node(leftF);
+ Node thisNodeL=new Node(this);
+ thisNodeL.addChild(orLeft);
+ orIntroductionLeft.tempRule=thisNodeL;
+ nodes.add(orIntroductionLeft);
+ RuleIntroduction orIntroductionRight=new RuleIntroduction("∨i(R)",5);
+ Node orRight=new Node(rightF);
+ Node thisNodeR=new Node(this);
+ thisNodeR.addChild(orRight);
+ orIntroductionRight.tempRule=thisNodeR;
+ nodes.add(orIntroductionRight);
+ return nodes;
+ }
+
+ public List<EliminationRule> EliminationRules()
+ {
+ List<EliminationRule> nodes=new ArrayList<EliminationRule>();
+ nodes.add(new RuleOrElimination(this));
+ return nodes;
+ }
+
+ @Override
+ public boolean Fill(Formula Filler) {
+ if(leftF.toString().equals("_")) {
+ this.leftF = Filler;
+ return true;
+ }
+ else if(rightF.toString().equals("_")) {
+ this.rightF = Filler;
+ return true;
+ }
+ return leftF.Fill(Filler) || rightF.Fill(Filler);
+ }
+
+ @Override
+ public boolean setCursor() {
+ return leftF.setCursor() || rightF.setCursor();
+ }
+
+ @Override
+ public Formula duplicate() {
+ return new FormulaOr(leftF.duplicate(),rightF.duplicate());
+ }
+}
+
--- /dev/null
+package com.example.furt.myapplication;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class FormulaTOP extends GenericFormula implements Formula{
+
+ FormulaTOP()
+ {
+ priority=100;
+ }
+
+ @Override
+ public String Draw(int p){return "Ț";}
+
+ public List<IntroductionRule> introductionRules(){
+ List<IntroductionRule> nodes=new ArrayList<IntroductionRule>();
+ nodes.addAll(super.introductionRules());
+ return nodes;
+ }
+
+ @Override
+ public boolean Fill(Formula F) {
+ return false;
+ }
+
+ @Override
+ public boolean setCursor() {
+ return false;
+ }
+
+ @Override
+ public Formula duplicate() {
+ return new FormulaTOP();
+ }
+
+ public List<EliminationRule> eliminationRules(){
+ List<EliminationRule> nodes=new ArrayList<EliminationRule>();
+ return nodes;
+ }
+
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.graphics.Paint;
+import android.graphics.Rect;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class GenericFormula implements Formula
+{
+ Paint p=new Paint();
+ int priority;
+ public String Draw(int p)
+ {
+ return "";
+ }
+ public String toString(){return Draw(0);}
+ public float size(){
+ p.setTextSize(DrawActivity.textSize);
+ return p.measureText(toString())+(float)(p.measureText(toString())*0.20);
+ }
+ public float sizeDeleted()
+ {
+ p.setTextSize(DrawActivity.textSize);
+ return p.measureText(toStringDeleted())+(float)(p.measureText(toStringDeleted())*0.20);
+ }
+ public String toStringDeleted()
+ {
+ return "["+toString()+"]";
+ }
+ public float height()
+ {
+ p.setTextSize(DrawActivity.textSize);
+ Rect bounds=new Rect();
+ p.getTextBounds(toString(),0,toString().length(),bounds);
+ return (float)((bounds.height()+((float)0.20*bounds.height()))*1.5);
+ }
+ public List<IntroductionRule> introductionRules(){
+ List<IntroductionRule> rules=new ArrayList<IntroductionRule>();
+ Node thisNode=new Node(this);
+ RuleIntroduction RAA=new RuleIntroduction("RAA",0); //R.A.A.
+ Node RAAnode=new Node(new FormulaBOT()); //Formula=Bottom
+ List<Formula> RAAhp=new ArrayList<Formula>(); //Tutte le ipotesi del nodo precedente
+ RAAhp.add(new FormulaNot(this)); //Più la negazione del nodo attuale
+ RAAnode.addHPFormula(RAAhp,true);
+ thisNode.addChild(RAAnode);
+ RAA.tempRule=thisNode;
+ rules.add(RAA);
+ /*
+ Node thisFakeNode=new Node(this);
+ RuleIntroduction fakeRAA=new RuleIntroduction("RAA",0,true); //fake R.A.A.
+ Node fakeRAAnode=new Node(new FormulaNot(this)); //Formula=!F
+ thisFakeNode.addChild(fakeRAAnode);
+ fakeRAA.tempRule=thisFakeNode;
+ rules.add(fakeRAA);
+ */
+ return rules;
+ }
+ public List<EliminationRule> EliminationRules(){
+ List<EliminationRule> nodes=new ArrayList<EliminationRule>();
+ return nodes;
+ }
+
+ @Override
+ public boolean Fill(Formula F) {
+ return false;
+ }
+
+ @Override
+ public boolean setCursor() {
+ return false;
+ }
+
+ @Override
+ public Formula duplicate() {
+ return null;
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+public class Hypothesis
+{
+ Formula HP;
+ boolean isDeleted;
+ Node fromNode;
+ Hypothesis(Formula F,boolean d)
+ {
+ HP=F;
+ isDeleted=d;
+ fromNode=null;
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.example.furt.myapplication;
+
+public interface IntroductionRule
+{
+ int getPriority();
+ String getName();
+ public Node createNodes(askFormula ask);
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Literal extends GenericFormula implements Formula
+{
+ String L;
+ Literal(char c)
+ {
+ priority=100;
+ L=c+"";
+ }
+ @Override
+ public String Draw(int p){return L;}
+
+ public List<IntroductionRule> introductionRules(){
+ List<IntroductionRule> nodes=new ArrayList<IntroductionRule>();
+ nodes.addAll(super.introductionRules());
+ return nodes;
+ }
+
+ @Override
+ public boolean Fill(Formula F) {
+ return false;
+ }
+
+ public boolean isCompatible(Node n) {
+ return true;
+ }
+
+ @Override
+ public Formula duplicate() {
+ return new Literal(this.L.charAt(0));
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.graphics.Color;
+import android.os.Handler;
+import android.view.View;
+
+public class LongHPClick implements View.OnLongClickListener {
+
+ Node n;
+ LongHPClick(Node node)
+ {
+ n=node;
+ }
+ @Override
+ public boolean onLongClick(View v) {
+ n.view.setTextColor(Color.BLUE);
+ final Handler handler = new Handler();
+ handler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ n.view.setTextColor(Color.BLACK);
+ }
+ }, 1000);
+ return true;
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.os.Environment;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.security.MessageDigest;
+
+
+public class MD5 {
+
+ MD5(){}
+
+ /*public static String digest(String fileName) throws NoSuchAlgorithmException, IOException
+ {
+
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ return getDigest(new FileInputStream("/var/www/html/esercizi/"+fileName), md, 2048);
+ }
+
+ public static String getDigest(InputStream is, MessageDigest md, int byteArraySize) throws NoSuchAlgorithmException, IOException
+ {
+ md.reset();
+ byte[] bytes = new byte[byteArraySize];
+ int numBytes;
+ while ((numBytes = is.read(bytes)) != -1) {
+ md.update(bytes, 0, numBytes);
+ }
+ byte[] digest = md.digest();
+ String result = new String(Hex.encodeHex(digest));
+ return result;
+ }*/
+ public static String digest(String filePath) {
+ InputStream inputStream = null;
+ try {
+ inputStream = new FileInputStream(Environment.getExternalStorageDirectory()+"/tesiEs/"+filePath);
+ byte[] buffer = new byte[1024];
+ MessageDigest digest = MessageDigest.getInstance("MD5");
+ int numRead = 0;
+ while (numRead != -1) {
+ numRead = inputStream.read(buffer);
+ if (numRead > 0)
+ digest.update(buffer, 0, numRead);
+ }
+ byte [] md5Bytes = digest.digest();
+ return convertHashToString(md5Bytes);
+ } catch (Exception e) {
+ return null;
+ } finally {
+ if (inputStream != null) {
+ try {
+ inputStream.close();
+ } catch (Exception e) { }
+ }
+ }
+ }
+
+ private static String convertHashToString(byte[] md5Bytes) {
+ String returnVal = "";
+ for (int i = 0; i < md5Bytes.length; i++) {
+ returnVal += Integer.toString(( md5Bytes[i] & 0xff ) + 0x100, 16).substring(1);
+ }
+ return returnVal;
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.IBinder;
+import android.util.Log;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.Scanner;
+
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+
+public class MyService extends Service {
+
+ @Override
+ public int onStartCommand(final Intent intent, int flags, int startId)
+ {
+ final Context context=getApplicationContext();
+ /*System.setProperty("javax.net.ssl.trustStore", "mysrvkeystore");
+ //Log.e("onStartCommand",""+R.raw.mysrvkeystore);
+ System.setProperty("javax.net.ssl.trustStorePassword", "123456");
+
+
+
+ String inviotmp = intent.getStringExtra("code") + intent.getStringExtra("varInvio");
+
+ if(intent.getStringExtra("code").charAt(0)!='2')
+ inviotmp = inviotmp + intent.getStringExtra("varInvio2");
+ final String invio=inviotmp;
+ final Thread readthread;
+ readthread = new Thread(new Runnable() {
+ public void run() {
+ SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
+ //Socket socket = null;
+ SSLSocket socket = null;
+ try {
+ int port = 25000;
+ // socket = new Socket("10.0.0.2", port);
+ socket=(SSLSocket) sslsocketfactory.createSocket("10.0.0.2", port); //Send the message to the server
+ OutputStream os = socket.getOutputStream();
+ OutputStreamWriter osw = new OutputStreamWriter(os);
+ BufferedWriter bw = new BufferedWriter(osw);
+
+ //String number = "2";
+
+ String sendMessage = invio+"\n";
+ bw.write(sendMessage+"\n");
+ bw.flush();
+ System.out.println("Message sent to the server : " + sendMessage);
+
+ //Get the return message from the server
+ InputStream is = socket.getInputStream();
+ InputStreamReader isr = new InputStreamReader(is);
+ BufferedReader br = new BufferedReader(isr);
+ String message;
+ message = br.readLine();
+ System.out.println("Message received from the server : " + message);
+ } catch (Exception exception) {
+ exception.printStackTrace();
+ } finally {
+ //Closing the socket
+ try {
+ socket.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ });
+
+ readthread.start();*/
+ final Thread readthread;
+ readthread = new Thread(new Runnable() {
+ public void run() {
+ InputStream certificato = getResources().openRawResource(R.raw.keystore);
+ KeyStore trustStore = null;
+ try
+ {
+ trustStore = KeyStore.getInstance("BKS");
+ trustStore.load(certificato, "123stella".toCharArray());
+ SSLSocketFactory fs = (SSLSocketFactory) SSLSocketFactory.getDefault();
+ SSLSocket socket = (SSLSocket) fs.createSocket("10.0.0.2", 25000);
+ Log.e("", "miracolo");
+
+ InputStream inputstream = System.in;
+ InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
+ BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
+
+ OutputStream os = socket.getOutputStream();
+ OutputStreamWriter osw = new OutputStreamWriter(os);
+ BufferedWriter bw = new BufferedWriter(osw);
+
+ String sendMessage ="brova";
+ bw.write(sendMessage+"\n");
+ bw.flush();
+
+ System.out.println("Message sent to the server : " + sendMessage);
+ }
+ catch (KeyStoreException e)
+ {
+ e.printStackTrace();
+ }
+ catch (CertificateException e)
+ {
+ e.printStackTrace();
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ e.printStackTrace();
+ }
+ catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ readthread.start();
+ return 0;
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.graphics.Color;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class Node implements Tree {
+
+ static int FIELD_UNSET = -1;
+ static int OPEN=0;
+ static int FAKE=1;
+ static int CLOSED=2;
+ static int FAKE_CLOSED=3;
+ static int CANCELED=4;
+ static int FAKE_CANCELED=5;
+
+ Formula F; //formula legata al nodo
+ String ruleName; //nome della regola associata a questo nodo
+ List<Node> Children = new ArrayList<Node>(); //Nodi figli
+ List<Hypothesis> NodeHP = new ArrayList<Hypothesis>(); //ipotesi associate
+ Node Father; //puntatore al padre
+ View.OnClickListener handler; //touchHandler per far comparire il pop-up delle regole
+ boolean hasFocus; //indica se questo nodo è quello selezionato
+ int status; //stato del nodo (chiuso, aperto,fake...)
+ RelativeLayout global; //layout in cui si trova l'albero
+ BorderedTextView view; //view contenente questo oggetto
+ TextView ruleView; //view contenente l'intestazione della regola
+
+ float baseLine;
+ float leftOffset;
+ float rightOffset;
+ float maxWidth;
+
+ Node(Formula F) {
+ this.F = F;
+ view = null;
+ handler = null;
+ ruleName="";
+ Father = null;
+ status=OPEN;
+ hasFocus = false;
+ leftOffset = 0;
+ rightOffset = 0;
+ baseLine = getBaseWidth();
+ maxWidth = baseLine;
+ }
+
+ /**************SetView**************+*****/
+ /*****************************************/
+ /*******Setta la TextView del node ******/
+ /** e il layout in cui deve comparire ***/
+ /*****************************************/
+
+ public void setView(BorderedTextView t,RelativeLayout r) {
+ view = t;
+ ruleView =new TextView(t.getContext());
+ global=r;
+ }
+
+
+ /**************Count****************+*****/
+ /*****************************************/
+ /*******Restituisce il numero di ******/
+ /*************nodi dell'albero ***********/
+ /*****************************************/
+
+ int count()
+ {
+ int ris=1;
+ for (Node n:Children)
+ ris+=n.count();
+ return ris;
+ }
+
+ public void addHPFormula(List<Formula>List,boolean deleted) {
+ loop:for (Formula newHp:List) {
+ for (Hypothesis oldHp: NodeHP) {
+ if (oldHp.HP.toString().equals(newHp.toString())) {
+ continue loop;
+ }
+ }
+ NodeHP.add(new Hypothesis(newHp, deleted));
+ }
+ }
+
+ public void addHPList(List<Hypothesis>List) {
+ loop:for (Hypothesis newHp:List) {
+ for (Hypothesis oldHp: NodeHP) {
+ if (oldHp.HP.toString().equals(newHp.HP.toString())) {
+ continue loop;
+ }
+ }
+ Hypothesis copyHP=new Hypothesis(newHp.HP, newHp.isDeleted);
+ copyHP.fromNode=newHp.fromNode;
+ NodeHP.add(copyHP);
+ }
+ }
+
+ public boolean searchFocus(Node caller)
+ {
+ if (Children.size()==0) //caso base: controllo se il focus può essere su di me
+ {
+ if (status!=OPEN && status!=FAKE) //nodo chiuso: il focus non può essere su di me
+ return false;
+ hasFocus=true; //posso assumere il focus
+ if (handler!=null)
+ handler.onClick(view);
+ return true;
+ }
+ //passo induttivo: vado su tutti i miei figli, poi su mio padre. Termino se il padre è null.
+ for (Node n:Children) {
+ if (caller != null)
+ if (n == caller) //per ogni figlio diverso dal chiamante
+ {
+ continue;
+ }
+ if(n.searchFocus(null))
+ return true;
+ }
+ if (caller==null) //ero stato chiamato da mio padre: è inutile richiamarlo
+ return false;
+ else if (Father==null)
+ return false; //padre null: l'albero è dimostrato e non ci sono nodi a cui dare il focus.
+ else
+ return Father.searchFocus(this); //propaga il searchFocus sul padre
+ }
+ public void addChild(Node N) {
+ N.Father = this;
+ Children.add(N);
+ Node tmp=Father;
+ baseLine=FIELD_UNSET;
+ maxWidth=FIELD_UNSET;
+ leftOffset=FIELD_UNSET;
+ rightOffset=FIELD_UNSET;
+ while (tmp!=null)
+ {
+ tmp.baseLine=FIELD_UNSET;
+ tmp.leftOffset=FIELD_UNSET;
+ tmp.rightOffset=FIELD_UNSET;
+ tmp.maxWidth=FIELD_UNSET;
+ tmp=tmp.Father;
+ }
+ }
+
+ public float getBaseWidth() {
+ return F.size();
+ }
+
+ public float getMaxWidth() //ritorna la larghezza massima del sottoalbero
+ {
+ if (maxWidth!=FIELD_UNSET)
+ return maxWidth;
+ else
+ maxWidth=getLeftOffset()+getBaseWidth()+getRightOffset();
+ return (maxWidth);
+ }
+
+ public float getLineWidth()
+ {
+ if (baseLine!=FIELD_UNSET)
+ return baseLine;
+ else
+ {
+ float spaceSize = DrawActivity.spaceSize;
+ if (Children.size() == 0)
+ return (getBaseWidth());
+ int res = 0;
+ for (Node n:Children)
+ res += (n.getMaxWidth()) + spaceSize;
+ res -= spaceSize;
+ res -= Children.get(0).getLeftOffset();
+ res -= Children.get(Children.size() - 1).getRightOffset();
+ baseLine=Math.max(res,getBaseWidth());
+ return baseLine;
+ }
+ }
+ public float getUpLine()
+ {
+ float spaceSize= DrawActivity.spaceSize;
+ if (Children.size()==0)
+ return(getBaseWidth());
+ int res=0;
+ for(Node n:Children)
+ res+=(n.getMaxWidth())+spaceSize;
+ res-=spaceSize;
+ res-=Children.get(0).getLeftOffset();
+ res-=Children.get(Children.size()-1).getRightOffset();
+ return res;
+ }
+ public float getLeftOffset() {
+ if (leftOffset != FIELD_UNSET) {
+ return leftOffset;
+ }
+ else {
+ if (Children.size() == 0) //foglia
+ leftOffset=0;
+ else
+ leftOffset=Math.max(Children.get(0).getLeftOffset() + ((getUpLine() - getBaseWidth()) / 2),0);
+ return leftOffset;
+ }
+ }
+
+ public float getMaxHeight()
+ {
+ float baseRes=F.height();
+ float res=baseRes;
+ for (Node n:Children)
+ {
+ float tempH=n.getMaxHeight()+baseRes;
+ if(tempH>res)
+ res=tempH;
+ }
+ return res;
+ }
+ public float getRightOffset()
+ {
+ if (rightOffset!=FIELD_UNSET)
+ return rightOffset;
+ else {
+ if (Children.size() == 0) //foglia
+ rightOffset=0;
+ else
+ rightOffset=Math.max(Children.get(Children.size() - 1).getRightOffset() + ((getUpLine() - getBaseWidth()) / 2),0);
+ return rightOffset;
+ }
+ }
+ void Refactor()
+ {
+ baseLine=FIELD_UNSET;
+ leftOffset=FIELD_UNSET;
+ rightOffset=FIELD_UNSET;
+ maxWidth=FIELD_UNSET;
+ for(Node n:Children)
+ n.Refactor();
+ }
+
+ void Resize()
+ {
+ int i;
+ float interval=0; //intervallo di spazio da sommare nella creazione dei figli
+ float spaceSize= DrawActivity.spaceSize;
+ int childNo=Children.size();
+ if (childNo!=0)
+ {
+
+ ruleView.setText(ruleName);
+ ruleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, DrawActivity.textSize / 2);
+ RelativeLayout.LayoutParams intlp=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ intlp.addRule(RelativeLayout.RIGHT_OF,view.getId());
+ int sum=0;
+ sum+=F.height();
+ Node tmp=Father;
+ while (tmp!=null)
+ {
+ sum+=tmp.F.height();
+ tmp=tmp.Father;
+ }
+ intlp.setMargins(0,0,0,sum);
+ intlp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+ ruleView.setLayoutParams(intlp);
+ }
+ for (i=0;i<childNo;i++) {
+ Node newChild=Children.get(i);
+ RelativeLayout.LayoutParams lp=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ TextView childView=Children.get(i).view;
+ lp.addRule(RelativeLayout.ABOVE,view.getId());
+ if (i==0) //first child
+ {
+ float leftPos= view.getLeft()-Math.max((newChild.getLineWidth()-newChild.getBaseWidth())/2,0);
+ if (getLineWidth()>getUpLine())
+ leftPos+=((getLineWidth()-getUpLine())/2);
+ lp.setMargins(Math.round(leftPos), 0, 0, 0);
+ childView.setLeft(Math.round(leftPos));
+ }
+ else {
+ lp.setMargins(Math.round(view.getLeft() + interval), 0, 0, 0);
+ childView.setLeft(Math.round(view.getLeft() + interval));
+ }
+ childView.setLayoutParams(lp);
+ childView.setTextSize(TypedValue.COMPLEX_UNIT_PX, DrawActivity.textSize);
+
+ if(newChild.status==CANCELED || newChild.status==FAKE_CANCELED)
+ childView.setWidth((int) ((newChild.F.sizeDeleted())));
+ else
+ childView.setWidth(Math.round(newChild.getLineWidth()));
+
+ newChild.Resize();
+
+ if (i!=childNo-1) //l'ultimo figlio non ha intervalli
+ {
+ float leftOverflow=(Children.get(i+1).getLineWidth()-Children.get(i+1).getBaseWidth())/2;
+ interval += (newChild.getBaseWidth()+newChild.getRightOffset()+Children.get(i+1).getLeftOffset()-(leftOverflow));
+ interval+=spaceSize;
+ if (i!=0) //devo sommare anche il leftOverflow del nuovo figlio
+ interval+=newChild.getLeftOffset();
+ }
+
+ }
+
+ }
+
+ public int treeHeight()
+ {
+ int res=0,tmp;
+ for (Node n:Children)
+ {
+ tmp=n.treeHeight();
+ if (tmp>res)
+ res=tmp;
+ }
+ return res+1;
+ }
+ public boolean isCorrect()
+ {
+ if (status==FAKE || status==FAKE_CANCELED || status==FAKE_CLOSED)
+ return false;
+ else for (Node n:Children)
+ if (!n.isCorrect())
+ return false;
+ return true;
+
+ }
+ public void Clean()
+ {
+ global.removeAllViews();
+ }
+
+ public void Draw()
+ {
+ int i;
+ float interval=0; //intervallo di spazio da sommare nella creazione dei figli
+ float spaceSize= DrawActivity.spaceSize;
+ int childNo=Children.size();
+ if (childNo==0) //foglia: possibile ramo dimostrato
+ {
+ view.setBorders(null); //le foglie non hanno overline
+ if (status!=OPEN && status!=FAKE) { //nodo chiuso
+ view.setTextColor(Color.GRAY);
+ if (hasFocus) //avevo il focus: provo a darlo ad uno dei miei fratelli
+ {
+ if (!(Father.searchFocus(this))) {
+ DrawActivity.finishedTree(view.getContext());
+ return;
+ }
+ hasFocus = false;
+ }
+ if (status==CANCELED || status==FAKE_CANCELED) { //nodo cancellato
+ view.setWidth((int) F.sizeDeleted());
+ view.setText("[" + view.getText() + "]");
+ view.setOnClickListener(null); //rimuove eventuali listener per evitare il proseguimento dell'albero
+ }
+ return;
+ }
+ if (hasFocus && DrawActivity.selectedNode!=this)
+ handler.onClick(view);
+ else if (hasFocus) //hasFocus: must be colored red anyway
+ view.setTextColor(Color.RED);
+ return;
+ }
+
+ ruleView.setText(ruleName);
+ ruleView.setTextSize(TypedValue.COMPLEX_UNIT_PX, DrawActivity.textSize / 2);
+ RelativeLayout.LayoutParams intlp=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ intlp.addRule(RelativeLayout.RIGHT_OF,view.getId());
+ int sum=0;
+ sum+=F.height();
+ Node tmp=Father;
+ while (tmp!=null)
+ {
+ sum+=tmp.F.height();
+ tmp=tmp.Father;
+ }
+ intlp.setMargins(0,0,0,sum);
+ intlp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+ ruleView.setLayoutParams(intlp);
+ global.addView(ruleView);
+
+ /////////////////
+
+
+ hasFocus=false;
+ for (i=0;i<childNo;i++) {
+ final Node newChild=Children.get(i);
+ RelativeLayout.LayoutParams lp=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ final BorderedTextView childView=new BorderedTextView(view.getContext());
+ childView.setBorders(DrawActivity.b);
+ lp.addRule(RelativeLayout.ABOVE, view.getId());
+ if (i==0) //first child
+ {
+ float leftPos= view.getLeft()-Math.max((newChild.getLineWidth()-newChild.getBaseWidth())/2,0);
+ if (getLineWidth()>getUpLine())
+ leftPos+=((getLineWidth()-getUpLine())/2);
+
+ lp.setMargins(Math.round(leftPos), 0, 0, 0);
+ childView.setLeft(Math.round(leftPos));
+ }
+ else {
+ lp.setMargins(Math.round(view.getLeft() + interval), 0, 0, 0);
+ childView.setLeft(Math.round(view.getLeft() + interval));
+ }
+ childView.setLayoutParams(lp);
+ childView.setId(DrawActivity.globalId++);
+ childView.setText(newChild.F.toString());
+ childView.setTextSize(TypedValue.COMPLEX_UNIT_PX, DrawActivity.textSize);
+ childView.setGravity(Gravity.CENTER); //formula al centro della sua overline
+ childView.setWidth(Math.round(newChild.getLineWidth()));
+ global.addView(childView);
+ childView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ newChild.setView(childView,global);
+ if(newChild.handler==null)
+ newChild.handler=new touchnodeHandler(newChild);
+ newChild.view.setOnClickListener(newChild.handler);
+ childView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ newChild.Draw();
+ }
+ });
+ if (i!=childNo-1) //l'ultimo figlio non ha intervalli
+ {
+ float leftOverflow=Math.max((Children.get(i+1).getLineWidth()-Children.get(i+1).getBaseWidth())/2,0);
+ interval += (newChild.getBaseWidth()+newChild.getRightOffset()+Children.get(i+1).getLeftOffset()-(leftOverflow));
+ interval+=spaceSize;
+ if (i!=0) //devo sommare anche il leftOverflow del nuovo figlio
+ interval+=newChild.getLeftOffset();
+ }
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package com.example.furt.myapplication;
+
+import java.util.ArrayList;
+import java.util.List;
+public class RuleAndElimination implements EliminationRule
+{
+ String ruleName;
+ public String getName()
+ {
+ return ruleName;
+ }
+ FormulaAnd Fn;
+ RuleAndElimination(FormulaAnd F){
+ Fn=F;
+ ruleName="∧e";
+ }
+ public Node createNodes(Formula F,askFormula ask)
+ {
+ Formula C;
+ if (F==null)
+ C=ask.Ask();
+ else
+ C=F;
+ Node cNode=new Node(C);
+ if ((C.toString().equals(Fn.leftF.toString())) || (C.toString().equals(Fn.rightF.toString()))) //I can return leftAnd rule or rightAnd rule
+ {
+ cNode.addChild(new Node(Fn));
+ return cNode;
+ }
+ Node elNode=new Node(Fn);
+ List<Formula> HP=new ArrayList<Formula>();
+ HP.add(Fn.leftF);
+ HP.add(Fn.rightF);
+ cNode.addHPFormula(HP,true);
+ Node rNode=new Node(C);
+ rNode.addChild(elNode);
+ rNode.addChild(cNode);
+ rNode.ruleName=ruleName;
+ return rNode;
+ }
+}
+
+
--- /dev/null
+package com.example.furt.myapplication;
+
+public class RuleBotElimination implements EliminationRule
+{
+ String ruleName;
+ public String getName()
+ {
+ return ruleName;
+ }
+ FormulaBOT Fn;
+ RuleBotElimination(FormulaBOT F)
+ {
+ Fn=F;
+ ruleName="⊥e";
+ }
+ public Node createNodes(Formula F,askFormula ask)
+ {
+ Formula C=ask.Ask();
+ Node elNode=new Node(Fn);
+ Node rNode=new Node(C);
+ rNode.addChild(elNode);
+ rNode.ruleName=ruleName;
+ return rNode;
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.widget.RelativeLayout;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class RuleDialog extends DialogFragment {
+ List<IntroductionRule> rules;
+ static Node selectedRule;
+ boolean showAllRules;
+ public RuleDialog(List<IntroductionRule> r)
+ {
+ selectedRule=null;
+ rules=new ArrayList<IntroductionRule>();
+ rules.addAll(r);
+ showAllRules=false;
+ }
+ @Override
+ public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ // Use the Builder class for convenient dialog construction
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ LayoutInflater inflater=getActivity().getLayoutInflater();
+ View view=inflater.inflate(R.layout.ruledialog,null);
+ RelativeLayout layout=(RelativeLayout)((ViewGroup)((ViewGroup)view).getChildAt(0)).getChildAt(0);
+ int ruleInterval=50;
+ int i=0;
+ for (i=0;i<rules.size();i++) {
+ IntroductionRule rule=rules.get(i);
+ if (!showAllRules && rule.getPriority()==0)
+ continue; //only high priority: skip this node
+ final Node drawNode = rule.createNodes(new askFormula());
+ BorderedTextView t = new BorderedTextView(layout.getContext());
+ t.setId(DrawActivity.globalId);
+ DrawActivity.globalId++;
+ drawNode.setView(t, layout);
+ RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ lp.setMargins(ruleInterval, 0, 0, 0);
+ ruleInterval+=2*drawNode.getMaxWidth();
+ lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, drawNode.view.getId());
+ drawNode.view.setLayoutParams(lp);
+ drawNode.view.setBorders(DrawActivity.b);
+ drawNode.view.setTextSize(TypedValue.COMPLEX_UNIT_PX, DrawActivity.textSize);
+ drawNode.view.setWidth(Math.round(drawNode.getLineWidth())); //setto la larghezza della view al contenuto della linea
+ drawNode.view.setGravity(Gravity.CENTER); //formula al centro della sua overline
+ drawNode.view.setText(drawNode.F.toString()); //setta il contenuto della formula
+ drawNode.global.addView(drawNode.view);
+ drawNode.handler=new DialogTouchHandler(drawNode);
+ for (Node n:drawNode.Children) {
+ n.handler = new DialogTouchHandler(drawNode);
+ }
+ //inserisco un listener a rootView da attivare quando sono state fissate le coordinate nel RelativeLayout
+ drawNode.view.getViewTreeObserver().addOnGlobalLayoutListener(
+ new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ drawNode.global.setPadding(0, 0, (int) Math.max(drawNode.getRightOffset(), 50), 0); //MAXWIDTH non provoca lo scroll involontario dello schermo.
+ drawNode.global.getLayoutParams().height = (int) Math.max(100, drawNode.getMaxHeight());
+ drawNode.global.requestLayout();
+ drawNode.view.setOnClickListener(drawNode.handler);
+ drawNode.hasFocus = true;
+ drawNode.view.getViewTreeObserver().removeOnGlobalLayoutListener(this); //rimuove il listener per evitare che l'albero sia creato ad ogni modifica del layout
+ drawNode.Draw();
+ }
+ });
+ }
+ builder.setView(view);
+ builder.setTitle("Scegli una regola:")
+ .setPositiveButton("Ok", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ if (selectedRule == null) return;
+ for (Node n : selectedRule.Children) {
+ for (Hypothesis hp : n.NodeHP)
+ hp.fromNode = DrawActivity.selectedNode; //le ipotesi dei nuovi figli provengono dal nodo in cui stanno per essere inserite
+ n.addHPList(DrawActivity.selectedNode.NodeHP);
+ n.handler = null;
+ DrawActivity.selectedNode.addChild(n);
+ }
+ DrawActivity.selectedNode.hasFocus = false;
+ DrawActivity.selectedNode.ruleName = selectedRule.Children.get(0).ruleName;
+ DrawActivity.selectedNode.Children.get(0).hasFocus = true;
+ DrawActivity.nmoves++;
+ DrawActivity.rootNode.Clean();
+ DrawActivity.startDraw();
+ selectedRule=null;
+ }
+ });
+ if (!showAllRules) {
+ builder.setNeutralButton("Mostra tutte", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ showAllRules = true;
+ reboot();
+ }
+ });
+ }
+ else {
+ builder.setNeutralButton("Nascondi", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ showAllRules = false;
+ reboot();
+ }
+ });
+ }
+ builder.setNegativeButton("Annulla", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ selectedRule=null;
+ }
+ });
+ // Create the AlertDialog object and return it
+ return builder.create();
+ }
+ void reboot()
+ {
+ selectedRule=null;
+ RuleDialog ruleDialog=new RuleDialog(rules);
+ ruleDialog.showAllRules=showAllRules;
+ ruleDialog.show(DrawActivity.fragmentManager, "CIAO");
+ }
+}
+
--- /dev/null
+package com.example.furt.myapplication;
+
+public class RuleImplElimination implements EliminationRule
+{
+ String ruleName;
+ public String getName()
+ {
+ return ruleName;
+ }
+ FormulaImpl Fn;
+ RuleImplElimination(FormulaImpl F)
+ {
+ Fn=F;
+ ruleName="⇒e";
+ }
+ public Node createNodes(Formula F,askFormula ask)
+ {
+ Formula C;
+ if (F==null) {
+ C=ask.Ask();
+ if (!(C.toString().equals(Fn.rightF.toString())))
+ return null;
+ }
+ else
+ if (!(F.toString().equals(Fn.rightF.toString())))
+ return null;
+ Node elNode=new Node(Fn);
+ Node lNode=new Node(Fn.leftF);
+ Node bNode=new Node(Fn.rightF);
+ bNode.addChild(elNode);
+ bNode.addChild(lNode);
+ bNode.ruleName=ruleName;
+ return bNode;
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+//Regole di introduzione per la deduzione top-down: la formula è sempre applicabile, per cui la regola si limita
+//a chiamare la callback e restituire il sottoalbero di nodi conseguente all'applicazione della regola
+public class RuleIntroduction implements IntroductionRule
+{
+ int priority;
+ Node tempRule;
+ String ruleName;
+ public RuleIntroduction(String name,int p)
+ {
+ ruleName=name; priority=p;
+ }
+ public String getName()
+ {
+ return ruleName;
+ }
+ public Node createNodes(askFormula ask)
+ {
+ Formula C=ask.Ask();
+ for (Node n:tempRule.Children)
+ {
+ if (n.F.toString().equals(" ")) //undefined formula
+ n.F=C;
+ n.ruleName=ruleName;
+ }
+ tempRule.ruleName=ruleName;
+ return tempRule;
+ }
+ public int getPriority()
+ {
+ return priority;
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+public class RuleNotElimination implements EliminationRule
+{
+ String ruleName;
+ public String getName()
+ {
+ return ruleName;
+ }
+ FormulaNot Fn;
+ RuleNotElimination(FormulaNot F)
+ {
+ Fn=F;
+ ruleName="¬e";
+ }
+ public Node createNodes(Formula F,askFormula ask)
+ {
+ Formula C=ask.Ask();
+ if ((C.toString().equals("⊥"))&&(F==null ||F==Fn.Operand)) //top-down con nodo attuale bottom o bottom-up con nodi attuali Fn e !Fn
+ {
+ Node elNode=new Node(Fn);
+ Node cNode=new Node(Fn.Operand);
+ Node rNode=new Node(C);
+ rNode.addChild(elNode);
+ rNode.addChild(cNode);
+ rNode.ruleName=ruleName;
+ return rNode;
+ }
+ else
+ return null;
+ }
+}
+
--- /dev/null
+package com.example.furt.myapplication;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class RuleOrElimination implements EliminationRule
+{
+ String ruleName;
+ public String getName()
+ {
+ return ruleName;
+ }
+ FormulaOr Fn;
+ RuleOrElimination(FormulaOr F)
+ {
+ Fn=F;
+ ruleName="∨e";
+ }
+ public Node createNodes(Formula F,askFormula ask)
+ {
+ Formula C;
+ if (F==null)
+ C=ask.Ask();
+ else
+ C=F;
+ Node elNode=new Node(Fn);
+ Node c1Node=new Node(C);
+ Node c2Node=new Node(C);
+ List<Formula> HP1=new ArrayList<Formula>();
+ List<Formula> HP2=new ArrayList<Formula>();
+ HP1.add(Fn.leftF);
+ HP2.add(Fn.rightF);
+ c1Node.addHPFormula(HP1,true);
+ c2Node.addHPFormula(HP2,true);
+ Node rNode=new Node(C);
+ rNode.addChild(elNode);
+ rNode.addChild(c1Node);
+ rNode.addChild(c2Node);
+ rNode.ruleName=ruleName;
+ return rNode;
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+// simple class that just has one member property as an example
+public class ServerData implements Parcelable {
+ private static List<String> L;
+
+ ServerData(List<String> List)
+ {
+ L=List;
+ }
+ /* everything below here is for implementing Parcelable */
+
+ // 99.9% of the time you can just ignore this
+ public int describeContents() {
+ return 0;
+ }
+
+ // write your object's data to the passed-in Parcel
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeList(L);
+ }
+
+ // this is used to regenerate your object. All Parcelables must have a CREATOR that implements these two methods
+ public static final Creator<ServerData> CREATOR = new Creator<ServerData>() {
+ public ServerData createFromParcel(Parcel in) {
+ return new ServerData(L);
+ }
+
+ public ServerData[] newArray(int size) {
+ return new ServerData[size];
+ }
+ };
+
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+public interface Tree
+{
+ float getBaseWidth();
+ float getMaxWidth();
+ float getLineWidth();
+ float getUpLine();
+ float getLeftOffset() ;
+ float getRightOffset();
+ void Draw();
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.FocusFinder;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.view.animation.AnimationUtils;
+import android.widget.FrameLayout;
+import android.widget.Scroller;
+
+import java.util.List;
+
+
+/**
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+*
+ * Revised 5/19/2010 by GORGES
+ * Now supports two-dimensional view scrolling
+ * http://GORGES.us
+ */
+
+/**
+ * Layout container for a view hierarchy that can be scrolled by the user,
+ * allowing it to be larger than the physical display. A TwoDScrollView
+ * is a {@link android.widget.FrameLayout}, meaning you should place one child in it
+ * containing the entire contents to scroll; this child may itself be a layout
+ * manager with a complex hierarchy of objects. A child that is often used
+ * is a {@link android.widget.LinearLayout} in a vertical orientation, presenting a vertical
+ * array of top-level items that the user can scroll through.
+ *
+ * <p>The {@link android.widget.TextView} class also
+ * takes care of its own scrolling, so does not require a TwoDScrollView, but
+ * using the two together is possible to achieve the effect of a text view
+ * within a larger container.
+ */
+
+public class TwoDScrollView extends FrameLayout {
+ static final int ANIMATED_SCROLL_GAP = 250;
+ static final float MAX_SCROLL_FACTOR = 0.5f;
+
+ private long mLastScroll;
+
+ private final Rect mTempRect = new Rect();
+ private Scroller mScroller;
+
+ /*
+ * Flag to indicate that we are moving focus ourselves. This is so the
+ * code that watches for focus changes initiated outside this TwoDScrollView
+ * knows that it does not have to do anything.
+ */
+ private boolean mTwoDScrollViewMovedFocus;
+
+ /*
+ * Position of the last motion event.
+ */
+ private float mLastMotionY;
+ private float mLastMotionX;
+
+ /*
+ * True when the layout has changed but the traversal has not come through yet.
+ * Ideally the view hierarchy would keep track of this for us.
+ */
+ private boolean mIsLayoutDirty = true;
+
+ /*
+ * The child to give focus to in the event that a child has requested focus while the
+ * layout is dirty. This prevents the scroll from being wrong if the child has not been
+ * laid out before requesting focus.
+ */
+ private View mChildToScrollTo = null;
+
+ /*
+ * True if the user is currently dragging this TwoDScrollView around. This is
+ * not the same as 'is being flinged', which can be checked by
+ * mScroller.isFinished() (flinging begins when the user lifts his finger).
+ */
+ private boolean mIsBeingDragged = false;
+
+ /*
+ * Determines speed during touch scrolling
+ */
+ private VelocityTracker mVelocityTracker;
+
+ /*
+ * Whether arrow scrolling is animated.
+ */
+ private int mTouchSlop;
+ private int mMinimumVelocity;
+ private int mMaximumVelocity;
+
+ public TwoDScrollView(Context context) {
+ super(context);
+ initTwoDScrollView();
+ }
+
+ public TwoDScrollView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initTwoDScrollView();
+ }
+
+ public TwoDScrollView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ initTwoDScrollView();
+ }
+
+ @Override
+ protected float getTopFadingEdgeStrength() {
+ if (getChildCount() == 0) {
+ return 0.0f;
+ }
+ final int length = getVerticalFadingEdgeLength();
+ if (getScrollY() < length) {
+ return getScrollY() / (float) length;
+ }
+ return 1.0f;
+ }
+
+ @Override
+ protected float getBottomFadingEdgeStrength() {
+ if (getChildCount() == 0) {
+ return 0.0f;
+ }
+ final int length = getVerticalFadingEdgeLength();
+ final int bottomEdge = getHeight() - getPaddingBottom();
+ final int span = getChildAt(0).getBottom() - getScrollY() - bottomEdge;
+ if (span < length) {
+ return span / (float) length;
+ }
+ return 1.0f;
+ }
+
+ @Override
+ protected float getLeftFadingEdgeStrength() {
+ if (getChildCount() == 0) {
+ return 0.0f;
+ }
+ final int length = getHorizontalFadingEdgeLength();
+ if (getScrollX() < length) {
+ return getScrollX() / (float) length;
+ }
+ return 1.0f;
+ }
+
+ @Override
+ protected float getRightFadingEdgeStrength() {
+ if (getChildCount() == 0) {
+ return 0.0f;
+ }
+ final int length = getHorizontalFadingEdgeLength();
+ final int rightEdge = getWidth() - getPaddingRight();
+ final int span = getChildAt(0).getRight() - getScrollX() - rightEdge;
+ if (span < length) {
+ return span / (float) length;
+ }
+ return 1.0f;
+ }
+
+ /**
+ * @return The maximum amount this scroll view will scroll in response to
+ * an arrow event.
+ */
+ public int getMaxScrollAmountVertical() {
+ return (int) (MAX_SCROLL_FACTOR * getHeight());
+ }
+ public int getMaxScrollAmountHorizontal() {
+ return (int) (MAX_SCROLL_FACTOR * getWidth());
+ }
+
+ private void initTwoDScrollView() {
+ mScroller = new Scroller(getContext());
+ setFocusable(true);
+ setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
+ setWillNotDraw(false);
+ final ViewConfiguration configuration = ViewConfiguration.get(getContext());
+ mTouchSlop = configuration.getScaledTouchSlop();
+ mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
+ mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
+ }
+
+ @Override
+ public void addView(View child) {
+ if (getChildCount() > 0) {
+ throw new IllegalStateException("TwoDScrollView can host only one direct child");
+ }
+ super.addView(child);
+ }
+
+ @Override
+ public void addView(View child, int index) {
+ if (getChildCount() > 0) {
+ throw new IllegalStateException("TwoDScrollView can host only one direct child");
+ }
+ super.addView(child, index);
+ }
+
+ @Override
+ public void addView(View child, ViewGroup.LayoutParams params) {
+ if (getChildCount() > 0) {
+ throw new IllegalStateException("TwoDScrollView can host only one direct child");
+ }
+ super.addView(child, params);
+ }
+
+ @Override
+ public void addView(View child, int index, ViewGroup.LayoutParams params) {
+ if (getChildCount() > 0) {
+ throw new IllegalStateException("TwoDScrollView can host only one direct child");
+ }
+ super.addView(child, index, params);
+ }
+
+ /**
+ * @return Returns true this TwoDScrollView can be scrolled
+ */
+ private boolean canScroll() {
+ View child = getChildAt(0);
+ if (child != null) {
+ int childHeight = child.getHeight();
+ int childWidth = child.getWidth();
+ return (getHeight() < childHeight + getPaddingTop() + getPaddingBottom()) ||
+ (getWidth() < childWidth + getPaddingLeft() + getPaddingRight());
+ }
+ return false;
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ // Let the focused view and/or our descendants get the key first
+ boolean handled = super.dispatchKeyEvent(event);
+ if (handled) {
+ return true;
+ }
+ return executeKeyEvent(event);
+ }
+
+ /**
+ * You can call this function yourself to have the scroll view perform
+ * scrolling from a key event, just as if the event had been dispatched to
+ * it by the view hierarchy.
+ *
+ * @param event The key event to execute.
+ * @return Return true if the event was handled, else false.
+ */
+ public boolean executeKeyEvent(KeyEvent event) {
+ mTempRect.setEmpty();
+ if (!canScroll()) {
+ if (isFocused()) {
+ View currentFocused = findFocus();
+ if (currentFocused == this) currentFocused = null;
+ View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, View.FOCUS_DOWN);
+ return nextFocused != null && nextFocused != this && nextFocused.requestFocus(View.FOCUS_DOWN);
+ }
+ return false;
+ }
+ boolean handled = false;
+ if (event.getAction() == KeyEvent.ACTION_DOWN) {
+ switch (event.getKeyCode()) {
+ case KeyEvent.KEYCODE_DPAD_UP:
+ if (!event.isAltPressed()) {
+ handled = arrowScroll(View.FOCUS_UP, false);
+ } else {
+ handled = fullScroll(View.FOCUS_UP, false);
+ }
+ break;
+ case KeyEvent.KEYCODE_DPAD_DOWN:
+ if (!event.isAltPressed()) {
+ handled = arrowScroll(View.FOCUS_DOWN, false);
+ } else {
+ handled = fullScroll(View.FOCUS_DOWN, false);
+ }
+ break;
+ case KeyEvent.KEYCODE_DPAD_LEFT:
+ if (!event.isAltPressed()) {
+ handled = arrowScroll(View.FOCUS_LEFT, true);
+ } else {
+ handled = fullScroll(View.FOCUS_LEFT, true);
+ }
+ break;
+ case KeyEvent.KEYCODE_DPAD_RIGHT:
+ if (!event.isAltPressed()) {
+ handled = arrowScroll(View.FOCUS_RIGHT, true);
+ } else {
+ handled = fullScroll(View.FOCUS_RIGHT, true);
+ }
+ break;
+ }
+ }
+ return handled;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ /*
+ * This method JUST determines whether we want to intercept the motion.
+ * If we return true, onMotionEvent will be called and we do the actual
+ * scrolling there.
+ *
+ * Shortcut the most recurring case: the user is in the dragging
+ * state and he is moving his finger. We want to intercept this
+ * motion.
+ */
+ final int action = ev.getAction();
+ if ((action == MotionEvent.ACTION_MOVE) && (mIsBeingDragged)) {
+ return true;
+ }
+ if (!canScroll()) {
+ mIsBeingDragged = false;
+ return false;
+ }
+ final float y = ev.getY();
+ final float x = ev.getX();
+ switch (action) {
+ case MotionEvent.ACTION_MOVE:
+ /*
+ * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
+ * whether the user has moved far enough from his original down touch.
+ */
+ /*
+ * Locally do absolute value. mLastMotionY is set to the y value
+ * of the down event.
+ */
+ final int yDiff = (int) Math.abs(y - mLastMotionY);
+ final int xDiff = (int) Math.abs(x - mLastMotionX);
+ if (yDiff > mTouchSlop || xDiff > mTouchSlop) {
+ mIsBeingDragged = true;
+ }
+ break;
+
+ case MotionEvent.ACTION_DOWN:
+ /* Remember location of down touch */
+ mLastMotionY = y;
+ mLastMotionX = x;
+
+ /*
+ * If being flinged and user touches the screen, initiate drag;
+ * otherwise don't. mScroller.isFinished should be false when
+ * being flinged.
+ */
+ mIsBeingDragged = !mScroller.isFinished();
+ break;
+
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ /* Release the drag */
+ mIsBeingDragged = false;
+ break;
+ }
+
+ /*
+ * The only time we want to intercept motion events is if we are in the
+ * drag mode.
+ */
+ return mIsBeingDragged;
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+
+ if (ev.getAction() == MotionEvent.ACTION_DOWN && ev.getEdgeFlags() != 0) {
+ // Don't handle edge touches immediately -- they may actually belong to one of our
+ // descendants.
+ return false;
+ }
+
+ if (!canScroll()) {
+ return false;
+ }
+
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ }
+ mVelocityTracker.addMovement(ev);
+
+ final int action = ev.getAction();
+ final float y = ev.getY();
+ final float x = ev.getX();
+
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ /*
+ * If being flinged and user touches, stop the fling. isFinished
+ * will be false if being flinged.
+ */
+ if (!mScroller.isFinished()) {
+ mScroller.abortAnimation();
+ }
+
+ // Remember where the motion event started
+ mLastMotionY = y;
+ mLastMotionX = x;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ // Scroll to follow the motion event
+ int deltaX = (int) (mLastMotionX - x);
+ int deltaY = (int) (mLastMotionY - y);
+ mLastMotionX = x;
+ mLastMotionY = y;
+
+ if (deltaX < 0) {
+ if (getScrollX() < 0) {
+ deltaX = 0;
+ }
+ } else if (deltaX > 0) {
+ final int rightEdge = getWidth() - getPaddingRight();
+ final int availableToScroll = getChildAt(0).getRight() - getScrollX() - rightEdge;
+ if (availableToScroll > 0) {
+ deltaX = Math.min(availableToScroll, deltaX);
+ } else {
+ deltaX = 0;
+ }
+ }
+ if (deltaY < 0) {
+ if (getScrollY() < 0) {
+ deltaY = 0;
+ }
+ } else if (deltaY > 0) {
+ final int bottomEdge = getHeight() - getPaddingBottom();
+ final int availableToScroll = getChildAt(0).getBottom() - getScrollY() - bottomEdge;
+ if (availableToScroll > 0) {
+ deltaY = Math.min(availableToScroll, deltaY);
+ } else {
+ deltaY = 0;
+ }
+ }
+ if (deltaY != 0 || deltaX != 0)
+ scrollBy(deltaX, deltaY);
+ break;
+ case MotionEvent.ACTION_UP:
+ final VelocityTracker velocityTracker = mVelocityTracker;
+ velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+ int initialXVelocity = (int) velocityTracker.getXVelocity();
+ int initialYVelocity = (int) velocityTracker.getYVelocity();
+ if ((Math.abs(initialXVelocity) + Math.abs(initialYVelocity) > mMinimumVelocity) && getChildCount() > 0) {
+ fling(-initialXVelocity, -initialYVelocity);
+ }
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Finds the next focusable component that fits in this View's bounds
+ * (excluding fading edges) pretending that this View's top is located at
+ * the parameter top.
+ *
+ * @param topFocus look for a candidate is the one at the top of the bounds
+ * if topFocus is true, or at the bottom of the bounds if topFocus is
+ * false
+ * @param top the top offset of the bounds in which a focusable must be
+ * found (the fading edge is assumed to start at this position)
+ * @param preferredFocusable the View that has highest priority and will be
+ * returned if it is within my bounds (null is valid)
+ * @return the next focusable component in the bounds or null if none can be
+ * found
+ */
+ private View findFocusableViewInMyBounds(final boolean topFocus, final int top, final boolean leftFocus, final int left, View preferredFocusable) {
+ /*
+ * The fading edge's transparent side should be considered for focus
+ * since it's mostly visible, so we divide the actual fading edge length
+ * by 2.
+ */
+ final int verticalFadingEdgeLength = getVerticalFadingEdgeLength() / 2;
+ final int topWithoutFadingEdge = top + verticalFadingEdgeLength;
+ final int bottomWithoutFadingEdge = top + getHeight() - verticalFadingEdgeLength;
+ final int horizontalFadingEdgeLength = getHorizontalFadingEdgeLength() / 2;
+ final int leftWithoutFadingEdge = left + horizontalFadingEdgeLength;
+ final int rightWithoutFadingEdge = left + getWidth() - horizontalFadingEdgeLength;
+
+ if ((preferredFocusable != null)
+ && (preferredFocusable.getTop() < bottomWithoutFadingEdge)
+ && (preferredFocusable.getBottom() > topWithoutFadingEdge)
+ && (preferredFocusable.getLeft() < rightWithoutFadingEdge)
+ && (preferredFocusable.getRight() > leftWithoutFadingEdge)) {
+ return preferredFocusable;
+ }
+ return findFocusableViewInBounds(topFocus, topWithoutFadingEdge, bottomWithoutFadingEdge, leftFocus, leftWithoutFadingEdge, rightWithoutFadingEdge);
+ }
+
+ /**
+ * Finds the next focusable component that fits in the specified bounds.
+ * </p>
+ *
+ * @param topFocus look for a candidate is the one at the top of the bounds
+ * if topFocus is true, or at the bottom of the bounds if topFocus is
+ * false
+ * @param top the top offset of the bounds in which a focusable must be
+ * found
+ * @param bottom the bottom offset of the bounds in which a focusable must
+ * be found
+ * @return the next focusable component in the bounds or null if none can
+ * be found
+ */
+ private View findFocusableViewInBounds(boolean topFocus, int top, int bottom, boolean leftFocus, int left, int right) {
+ List<View> focusables = getFocusables(View.FOCUS_FORWARD);
+ View focusCandidate = null;
+
+ /*
+ * A fully contained focusable is one where its top is below the bound's
+ * top, and its bottom is above the bound's bottom. A partially
+ * contained focusable is one where some part of it is within the
+ * bounds, but it also has some part that is not within bounds. A fully contained
+ * focusable is preferred to a partially contained focusable.
+ */
+ boolean foundFullyContainedFocusable = false;
+
+ int count = focusables.size();
+ for (int i = 0; i < count; i++) {
+ View view = focusables.get(i);
+ int viewTop = view.getTop();
+ int viewBottom = view.getBottom();
+ int viewLeft = view.getLeft();
+ int viewRight = view.getRight();
+
+ if (top < viewBottom && viewTop < bottom && left < viewRight && viewLeft < right) {
+ /*
+ * the focusable is in the target area, it is a candidate for
+ * focusing
+ */
+ final boolean viewIsFullyContained = (top < viewTop) && (viewBottom < bottom) && (left < viewLeft) && (viewRight < right);
+ if (focusCandidate == null) {
+ /* No candidate, take this one */
+ focusCandidate = view;
+ foundFullyContainedFocusable = viewIsFullyContained;
+ } else {
+ final boolean viewIsCloserToVerticalBoundary =
+ (topFocus && viewTop < focusCandidate.getTop()) ||
+ (!topFocus && viewBottom > focusCandidate.getBottom());
+ final boolean viewIsCloserToHorizontalBoundary =
+ (leftFocus && viewLeft < focusCandidate.getLeft()) ||
+ (!leftFocus && viewRight > focusCandidate.getRight());
+ if (foundFullyContainedFocusable) {
+ if (viewIsFullyContained && viewIsCloserToVerticalBoundary && viewIsCloserToHorizontalBoundary) {
+ /*
+ * We're dealing with only fully contained views, so
+ * it has to be closer to the boundary to beat our
+ * candidate
+ */
+ focusCandidate = view;
+ }
+ } else {
+ if (viewIsFullyContained) {
+ /* Any fully contained view beats a partially contained view */
+ focusCandidate = view;
+ foundFullyContainedFocusable = true;
+ } else if (viewIsCloserToVerticalBoundary && viewIsCloserToHorizontalBoundary) {
+ /*
+ * Partially contained view beats another partially
+ * contained view if it's closer
+ */
+ focusCandidate = view;
+ }
+ }
+ }
+ }
+ }
+ return focusCandidate;
+ }
+
+ /**
+ * <p>Handles scrolling in response to a "home/end" shortcut press. This
+ * method will scroll the view to the top or bottom and give the focus
+ * to the topmost/bottommost component in the new visible area. If no
+ * component is a good candidate for focus, this scrollview reclaims the
+ * focus.</p>
+ *
+ * @param direction the scroll direction: {@link android.view.View#FOCUS_UP}
+ * to go the top of the view or
+ * {@link android.view.View#FOCUS_DOWN} to go the bottom
+ * @return true if the key event is consumed by this method, false otherwise
+ */
+ public boolean fullScroll(int direction, boolean horizontal) {
+ if (!horizontal) {
+ boolean down = direction == View.FOCUS_DOWN;
+ int height = getHeight();
+ mTempRect.top = 0;
+ mTempRect.bottom = height;
+ if (down) {
+ int count = getChildCount();
+ if (count > 0) {
+ View view = getChildAt(count - 1);
+ mTempRect.bottom = view.getBottom();
+ mTempRect.top = mTempRect.bottom - height;
+ }
+ }
+ return scrollAndFocus(direction, mTempRect.top, mTempRect.bottom, 0, 0, 0);
+ } else {
+ boolean right = direction == View.FOCUS_DOWN;
+ int width = getWidth();
+ mTempRect.left = 0;
+ mTempRect.right = width;
+ if (right) {
+ int count = getChildCount();
+ if (count > 0) {
+ View view = getChildAt(count - 1);
+ mTempRect.right = view.getBottom();
+ mTempRect.left = mTempRect.right - width;
+ }
+ }
+ return scrollAndFocus(0, 0, 0, direction, mTempRect.top, mTempRect.bottom);
+ }
+ }
+
+ /**
+ * <p>Scrolls the view to make the area defined by <code>top</code> and
+ * <code>bottom</code> visible. This method attempts to give the focus
+ * to a component visible in this area. If no component can be focused in
+ * the new visible area, the focus is reclaimed by this scrollview.</p>
+ *
+ * @param direction the scroll direction: {@link android.view.View#FOCUS_UP}
+ * to go upward
+ * {@link android.view.View#FOCUS_DOWN} to downward
+ * @param top the top offset of the new area to be made visible
+ * @param bottom the bottom offset of the new area to be made visible
+ * @return true if the key event is consumed by this method, false otherwise
+ */
+ private boolean scrollAndFocus(int directionY, int top, int bottom, int directionX, int left, int right) {
+ boolean handled = true;
+ int height = getHeight();
+ int containerTop = getScrollY();
+ int containerBottom = containerTop + height;
+ boolean up = directionY == View.FOCUS_UP;
+ int width = getWidth();
+ int containerLeft = getScrollX();
+ int containerRight = containerLeft + width;
+ boolean leftwards = directionX == View.FOCUS_UP;
+ View newFocused = findFocusableViewInBounds(up, top, bottom, leftwards, left, right);
+ if (newFocused == null) {
+ newFocused = this;
+ }
+ if ((top >= containerTop && bottom <= containerBottom) || (left >= containerLeft && right <= containerRight)) {
+ handled = false;
+ } else {
+ int deltaY = up ? (top - containerTop) : (bottom - containerBottom);
+ int deltaX = leftwards ? (left - containerLeft) : (right - containerRight);
+ doScroll(deltaX, deltaY);
+ }
+ if (newFocused != findFocus() && newFocused.requestFocus(directionY)) {
+ mTwoDScrollViewMovedFocus = true;
+ mTwoDScrollViewMovedFocus = false;
+ }
+ return handled;
+ }
+
+ /**
+ * Handle scrolling in response to an up or down arrow click.
+ *
+ * @param direction The direction corresponding to the arrow key that was
+ * pressed
+ * @return True if we consumed the event, false otherwise
+ */
+ public boolean arrowScroll(int direction, boolean horizontal) {
+ View currentFocused = findFocus();
+ if (currentFocused == this) currentFocused = null;
+ View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, direction);
+ final int maxJump = horizontal ? getMaxScrollAmountHorizontal() : getMaxScrollAmountVertical();
+
+ if (!horizontal) {
+ if (nextFocused != null) {
+ nextFocused.getDrawingRect(mTempRect);
+ offsetDescendantRectToMyCoords(nextFocused, mTempRect);
+ int scrollDelta = computeScrollDeltaToGetChildRectOnScreen(mTempRect);
+ doScroll(0, scrollDelta);
+ nextFocused.requestFocus(direction);
+ } else {
+ // no new focus
+ int scrollDelta = maxJump;
+ if (direction == View.FOCUS_UP && getScrollY() < scrollDelta) {
+ scrollDelta = getScrollY();
+ } else if (direction == View.FOCUS_DOWN) {
+ if (getChildCount() > 0) {
+ int daBottom = getChildAt(0).getBottom();
+ int screenBottom = getScrollY() + getHeight();
+ if (daBottom - screenBottom < maxJump) {
+ scrollDelta = daBottom - screenBottom;
+ }
+ }
+ }
+ if (scrollDelta == 0) {
+ return false;
+ }
+ doScroll(0, direction == View.FOCUS_DOWN ? scrollDelta : -scrollDelta);
+ }
+ } else {
+ if (nextFocused != null) {
+ nextFocused.getDrawingRect(mTempRect);
+ offsetDescendantRectToMyCoords(nextFocused, mTempRect);
+ int scrollDelta = computeScrollDeltaToGetChildRectOnScreen(mTempRect);
+ doScroll(scrollDelta, 0);
+ nextFocused.requestFocus(direction);
+ } else {
+ // no new focus
+ int scrollDelta = maxJump;
+ if (direction == View.FOCUS_UP && getScrollY() < scrollDelta) {
+ scrollDelta = getScrollY();
+ } else if (direction == View.FOCUS_DOWN) {
+ if (getChildCount() > 0) {
+ int daBottom = getChildAt(0).getBottom();
+ int screenBottom = getScrollY() + getHeight();
+ if (daBottom - screenBottom < maxJump) {
+ scrollDelta = daBottom - screenBottom;
+ }
+ }
+ }
+ if (scrollDelta == 0) {
+ return false;
+ }
+ doScroll(direction == View.FOCUS_DOWN ? scrollDelta : -scrollDelta, 0);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Smooth scroll by a Y delta
+ *
+ * @param delta the number of pixels to scroll by on the Y axis
+ */
+ private void doScroll(int deltaX, int deltaY) {
+ if (deltaX != 0 || deltaY != 0) {
+ smoothScrollBy(deltaX, deltaY);
+ }
+ }
+
+ /**
+ * Like {@link android.view.View#scrollBy}, but scroll smoothly instead of immediately.
+ *
+ * @param dx the number of pixels to scroll by on the X axis
+ * @param dy the number of pixels to scroll by on the Y axis
+ */
+ public final void smoothScrollBy(int dx, int dy) {
+ long duration = AnimationUtils.currentAnimationTimeMillis() - mLastScroll;
+ if (duration > ANIMATED_SCROLL_GAP) {
+ mScroller.startScroll(getScrollX(), getScrollY(), dx, dy);
+ awakenScrollBars(mScroller.getDuration());
+ invalidate();
+ } else {
+ if (!mScroller.isFinished()) {
+ mScroller.abortAnimation();
+ }
+ scrollBy(dx, dy);
+ }
+ mLastScroll = AnimationUtils.currentAnimationTimeMillis();
+ }
+
+ /**
+ * Like {@link #scrollTo}, but scroll smoothly instead of immediately.
+ *
+ * @param x the position where to scroll on the X axis
+ * @param y the position where to scroll on the Y axis
+ */
+ public final void smoothScrollTo(int x, int y) {
+ smoothScrollBy(x - getScrollX(), y - getScrollY());
+ }
+
+ /**
+ * <p>The scroll range of a scroll view is the overall height of all of its
+ * children.</p>
+ */
+ @Override
+ protected int computeVerticalScrollRange() {
+ int count = getChildCount();
+ return count == 0 ? getHeight() : (getChildAt(0)).getBottom();
+ }
+ @Override
+ protected int computeHorizontalScrollRange() {
+ int count = getChildCount();
+ return count == 0 ? getWidth() : (getChildAt(0)).getRight();
+ }
+
+ @Override
+ protected void measureChild(View child, int parentWidthMeasureSpec, int parentHeightMeasureSpec) {
+ ViewGroup.LayoutParams lp = child.getLayoutParams();
+ int childWidthMeasureSpec;
+ int childHeightMeasureSpec;
+
+ childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, getPaddingLeft() + getPaddingRight(), lp.width);
+ childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+
+ child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ }
+
+ @Override
+ protected void measureChildWithMargins(View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) {
+ final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
+ final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
+ getPaddingLeft() + getPaddingRight() + lp.leftMargin + lp.rightMargin + widthUsed, lp.width);
+ final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.topMargin + lp.bottomMargin, MeasureSpec.UNSPECIFIED);
+
+ child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
+ }
+
+ @Override
+ public void computeScroll() {
+ if (mScroller.computeScrollOffset()) {
+ // This is called at drawing time by ViewGroup. We don't want to
+ // re-show the scrollbars at this point, which scrollTo will do,
+ // so we replicate most of scrollTo here.
+ //
+ // It's a little odd to call onScrollChanged from inside the drawing.
+ //
+ // It is, except when you remember that computeScroll() is used to
+ // animate scrolling. So unless we want to defer the onScrollChanged()
+ // until the end of the animated scrolling, we don't really have a
+ // choice here.
+ //
+ // I agree. The alternative, which I think would be worse, is to post
+ // something and tell the subclasses later. This is bad because there
+ // will be a window where mScrollX/Y is different from what the app
+ // thinks it is.
+ //
+ int oldX = getScrollX();
+ int oldY = getScrollY();
+ int x = mScroller.getCurrX();
+ int y = mScroller.getCurrY();
+ if (getChildCount() > 0) {
+ View child = getChildAt(0);
+ scrollTo(clamp(x, getWidth() - getPaddingRight() - getPaddingLeft(), child.getWidth()),
+ clamp(y, getHeight() - getPaddingBottom() - getPaddingTop(), child.getHeight()));
+ } else {
+ scrollTo(x, y);
+ }
+ if (oldX != getScrollX() || oldY != getScrollY()) {
+ onScrollChanged(getScrollX(), getScrollY(), oldX, oldY);
+ }
+
+ // Keep on drawing until the animation has finished.
+ postInvalidate();
+ }
+ }
+
+ /**
+ * Scrolls the view to the given child.
+ *
+ * @param child the View to scroll to
+ */
+ private void scrollToChild(View child) {
+ child.getDrawingRect(mTempRect);
+ /* Offset from child's local coordinates to TwoDScrollView coordinates */
+ offsetDescendantRectToMyCoords(child, mTempRect);
+ int scrollDelta = computeScrollDeltaToGetChildRectOnScreen(mTempRect);
+ if (scrollDelta != 0) {
+ scrollBy(0, scrollDelta);
+ }
+ }
+
+ /**
+ * If rect is off screen, scroll just enough to get it (or at least the
+ * first screen size chunk of it) on screen.
+ *
+ * @param rect The rectangle.
+ * @param immediate True to scroll immediately without animation
+ * @return true if scrolling was performed
+ */
+ private boolean scrollToChildRect(Rect rect, boolean immediate) {
+ final int delta = computeScrollDeltaToGetChildRectOnScreen(rect);
+ final boolean scroll = delta != 0;
+ if (scroll) {
+ if (immediate) {
+ scrollBy(0, delta);
+ } else {
+ smoothScrollBy(0, delta);
+ }
+ }
+ return scroll;
+ }
+
+ /**
+ * Compute the amount to scroll in the Y direction in order to get
+ * a rectangle completely on the screen (or, if taller than the screen,
+ * at least the first screen size chunk of it).
+ *
+ * @param rect The rect.
+ * @return The scroll delta.
+ */
+ protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
+ if (getChildCount() == 0) return 0;
+ int height = getHeight();
+ int screenTop = getScrollY();
+ int screenBottom = screenTop + height;
+ int fadingEdge = getVerticalFadingEdgeLength();
+ // leave room for top fading edge as long as rect isn't at very top
+ if (rect.top > 0) {
+ screenTop += fadingEdge;
+ }
+
+ // leave room for bottom fading edge as long as rect isn't at very bottom
+ if (rect.bottom < getChildAt(0).getHeight()) {
+ screenBottom -= fadingEdge;
+ }
+ int scrollYDelta = 0;
+ if (rect.bottom > screenBottom && rect.top > screenTop) {
+ // need to move down to get it in view: move down just enough so
+ // that the entire rectangle is in view (or at least the first
+ // screen size chunk).
+ if (rect.height() > height) {
+ // just enough to get screen size chunk on
+ scrollYDelta += (rect.top - screenTop);
+ } else {
+ // get entire rect at bottom of screen
+ scrollYDelta += (rect.bottom - screenBottom);
+ }
+
+ // make sure we aren't scrolling beyond the end of our content
+ int bottom = getChildAt(0).getBottom();
+ int distanceToBottom = bottom - screenBottom;
+ scrollYDelta = Math.min(scrollYDelta, distanceToBottom);
+
+ } else if (rect.top < screenTop && rect.bottom < screenBottom) {
+ // need to move up to get it in view: move up just enough so that
+ // entire rectangle is in view (or at least the first screen
+ // size chunk of it).
+
+ if (rect.height() > height) {
+ // screen size chunk
+ scrollYDelta -= (screenBottom - rect.bottom);
+ } else {
+ // entire rect at top
+ scrollYDelta -= (screenTop - rect.top);
+ }
+
+ // make sure we aren't scrolling any further than the top our content
+ scrollYDelta = Math.max(scrollYDelta, -getScrollY());
+ }
+ return scrollYDelta;
+ }
+
+ @Override
+ public void requestChildFocus(View child, View focused) {
+ if (!mTwoDScrollViewMovedFocus) {
+ if (!mIsLayoutDirty) {
+ scrollToChild(focused);
+ } else {
+ // The child may not be laid out yet, we can't compute the scroll yet
+ mChildToScrollTo = focused;
+ }
+ }
+ super.requestChildFocus(child, focused);
+ }
+
+ /**
+ * When looking for focus in children of a scroll view, need to be a little
+ * more careful not to give focus to something that is scrolled off screen.
+ *
+ * This is more expensive than the default {@link android.view.ViewGroup}
+ * implementation, otherwise this behavior might have been made the default.
+ */
+ @Override
+ protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
+ // convert from forward / backward notation to up / down / left / right
+ // (ugh).
+ if (direction == View.FOCUS_FORWARD) {
+ direction = View.FOCUS_DOWN;
+ } else if (direction == View.FOCUS_BACKWARD) {
+ direction = View.FOCUS_UP;
+ }
+
+ final View nextFocus = previouslyFocusedRect == null ?
+ FocusFinder.getInstance().findNextFocus(this, null, direction) :
+ FocusFinder.getInstance().findNextFocusFromRect(this,
+ previouslyFocusedRect, direction);
+
+ if (nextFocus == null) {
+ return false;
+ }
+
+ return nextFocus.requestFocus(direction, previouslyFocusedRect);
+ }
+
+ @Override
+ public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
+ // offset into coordinate space of this scroll view
+ rectangle.offset(child.getLeft() - child.getScrollX(), child.getTop() - child.getScrollY());
+ return scrollToChildRect(rectangle, immediate);
+ }
+
+ @Override
+ public void requestLayout() {
+ mIsLayoutDirty = true;
+ super.requestLayout();
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ super.onLayout(changed, l, t, r, b);
+ mIsLayoutDirty = false;
+ // Give a child focus if it needs it
+ if (mChildToScrollTo != null && isViewDescendantOf(mChildToScrollTo, this)) {
+ scrollToChild(mChildToScrollTo);
+ }
+ mChildToScrollTo = null;
+
+ // Calling this with the present values causes it to re-clam them
+ scrollTo(getScrollX(), getScrollY());
+ }
+
+ @Override
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+ super.onSizeChanged(w, h, oldw, oldh);
+
+ View currentFocused = findFocus();
+ if (null == currentFocused || this == currentFocused)
+ return;
+
+ // If the currently-focused view was visible on the screen when the
+ // screen was at the old height, then scroll the screen to make that
+ // view visible with the new screen height.
+ currentFocused.getDrawingRect(mTempRect);
+ offsetDescendantRectToMyCoords(currentFocused, mTempRect);
+ int scrollDeltaX = computeScrollDeltaToGetChildRectOnScreen(mTempRect);
+ int scrollDeltaY = computeScrollDeltaToGetChildRectOnScreen(mTempRect);
+ doScroll(scrollDeltaX, scrollDeltaY);
+ }
+
+ /**
+ * Return true if child is an descendant of parent, (or equal to the parent).
+ */
+ private boolean isViewDescendantOf(View child, View parent) {
+ if (child == parent) {
+ return true;
+ }
+
+ final ViewParent theParent = child.getParent();
+ return (theParent instanceof ViewGroup) && isViewDescendantOf((View) theParent, parent);
+ }
+
+ /**
+ * Fling the scroll view
+ *
+ * @param velocityY The initial velocity in the Y direction. Positive
+ * numbers mean that the finger/curor is moving down the screen,
+ * which means we want to scroll towards the top.
+ */
+ public void fling(int velocityX, int velocityY) {
+ if (getChildCount() > 0) {
+ int height = getHeight() - getPaddingBottom() - getPaddingTop();
+ int bottom = getChildAt(0).getHeight();
+ int width = getWidth() - getPaddingRight() - getPaddingLeft();
+ int right = getChildAt(0).getWidth();
+
+ mScroller.fling(getScrollX(), getScrollY(), velocityX, velocityY, 0, right - width, 0, bottom - height);
+
+ final boolean movingDown = velocityY > 0;
+ final boolean movingRight = velocityX > 0;
+
+ View newFocused = findFocusableViewInMyBounds(movingRight, mScroller.getFinalX(), movingDown, mScroller.getFinalY(), findFocus());
+ if (newFocused == null) {
+ newFocused = this;
+ }
+
+ if (newFocused != findFocus() && newFocused.requestFocus(movingDown ? View.FOCUS_DOWN : View.FOCUS_UP)) {
+ mTwoDScrollViewMovedFocus = true;
+ mTwoDScrollViewMovedFocus = false;
+ }
+
+ awakenScrollBars(mScroller.getDuration());
+ invalidate();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>This version also clamps the scrolling to the bounds of our child.
+ */
+ public void scrollTo(int x, int y) {
+ // we rely on the fact the View.scrollBy calls scrollTo.
+ if (getChildCount() > 0) {
+ View child = getChildAt(0);
+ x = clamp(x, getWidth() - getPaddingRight() - getPaddingLeft(), child.getWidth());
+ y = clamp(y, getHeight() - getPaddingBottom() - getPaddingTop(), child.getHeight());
+ if (x != getScrollX() || y != getScrollY()) {
+ super.scrollTo(x, y);
+ }
+ }
+ }
+
+ private int clamp(int n, int my, int child) {
+ if (my >= child || n < 0) {
+ /* my >= child is this case:
+ * |--------------- me ---------------|
+ * |------ child ------|
+ * or
+ * |--------------- me ---------------|
+ * |------ child ------|
+ * or
+ * |--------------- me ---------------|
+ * |------ child ------|
+ *
+ * n < 0 is this case:
+ * |------ me ------|
+ * |-------- child --------|
+ * |-- mScrollX --|
+ */
+ return 0;
+ }
+ if ((my+n) > child) {
+ /* this case:
+ * |------ me ------|
+ * |------ child ------|
+ * |-- mScrollX --|
+ */
+ return child-my;
+ }
+ return n;
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.graphics.Paint;
+
+import java.util.List;
+
+public class UndefinedFormula implements Formula{
+
+ Paint p=new Paint();
+ int priority;
+ boolean currentF;
+ UndefinedFormula()
+ {
+ priority=100;
+ currentF=false;
+ }
+ public String Draw(int x)
+ {
+ if(currentF)
+ return "_";
+ else
+ return " ";
+ }
+ public String toString(){return Draw(0);}
+ public String toStringDeleted(){return null;} //UndefinedFormula should never be deleted
+ public float size(){
+ p.setTextSize(DrawActivity.textSize);
+ return p.measureText(toString());
+ }
+ public float height()
+ {
+ return 0;
+ }
+ public float sizeDeleted(){return(0);}
+ public List<IntroductionRule> introductionRules(){
+ return null;
+ } //UndefinedFormula accepts no rules
+ public List<EliminationRule> EliminationRules(){
+ return null;
+ }
+
+ @Override
+ public boolean Fill(Formula F) {
+ return false;
+ }
+
+ @Override
+ public boolean setCursor() {
+ currentF=true;
+ return true;
+ }
+
+ @Override
+ public Formula duplicate() {
+ UndefinedFormula tmp=new UndefinedFormula();
+ tmp.currentF=this.currentF;
+ return tmp;
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+
+import android.content.Context;
+import android.os.AsyncTask;
+import android.os.Environment;
+import android.util.Log;
+import android.widget.Toast;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+public class aggiorna {
+
+ aggiorna(){}
+
+ public String sincronizza(String sessionKey,String user,String pass) {
+ String ritorno = null;
+ String login = "1/" + user + "/" + pass;
+ while (ritorno == null || ritorno.contains("request-login"))
+ {
+ ritorno = serverSync(sessionKey, user);
+ if(ritorno == null || ritorno.contains("request-login"))
+ {
+ sessionKey= serverComunication.connessione(login);
+ }
+ else if(ritorno.contains("error"))
+ Toast.makeText(aggiornamento.t.getContext().getApplicationContext(), "errore di connessione", Toast.LENGTH_SHORT).show();
+ }
+ ritorno=null;
+ while (ritorno == null || ritorno.contains("request-login"))
+ {
+ ritorno = syncLocaldb(sessionKey, user);
+ if(ritorno == null || ritorno.contains("request-login"))
+ {
+ sessionKey= serverComunication.connessione(login);
+ }
+ else if(ritorno.contains("error"))
+ Toast.makeText(aggiornamento.t.getContext().getApplicationContext(), "errore di connessione", Toast.LENGTH_SHORT).show();
+ }
+ ritorno=null;
+ while (ritorno == null || ritorno.contains("request-login"))
+ {
+ ritorno=downloadEX(sessionKey);
+ if(ritorno == null || ritorno.contains("request-login"))
+ {
+ sessionKey= serverComunication.connessione(login);
+ }
+ else if(ritorno.contains("error"))
+ Toast.makeText(aggiornamento.t.getContext().getApplicationContext(), "errore di connessione", Toast.LENGTH_SHORT).show();
+ }
+ return sessionKey;
+ }
+
+ public String serverSync(String sessionKey, String user)
+ {
+ personalDBHelper connessione = new personalDBHelper(aggiornamento.t.getContext());
+ List<listElem> esercizi=connessione.getElem(user);
+ if(esercizi!=null && !esercizi.isEmpty()) {
+ for (listElem esercizio : esercizi) {
+ Log.e("",esercizio.getEsercizio());}
+ for (listElem esercizio : esercizi) {
+ String richiesta = "8/" + sessionKey + "/" + esercizio.getEsercizio() + "/" + esercizio.getMd5() + "/" + esercizio.getTime() + "/" + esercizio.getClick();
+ String ritorno = serverComunication.connessione(richiesta);
+ if (ritorno.contains("es-ok"))
+ connessione.updateElem(esercizio.getMd5(), user, esercizio.getTime());
+ else if (ritorno.contains("request-login") || ritorno.contains("es-err")){
+ if(ritorno.contains("es-err"))
+ connessione.remove(esercizio.getUtente(),esercizio.getTime());
+ return ritorno;
+ }
+ }
+ }
+ return "sync-ok";
+ }
+
+ public String syncLocaldb(String sessionKey, String utente)
+ {
+ String richiesta = "9/" + sessionKey;
+ String ritorno = serverComunication.connessione(richiesta);
+ if(ritorno.contains("request-login"))
+ return ritorno;
+ else
+ {
+ personalDBHelper connessione=new personalDBHelper(aggiornamento.t.getContext().getApplicationContext());
+ ArrayList<String> allExercise=suString.stringToMultiArray(ritorno);
+ List<listElem> localExercise=connessione.getAllElem(utente);
+ if(localExercise!=null && !localExercise.isEmpty()) {
+ for (String ex : allExercise) {
+ ArrayList<String> tmp = suString.stringToArrayList(ex);
+ boolean add = true;
+ for (listElem elem : localExercise) {
+ if (tmp.get(0).equals(elem.getEsercizio()) && Double.valueOf(tmp.get(2)) == elem.getTime()) {
+ if (elem.getCheck() == 0)
+ connessione.updateElem(tmp.get(1), utente, Double.valueOf(tmp.get(2)));
+ add = false;
+ }
+ }
+ if (add)
+ if(tmp.size()>3)
+ connessione.add(utente, tmp.get(0), tmp.get(1), Double.valueOf(tmp.get(2)), Integer.valueOf(tmp.get(3)), 1);
+ }
+ }
+ else{
+ for (String ex : allExercise) {
+ ArrayList<String> tmp = suString.stringToArrayList(ex);
+ if(tmp.size()>3)
+ connessione.add(utente, tmp.get(0), tmp.get(1), Double.valueOf(tmp.get(2)), Integer.valueOf(tmp.get(3)), 1);
+ }
+ }
+ }
+ return "local-sync-ok";
+ }
+
+ public String downloadEX(String sessionKey)
+ {
+ Context context = aggiornamento.t.getContext();
+ File SDCardRoot = Environment.getExternalStorageDirectory();
+ String[] names = SDCardRoot.list();
+ String ritorno=null;
+ boolean go = true;
+ for (String name : names) {
+ if (name.compareTo("tesiEs") == 0) {
+ go = false;
+ break;
+ }
+ }
+ if (go) {
+ File dir = new File(global.esDir);
+ dir.mkdir();
+ }
+ try {
+ ritorno = serverComunication.connessione("7/" + sessionKey);
+ if (!ritorno.contains("error") && !ritorno.contains("request-login"))
+ {
+ ArrayList<String> esercizi= suString.stringToMultiArray(ritorno);
+ File dir = new File(global.esDir);
+ String[] presenti = dir.list();
+ boolean tmp = true;
+ for(String esercizio : esercizi)
+ {
+ ArrayList<String> es=suString.stringToArrayList(esercizio);
+ tmp = true;
+ for (String nome : presenti) {
+ if (nome.contentEquals(es.get(0))) {
+ if ((MD5.digest(nome)).contentEquals(es.get(1))) {
+ tmp = false;
+ }
+ else {
+ File file = new File(global.esDir + nome);
+ file.delete();
+ }
+ }
+ }
+ if (tmp) {
+ String request = new download().execute(es.get(0)).get();
+ }
+ }
+ }
+ }catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return ritorno;
+ }
+}
+class download extends AsyncTask<String,String,String>
+{
+ @Override
+ protected String doInBackground(String... params)
+ {
+ try {
+ //set the download URL, a url that points to a file on the internet
+ //this is the file to be downloaded
+ URL url = new URL(global.httpHost+params[0]);
+
+ //create the new connection
+ HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
+
+ //set up some things on the connection
+ urlConnection.setRequestMethod("GET");
+ urlConnection.setDoOutput(true);
+
+ //and connect!
+ urlConnection.connect();
+
+ //set the path where we want to save the file
+ //in this case, going to save it on the root directory of the
+ //sd card.
+ File SDCardRoot = Environment.getExternalStorageDirectory();
+ File esDir = new File(global.esDir);
+ //create a new file, specifying the path, and the filename
+ //which we want to save the file as.
+
+
+ File file = new File(esDir,params[0]);
+ //this will be used to write the downloaded data into the file we created
+ FileOutputStream fileOutput = new FileOutputStream(file);
+
+ //this will be used in reading the data from the internet
+ InputStream inputStream = urlConnection.getInputStream();
+
+ //this is the total size of the file
+ int totalSize = urlConnection.getContentLength();
+ //variable to store total downloaded bytes
+ int downloadedSize = 0;
+
+ //create a buffer...
+ byte[] buffer = new byte[1024];
+ int bufferLength = 0; //used to store a temporary size of the buffer
+
+ //now, read through the input buffer and write the contents to the file
+ while ( (bufferLength = inputStream.read(buffer)) > 0 ) {
+ //add the data in the buffer to the file in the file output stream (the file on the sd card
+ fileOutput.write(buffer, 0, bufferLength);
+ //add up the size so we know how much is downloaded
+ downloadedSize += bufferLength;
+ //this is where you would do something to report the prgress, like this maybe
+ //updateProgress(downloadedSize, totalSize);
+
+ }
+ //close the output stream when done
+ fileOutput.close();
+
+//catch some possible errors...
+ } catch (MalformedURLException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+}
+
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.widget.RelativeLayout;
+
+
+public class aggiornamento extends Activity
+{
+ static RelativeLayout t; //for context
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.aggiornamento);
+ t=(RelativeLayout)findViewById(R.id.glob_agg);
+ Bundle dati=getIntent().getExtras();
+ String user=dati.getString("user");
+ String pass=dati.getString("pass");
+ String sessionKey=dati.getString("sessionKey");
+ if(sessionKey.contentEquals("000000000"))//controllo se le credenziali memorizzate sono corrette
+ {
+ sessionKey = serverComunication.connessione("1/" + user + "/" + pass);
+ if(sessionKey.contentEquals("request-login") || sessionKey.contains("err"))
+ {
+ Log.e("", "ciao");
+ Intent i = new Intent(getApplicationContext(), mainActivity.class);
+ i.putExtra("logout", "si");
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getApplicationContext().startActivity(i);
+ return;
+ }
+ }
+ aggiorna agg=new aggiorna();
+ sessionKey=agg.sincronizza(sessionKey,user,pass);
+ if(sessionKey.contains("err") || sessionKey.contentEquals("000000000"))
+ {
+ Intent i = new Intent(getApplicationContext(), mainActivity.class);
+ i.putExtra("logout", "si");
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getApplicationContext().startActivity(i);
+ }
+ else {
+ Intent i = new Intent(getApplicationContext(), download_page.class);
+ i.putExtra("user", user);
+ i.putExtra("pass", pass);
+ i.putExtra("sessionKey", sessionKey);
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getApplicationContext().startActivity(i);
+ }
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+public class askFormula{
+ public Formula Ask(){return DrawActivity.selectedNode.F;};
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import java.io.File;
+import java.util.List;
+
+public class download_page extends Activity
+{
+ static String user=null;
+ static String pass=null;
+ static String sessionKey=null;
+ static RelativeLayout globalDownload;
+ static TextView rootDownload;
+ static TextView dw;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ dw=(TextView)findViewById(R.id.startEs);
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.download);
+ final Context context=getApplicationContext();
+ Bundle dati=getIntent().getExtras();
+ globalDownload=(RelativeLayout)findViewById(R.id.dlglobal);
+ rootDownload=(TextView)findViewById(R.id.startEs);
+ user=dati.getString("user");
+ pass=dati.getString("pass");
+ sessionKey=dati.getString("sessionKey");
+ File dir = new File(global.esDir);
+ String[] presenti = dir.list();
+ ArrayAdapter<String> vievList=new ArrayAdapter<String>(this,R.layout.textviewgeneral);
+ ListView lista= (ListView) findViewById(R.id.listView);
+ for (String nome : presenti) {
+ String aggiungi="non risolto";
+ boolean min=false;
+ boolean check=false;
+ personalDBHelper db=new personalDBHelper(context);
+ List<listElem> risolti=db.getElemForName(user, nome);
+ if(risolti!=null && !risolti.isEmpty()) {
+
+ for (listElem elem : risolti) {
+ if (!min && elem.getCheck() == 0) {
+ min = true;
+ aggiungi = "da confermare: " + elem.getClick() + "/30";
+ } else if (!check && elem.getCheck() == 1) {
+ min = true;
+ check = true;
+ aggiungi = elem.getClick() + "/30";
+ }
+
+ }
+ }
+ vievList.add(nome+"\n"+aggiungi);
+ }
+ lista.setAdapter(vievList);
+ lista.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ TextView t=(TextView)view;
+ String valore=t.getText().toString();
+ String nomeEs = null;
+ for(int i=0;i<valore.length();i++)
+ {
+ if(valore.charAt(i)=='.')
+ {
+ nomeEs=valore.substring(0,i)+".xml";
+ i=valore.length();
+ }
+ }
+ Intent i = new Intent(getApplicationContext(), DrawActivity.class);
+ i.putExtra("nomeEs", nomeEs);
+ i.putExtra("user",user);
+ i.putExtra("pass",pass);
+ i.putExtra("sessionKey",sessionKey);
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getApplicationContext().startActivity(i);
+ }
+ });
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.menu_dow, menu);
+ return true;
+ }
+
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+ if(id==R.id.aggiorna)
+ {
+ Intent i = new Intent(getApplicationContext(), aggiornamento.class);
+ i.putExtra("user", user);
+ i.putExtra("pass", pass);
+ i.putExtra("sessionKey", sessionKey);
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getApplicationContext().startActivity(i);
+ }
+ else if (id==R.id.esci)
+ {
+ Intent i = new Intent(getApplicationContext(), mainActivity.class);
+ i.putExtra("logout","si");
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getApplicationContext().startActivity(i);
+ }
+ return super.onOptionsItemSelected(item);
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+
+import android.os.Environment;
+
+public class global {
+ public static String hostName = "130.136.129.1";
+ public static String esDir= Environment.getExternalStorageDirectory()+"/tesiEs/";
+ public static String httpHost="http://logicplayer.helm.cs.unibo.it/esercizi/";
+ public static int port=25000;
+
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+
+public class listElem {
+ private String esercizio;
+ private double time;
+ private int check;
+ private String md5;
+ private String utente;
+ private int click;
+
+ listElem()
+ {}
+
+ public void setEsercizio(String esercizio)
+ {
+ this.esercizio=esercizio;
+ }
+ public void setTime(double time)
+ {
+ this.time=time;
+ }
+ public void setCheck(int check)
+ {
+ this.check=check;
+ }
+ public void setMd5(String md5){this.md5=md5;}
+ public void setUtente(String utente){this.utente=utente;}
+ public void setClick(int click){this.click=click;}
+
+ public String getUtente(){return this.utente;}
+ public String getEsercizio()
+ {
+ return this.esercizio;
+ }
+ public String getMd5()
+ {
+ return this.md5;
+ }
+ public double getTime()
+ {
+ return this.time;
+ }
+ public int getCheck()
+ {
+ return this.check;
+ }
+ public int getClick(){return this.click;}
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+
+/*possiamo chiavare la mainActiviti in due casi, il primo è aprendo l'applicazione, il secondo è effettuando il
+* logout. nel primo caso viene controllato se sono state memorizzate delle credenziali e nel caso, il login viene
+* efetttuato direttamente. nel caso in cui si effettua il logout o non sono state memorizzate le credenziali,
+* viene data la possibilità di registrarsi o loggarsi, è possibile tramite il menù recuperare la password o aggiornarla
+* una volta effettuato il login viene passato il controllo ad "aggiorna.java"*/
+
+public class mainActivity extends Activity {
+
+ static TextView t;
+ public static final String PREFS_NAME = "MyPrefsFile";
+ private static final String PREF_USERNAME = "username";
+ private static final String PREF_PASSWORD = "password";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_login);
+ t = (TextView) findViewById(R.id.login);
+ SharedPreferences pref = getSharedPreferences(PREFS_NAME, MODE_PRIVATE);//recupero le ultime credenziali valide inserite
+ String username = pref.getString(PREF_USERNAME, null);
+ String password = pref.getString(PREF_PASSWORD, null);
+ String logout=null;
+ Bundle dati=getIntent().getExtras();
+ if(dati!=null)//controllo se la mainActivity è stata chiamata dopo un logout
+ logout=dati.getString("logout");
+ if(logout!=null)
+ {
+ username=null;
+ password=null;
+ }
+
+ if (username == null && password == null) {//viene effettuato solo se ci sono delle credenziali memorizzate e se mainActivity non è stata chiamata da un logout
+ Button b = (Button) findViewById(R.id.logout);
+ b.setOnClickListener(new View.OnClickListener() {//routin di gestione del login
+ @Override
+ public void onClick(View v) {
+ try {
+ EditText txt = (EditText) findViewById(R.id.userId);//recupero username inserito
+ EditText txt2 = (EditText) findViewById(R.id.oldPass);//recupero la password inserita
+ String testo = txt.getText().toString();
+ String testo2 = txt2.getText().toString();
+ if(testo.contains("/") || testo2.contains("/"))//controllo che non siano inseriti valori vietati
+ Toast.makeText(getApplicationContext(),"il carattere '/' non è consentito", Toast.LENGTH_SHORT).show();
+ else if(testo.isEmpty() || testo2.isEmpty())//controllo che tutti i campi siano completati
+ Toast.makeText(getApplicationContext(),"riempi i campi", Toast.LENGTH_SHORT).show();
+ else {//login effettuato con successo
+ String request = serverComunication.connessioneMain("1/" + testo + "/" + testo2);//richiedo il login al server
+ if (!request.contains("error")) {
+ getSharedPreferences(PREFS_NAME, MODE_PRIVATE)//salvo username e password per i prossimi accessi
+ .edit()
+ .putString(PREF_USERNAME, testo)
+ .putString(PREF_PASSWORD, testo2)
+ .commit();
+ Intent i = new Intent(getApplicationContext(), aggiornamento.class);
+ i.putExtra("user", testo);
+ i.putExtra("pass", testo2);
+ i.putExtra("sessionKey", request);
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getApplicationContext().startActivity(i);//avvio la "aggiornamento.class"
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ Button b2 = (Button) findViewById(R.id.button2);
+ b2.setOnClickListener(new View.OnClickListener() {//routine di gestione della registrazione
+ @Override
+ public void onClick(View v) {
+
+ EditText txt = (EditText) findViewById(R.id.userId);
+ EditText txt2 = (EditText) findViewById(R.id.oldPass);
+ String testo = txt.getText().toString();
+ String testo2 = txt2.getText().toString();
+ if(testo.isEmpty() || testo2.isEmpty())
+ Toast.makeText(getApplicationContext(),"riempi i campi", Toast.LENGTH_SHORT).show();
+ else {
+ try {
+ serverComunication connect = new serverComunication();
+ String request = connect.connessioneMain("0/" + testo + "/" + testo2);
+ Toast.makeText(getApplicationContext(), request, Toast.LENGTH_SHORT).show();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ });
+ } else {
+ Intent i = new Intent(getApplicationContext(), aggiornamento.class);
+ i.putExtra("user", username);
+ i.putExtra("pass", password);
+ i.putExtra("sessionKey", "000000000");
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getApplicationContext().startActivity(i);
+ }
+ }
+
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.login_set, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will
+ // automatically handle clicks on the Home/Up button, so long
+ // as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+ if(id==R.id.recupera)//routine di gestione di recupero password
+ {
+ EditText txt = (EditText) findViewById(R.id.userId);
+ String testo = txt.getText().toString();
+ if(testo.isEmpty())
+ Toast.makeText(getApplicationContext(),"inserisci l'indirizzo email", Toast.LENGTH_SHORT).show();
+ else {
+ try {
+ serverComunication connect = new serverComunication();
+ String request = connect.connessioneMain("2/" + testo);
+ Toast.makeText(getApplicationContext(), request, Toast.LENGTH_SHORT).show();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ if(id==R.id.reimposta)
+ {
+ Intent i = new Intent(getApplicationContext(), recuperaPass.class);
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getApplicationContext().startActivity(i);
+ }
+ return super.onOptionsItemSelected(item);
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.view.View;
+
+public class operandClick implements View.OnClickListener
+{
+ Node L;
+ operandClick(Node n)
+ {
+ L=n;
+ }
+ public void onClick(View view)
+ {
+ if (DrawActivity.selectedNode.Children.size()!=0) //not a leaf: can't add children
+ return;
+ if (L==null) //incompatible elimination
+ return;
+ for (Node n:L.Children) {
+ for (Hypothesis hp:n.NodeHP)
+ hp.fromNode= DrawActivity.selectedNode; //le ipotesi dei nuovi figli provengono dal nodo in cui stanno per essere inserite
+ n.addHPList(DrawActivity.selectedNode.NodeHP);
+ DrawActivity.selectedNode.addChild(n);
+ }
+ DrawActivity.selectedNode.hasFocus=false;
+ DrawActivity.selectedNode.Children.get(0).hasFocus=true;
+ DrawActivity.selectedNode.hasFocus=false;
+ DrawActivity.selectedNode.ruleName=L.ruleName;
+ DrawActivity.nmoves++;
+ DrawActivity.rootNode.Clean();
+ DrawActivity.startDraw();
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import org.w3c.dom.Document;
+import org.xml.sax.SAXException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathFactory;
+
+public class parser {
+ parser(){}
+
+ protected static Node root(String esercizio)
+ {
+ Node returnNode=null;
+ try {
+ String cartellaEs=global.esDir;
+ FileInputStream file = new FileInputStream(new File(cartellaEs+esercizio));
+ DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = builderFactory.newDocumentBuilder();
+ Document xmlDocument = builder.parse(file);
+ returnNode=new Node(createFormula(xmlDocument,"/esercizio/tesi/formula[1]"));
+ returnNode.addHPList(ipotesi(xmlDocument));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return returnNode;
+ }
+
+ static public ArrayList<String> getLiteral(String esercizio)
+ {
+ String cartellaEs=global.esDir;
+ ArrayList<String> listValue=new ArrayList<String>();
+ ArrayList<String> returnValue=new ArrayList<String>();
+ try {
+ FileInputStream file = new FileInputStream(new File(cartellaEs + esercizio));
+ DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = builderFactory.newDocumentBuilder();
+ Document xmlDocument = builder.parse(file);
+ listValue.add("Ț");
+ listValue.add("⊥");
+ listValue.addAll(getLiteralAtFormula(xmlDocument, "/esercizio/tesi/formula[1]"));
+ listValue.addAll(getLiteralAtHypotesis(xmlDocument));
+ for(String elem : listValue)
+ {
+ if(!returnValue.isEmpty())
+ {
+ if(!returnValue.contains(elem))
+ returnValue.add(elem);
+ }
+ else
+ returnValue.add(elem);
+ }
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (ParserConfigurationException e) {
+ e.printStackTrace();
+ } catch (SAXException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return returnValue;
+ }
+
+ static public ArrayList<String> getLiteralAtFormula(Document xmlDocument, String position)
+ {
+ ArrayList<String> returnList=new ArrayList<String>();
+ try {
+ XPath xPath = XPathFactory.newInstance().newXPath();
+ if(Integer.parseInt(xPath.compile("count(" + position + ")").evaluate(xmlDocument))==1) {
+ String type = xPath.compile(position + "/@type").evaluate(xmlDocument);
+ int numbOfElements = 5;
+ if (type.contentEquals("and") || type.contentEquals("or") || type.contentEquals("impl"))
+ numbOfElements = 2;
+ else if (type.contentEquals("not"))
+ numbOfElements = 1;
+ else if (type.contentEquals("literal") || type.contentEquals("atomic"))
+ numbOfElements = 0;
+ int count = Integer.parseInt(xPath.compile("count(" + position + "/formula)").evaluate(xmlDocument));
+ if (count == numbOfElements) {
+ if (numbOfElements == 2) {
+ returnList.addAll(getLiteralAtFormula(xmlDocument, position + "/formula[1]"));
+ returnList.addAll(getLiteralAtFormula(xmlDocument, position + "/formula[2]"));
+
+ return returnList;
+ } else if (numbOfElements == 1) {
+ return getLiteralAtFormula(xmlDocument, position + "/formula[1]");
+ } else if (numbOfElements == 0) {
+ String child = xPath.compile(position).evaluate(xmlDocument);
+ if (child == null || child.isEmpty())
+ return null;
+ else if (child.contentEquals("top")) {
+ returnList.add("Ț");
+ return returnList;
+ }
+ else if (child.contentEquals("bot")){
+ returnList.add("⊥");
+ return returnList;
+ }
+ else{
+ returnList.add(String.valueOf(child.charAt(0)));
+ return returnList;
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ static public Formula createFormula(Document xmlDocument, String position) {
+ try {
+ XPath xPath = XPathFactory.newInstance().newXPath();
+ if(Integer.parseInt(xPath.compile("count(" + position + ")").evaluate(xmlDocument))==1) {
+ String type = xPath.compile(position + "/@type").evaluate(xmlDocument);
+ int numbOfElements = 5;
+ if (type.contentEquals("and") || type.contentEquals("or") || type.contentEquals("impl"))
+ numbOfElements = 2;
+ else if (type.contentEquals("not"))
+ numbOfElements = 1;
+ else if (type.contentEquals("literal") || type.contentEquals("atomic"))
+ numbOfElements = 0;
+ int count = Integer.parseInt(xPath.compile("count(" + position + "/formula)").evaluate(xmlDocument));
+ if (count == numbOfElements) {
+ if (numbOfElements == 2) {
+ Formula firstChild = createFormula(xmlDocument, position + "/formula[1]");
+ Formula secondChild = createFormula(xmlDocument, position + "/formula[2]");
+ if (firstChild == null || secondChild == null)
+ return null;
+ else if (type.contentEquals("and"))
+ return new FormulaAnd(createFormula(xmlDocument, position + "/formula[1]"), createFormula(xmlDocument, position + "/formula[2]"));
+ else if (type.contentEquals("or"))
+ return new FormulaOr(createFormula(xmlDocument, position + "/formula[1]"), createFormula(xmlDocument, position + "/formula[2]"));
+ else if (type.contentEquals("impl"))
+ return new FormulaImpl(createFormula(xmlDocument, position + "/formula[1]"), createFormula(xmlDocument, position + "/formula[2]"));
+ } else if (numbOfElements == 1) {
+ Formula child = createFormula(xmlDocument, position + "/formula[1]");
+ if (child == null)
+ return null;
+ return new FormulaNot(createFormula(xmlDocument, position + "/formula[1]"));
+ } else if (numbOfElements == 0) {
+ String child = xPath.compile(position).evaluate(xmlDocument);
+ if (child == null || child.isEmpty())
+ return null;
+ else if (child.length()>=3 && child.substring(0,3).equals("top"))
+ return new FormulaTOP();
+ else if (child.length()>=3 && child.substring(0,3).equals("bot"))
+ return new FormulaBOT();
+ else
+ return new Literal(child.charAt(0));
+ }
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ static public List<Hypothesis> ipotesi(Document xmlDocument)
+ {
+ List<Hypothesis> returnValue=new ArrayList<Hypothesis>();
+ XPath xPath = XPathFactory.newInstance().newXPath();
+ try
+ {
+ int count = Integer.parseInt(xPath.compile("count(/esercizio/ipotesi/formula)").evaluate(xmlDocument));
+ for(int i=1;i<=count;i++)
+ {
+ Formula F=createFormula(xmlDocument,"/esercizio/ipotesi/formula["+i+"]");
+ Hypothesis valore;
+ if(F==null)
+ valore=null;
+ else
+ valore=new Hypothesis(F,false);
+ if(valore!=null)
+ returnValue.add(valore);
+ }
+ }catch (Exception e) {
+ e.printStackTrace();
+ }
+ return returnValue;
+ }
+
+ static public ArrayList<String> getLiteralAtHypotesis(Document xmlDocument)
+ {
+ ArrayList<String> returnValue=new ArrayList<String>();
+ XPath xPath = XPathFactory.newInstance().newXPath();
+ try
+ {
+ int count = Integer.parseInt(xPath.compile("count(/esercizio/ipotesi/formula)").evaluate(xmlDocument));
+ for(int i=1;i<=count;i++)
+ returnValue.addAll(getLiteralAtFormula(xmlDocument, "/esercizio/ipotesi/formula[" + i + "]"));
+ }catch (Exception e) {
+ e.printStackTrace();
+ }
+ return returnValue;
+ }
+
+ static public ArrayList<String> getParameters(String esercizio)
+ {
+ ArrayList<String> value=new ArrayList<String>();
+ try {
+ String cartellaEs=global.esDir;
+ FileInputStream file = new FileInputStream(new File(cartellaEs+esercizio));
+ DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = builderFactory.newDocumentBuilder();
+ Document xmlDocument = builder.parse(file);
+ return parameters(xmlDocument);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return value;
+ }
+
+ static private ArrayList<String> parameters(Document xmlDocument)
+ {
+ ArrayList<String> returnValue= new ArrayList<String>();
+ XPath xPath = XPathFactory.newInstance().newXPath();
+ try
+ {
+ if( Integer.parseInt(xPath.compile("count(/esercizio/valutazione/click)").evaluate(xmlDocument))==1 &&
+ Integer.parseInt(xPath.compile("count(/esercizio/valutazione/tempo)").evaluate(xmlDocument))==1 &&
+ Integer.parseInt(xPath.compile("count(/esercizio/valutazione/altezza)").evaluate(xmlDocument))==1)
+ {
+ returnValue.add(xPath.compile("/esercizio/valutazione/click").evaluate(xmlDocument));
+ returnValue.add(xPath.compile("/esercizio/valutazione/tempo").evaluate(xmlDocument));
+ returnValue.add(xPath.compile("/esercizio/valutazione/altezza").evaluate(xmlDocument));
+ }
+ }catch (Exception e) {
+ e.printStackTrace();
+ }
+ return returnValue;
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class parserDialog extends DialogFragment {
+ static Formula F=null; //formula che sto costruendo
+ static RelativeLayout formulaLayout;
+ static TextView FView; //View contenente la formula che sto visualizzando
+ static Button dismissButton;
+ static boolean reload=false;
+ static ArrayList<String> esliter=new ArrayList<String>();
+ static ArrayList<Formula> undo=new ArrayList<Formula>();
+ public parserDialog()
+ {
+ esliter.removeAll(esliter);
+ if(!reload)
+ undo.removeAll(undo);
+ reload=false;
+ if(F==null) {
+ F = new UndefinedFormula();
+ F.setCursor();
+ }
+ esliter.addAll(parser.getLiteral(DrawActivity.nomeEs));
+ Log.e("","⊤");
+ }
+ @Override
+ public Dialog onCreateDialog(final Bundle savedInstanceState) {
+ // Use the Builder class for convenient dialog construction
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ LayoutInflater inflater=getActivity().getLayoutInflater();
+ View view=inflater.inflate(R.layout.string_layout, null);
+ RelativeLayout litersLayout=(RelativeLayout)((ViewGroup)((ViewGroup)view).getChildAt(0)).getChildAt(0);
+ RelativeLayout operatorsLayout=(RelativeLayout)(((ViewGroup)view).getChildAt(1));
+ formulaLayout=(RelativeLayout)((ViewGroup)((ViewGroup)view).getChildAt(2)).getChildAt(0);
+ FView=new TextView(formulaLayout.getContext());
+ FView.setText(F.toString());
+ FView.setTextSize(DrawActivity.textSize);
+ formulaLayout.addView(FView);
+ int leftId=0;
+ if(!esliter.isEmpty()) {
+ for (String liter : esliter) {
+ Button lit = new Button(litersLayout.getContext());
+ RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ lit.setText(liter);
+ if (leftId != 0) {
+ lp.addRule(RelativeLayout.RIGHT_OF, leftId);
+ }
+ lit.setLayoutParams(lp);
+ lit.setId(DrawActivity.globalId++);
+ leftId = lit.getId();
+ litersLayout.addView(lit);
+ lit.setOnClickListener(new touchParserHandler(4, liter.charAt(0)));
+ }
+ }
+ Button bImpl=new Button(operatorsLayout.getContext());
+ Button bAnd=new Button(operatorsLayout.getContext());
+ Button bOr=new Button(operatorsLayout.getContext());
+ Button bNot=new Button(operatorsLayout.getContext());
+ RelativeLayout.LayoutParams lpImpl=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ RelativeLayout.LayoutParams lpAnd=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ RelativeLayout.LayoutParams lpNot=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ RelativeLayout.LayoutParams lpOr=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+
+ bImpl.setText("⇒");
+ bImpl.setLayoutParams(lpImpl);
+ bImpl.setId(DrawActivity.globalId++);
+ leftId=bImpl.getId();
+
+ bOr.setText("∨");
+ lpOr.addRule(RelativeLayout.RIGHT_OF, leftId);
+ bOr.setLayoutParams(lpOr);
+ bOr.setId(DrawActivity.globalId++);
+ leftId=bOr.getId();
+
+ bAnd.setText("∧");
+ lpAnd.addRule(RelativeLayout.RIGHT_OF, leftId);
+ bAnd.setLayoutParams(lpAnd);
+ bAnd.setId(DrawActivity.globalId++);
+ leftId=bAnd.getId();
+
+ bNot.setText("¬");
+ lpNot.addRule(RelativeLayout.RIGHT_OF, leftId);
+ bNot.setLayoutParams(lpNot);
+ bNot.setId(DrawActivity.globalId++);
+
+ operatorsLayout.addView(bImpl);
+ operatorsLayout.addView(bAnd);
+ operatorsLayout.addView(bNot);
+ operatorsLayout.addView(bOr);
+ bImpl.setOnClickListener(new touchParserHandler(2,' '));
+ bAnd.setOnClickListener(new touchParserHandler(0,' '));
+ bNot.setOnClickListener(new touchParserHandler(3, ' '));
+ bOr.setOnClickListener(new touchParserHandler(1, ' '));
+ builder.setView(view);
+ builder.setTitle("Inserisci una formula").setPositiveButton("Ok", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ if(!F.toString().contains("_")) {
+ List<EliminationRule> L = F.EliminationRules();
+ if (L.size()==0)
+ return;
+ touchHPHandler t = new touchHPHandler(L.get(0).createNodes(null, new askFormula()),new Hypothesis(F,true));
+ F = null;
+ t.discard=false;
+ t.onClick(null);
+ }
+ else
+ reboot();
+ }
+ });
+ builder.setNeutralButton("Undo", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ if(undo.size()>1) {
+ F = undo.remove(undo.size() - 1);
+ /*for(int i=0;i<undo.size();i++) {
+ Log.e(String.valueOf(i), undo.get(i).toString());
+ }*/
+ }
+ else
+ F=null;
+ reboot();
+ }
+ });
+ builder.setNegativeButton("Annulla", new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ F=null;
+ }
+ });
+ // Create the AlertDialog object and return it
+ return builder.create();
+ }
+ static void reboot()
+ {
+ reload=true;
+ parserDialog p=new parserDialog();
+ p.F=F;
+ p.show(DrawActivity.fragmentManager, "CIAO");
+ }
+
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.util.Log;
+
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.example.furt.myapplication.personalTrackerContract.DATABASE_NAME;
+import static com.example.furt.myapplication.personalTrackerContract.DATABASE_VERSION;
+import static com.example.furt.myapplication.personalTrackerContract.esercizi;
+import static com.example.furt.myapplication.personalTrackerContract.esercizi.COLUMN_CHECK;
+import static com.example.furt.myapplication.personalTrackerContract.esercizi.COLUMN_CLICK;
+import static com.example.furt.myapplication.personalTrackerContract.esercizi.COLUMN_ESERCIZIO;
+import static com.example.furt.myapplication.personalTrackerContract.esercizi.COLUMN_MD5;
+import static com.example.furt.myapplication.personalTrackerContract.esercizi.COLUMN_TIME;
+import static com.example.furt.myapplication.personalTrackerContract.esercizi.COLUMN_UTENTE;
+import static com.example.furt.myapplication.personalTrackerContract.esercizi.SQL_CREATE_ENTRIES;
+import static com.example.furt.myapplication.personalTrackerContract.esercizi.TABLE_NAME;
+
+
+
+public class personalDBHelper extends SQLiteOpenHelper{
+ public personalDBHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ public void onCreate(SQLiteDatabase db) {
+
+ db.execSQL(SQL_CREATE_ENTRIES);
+ Log.e("dphelper", SQL_CREATE_ENTRIES);
+ }
+
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ // This database is only a cache for online data, so its upgrade policy is
+ // to simply to discard the data and start over
+ db.execSQL(SQL_CREATE_ENTRIES);
+ onCreate(db);
+ }
+
+ public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ onUpgrade(db, oldVersion, newVersion);
+ }
+
+ public void add(String utente, String esercizio, String md5, Double time, int ckick, int check)
+ {
+ SQLiteDatabase db=this.getWritableDatabase();
+ ContentValues values=new ContentValues();
+ values.put(COLUMN_MD5,md5);
+ if(time==0)
+ values.put(COLUMN_TIME,(double)time());
+ else
+ values.put(COLUMN_TIME,(time));
+ values.put(COLUMN_CHECK,check);
+ values.put(COLUMN_UTENTE,utente);
+ values.put(COLUMN_ESERCIZIO,esercizio);
+ values.put(COLUMN_CLICK, ckick);
+ db.insert(TABLE_NAME, null, values);
+ db.close();
+ }
+
+ public void remove(String user, double time)
+ {
+ SQLiteDatabase db = this.getWritableDatabase();
+ String request=COLUMN_MD5 + "=? AND " + COLUMN_TIME + "=? AND " + COLUMN_UTENTE + "=?";
+ String[] condition=new String[]{
+ String.valueOf(time),
+ String.valueOf(user)
+ };
+ db.delete(TABLE_NAME,request,condition);
+ db.close();
+ }
+
+ public static Long time()
+ {
+ java.util.Date date= new java.util.Date();
+ Timestamp now=new Timestamp(date.getTime());
+ return now.getTime();
+ }
+
+ public void removeAll(){
+ SQLiteDatabase db=this.getWritableDatabase();
+ String request="TRUNCATE "+TABLE_NAME;
+ }
+
+ public List<listElem> getElem(String user)
+ {
+ List<listElem> elem=null;
+ SQLiteDatabase db=this.getReadableDatabase();
+ String[] tableColums={
+ esercizi.COLUMN_MD5,
+ esercizi.COLUMN_TIME,
+ esercizi.COLUMN_CLICK,
+ esercizi.COLUMN_ESERCIZIO
+ };
+ String whereClause= COLUMN_UTENTE +"=? AND " + COLUMN_CHECK +"=?";
+ String[] whereArgs=new String[]{
+ String.valueOf(user),
+ String.valueOf("0")
+ };
+ Cursor cursor=db.query(TABLE_NAME,tableColums,whereClause,whereArgs,null,null,null);
+ if(cursor.moveToFirst()) {
+ elem = new ArrayList<listElem>();
+ listElem el=new listElem();
+ do {
+ el.setMd5 (cursor.getString(0));
+ el.setTime(cursor.getDouble(1));
+ el.setClick(cursor.getInt(2));
+ el.setEsercizio(cursor.getString(3));
+ elem.add(el);
+ }while(cursor.moveToNext());
+ }
+ return elem;
+ }
+
+ public List<listElem> getElemForName(String user, String esName)
+ {
+ List<listElem> elem=null;
+ SQLiteDatabase db=this.getReadableDatabase();
+ String[] tableColums={
+ esercizi.COLUMN_MD5,
+ esercizi.COLUMN_TIME,
+ esercizi.COLUMN_CLICK,
+ esercizi.COLUMN_CHECK
+ };
+ String whereClause= COLUMN_UTENTE +"=? AND " + COLUMN_ESERCIZIO +"=? ORDER BY "+COLUMN_CLICK;
+ String[] whereArgs=new String[]{
+ String.valueOf(user),
+ String.valueOf(esName)
+ };
+ Cursor cursor=db.query(TABLE_NAME,tableColums,whereClause,whereArgs,null,null,null);
+ if(cursor.moveToFirst()) {
+ elem = new ArrayList<listElem>();
+ listElem el=new listElem();
+ do {
+ el.setMd5 (cursor.getString(0));
+ el.setTime(cursor.getDouble(1));
+ el.setClick(cursor.getInt(2));
+ el.setCheck(cursor.getInt(3));
+ elem.add(el);
+ }while(cursor.moveToNext());
+ }
+ return elem;
+ }
+
+ public List<listElem> getAllElem(String user)
+ {
+ List<listElem> elem=null;
+ SQLiteDatabase db=this.getReadableDatabase();
+ String[] tableColums={
+ esercizi.COLUMN_MD5,
+ esercizi.COLUMN_TIME,
+ esercizi.COLUMN_CLICK,
+ esercizi.COLUMN_ESERCIZIO,
+ esercizi.COLUMN_CHECK
+ };
+ String whereClause= COLUMN_UTENTE +"=?";
+ String[] whereArgs=new String[]{
+ String.valueOf(user)
+ };
+ Cursor cursor=db.query(TABLE_NAME,tableColums,whereClause,whereArgs,null,null,null);
+ if(cursor.moveToFirst()) {
+ elem = new ArrayList<listElem>();
+ listElem el=new listElem();
+ do {
+ el.setMd5 (cursor.getString(0));
+ el.setTime(cursor.getDouble(1));
+ el.setClick(cursor.getInt(2));
+ el.setEsercizio(cursor.getString(3));
+ el.setCheck(cursor.getInt(4));
+ elem.add(el);
+ }while(cursor.moveToNext());
+ }
+ return elem;
+ }
+
+ public void updateElem(String md5, String user, double time)
+ {
+ SQLiteDatabase db=this.getWritableDatabase();
+ String request="UPDATE "+TABLE_NAME+" set "+COLUMN_CHECK+"=1 WHERE "+COLUMN_UTENTE+"='"+user+"' AND "+COLUMN_MD5+"='"+md5+"' AND "+COLUMN_TIME+"="+time;
+ db.execSQL(request);
+ }
+
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.provider.BaseColumns;
+
+
+public final class personalTrackerContract {
+ // To prevent someone from accidentally instantiating the contract class,
+ // give it an empty constructor.
+ public personalTrackerContract() {
+ }
+
+ public static final int DATABASE_VERSION = 1;
+ public static final String DATABASE_NAME = "exercise.db";
+
+ private static final String TEXT_TYPE = " TEXT";
+ private static final String VALUE_TYPE=" DECIMAL";
+ private static final String COMMA_SEP = ",";
+ private static final String INT_TYPE = " INTEGER";
+ private static final String DOUBLE_TYPE=" DOUBLE";
+
+ /* Inner class that defines the table contents */
+ public static abstract class esercizi implements BaseColumns {
+
+ public static final String TABLE_NAME = " esercizi ";
+ public static final String COLUMN_ESERCIZIO = " esercizio ";
+ public static final String COLUMN_MD5 = " md5 ";
+ public static final String COLUMN_UTENTE = " utente ";
+ public static final String COLUMN_TIME = " time ";
+ public static final String COLUMN_CHECK = " checks ";
+ public static final String COLUMN_CLICK = " click ";
+
+ public static final String SQL_CREATE_ENTRIES =
+ "CREATE TABLE " + TABLE_NAME + " (" +
+ COLUMN_UTENTE + TEXT_TYPE + COMMA_SEP +
+ COLUMN_MD5 + TEXT_TYPE + COMMA_SEP +
+ COLUMN_TIME + DOUBLE_TYPE + COMMA_SEP +
+ COLUMN_CLICK + INT_TYPE + COMMA_SEP +
+ COLUMN_ESERCIZIO + TEXT_TYPE + COMMA_SEP +
+ COLUMN_CHECK + INT_TYPE +
+ " )";
+
+ public static final String SQL_DELETE_ENTRIES =
+ "DROP TABLE IF EXISTS " + TABLE_NAME;
+
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.example.furt.myapplication;
+
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.Toast;
+
+public class recuperaPass extends Activity{
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.reimpostapass);
+ Button invia=(Button) findViewById(R.id.invia);
+ invia.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ EditText ut=(EditText) findViewById(R.id.userId);
+ EditText oP=(EditText) findViewById(R.id.oldPass);
+ EditText nP=(EditText) findViewById(R.id.newPass);
+ String utente=ut.getText().toString();
+ String oldPass=oP.getText().toString();
+ String newPass=nP.getText().toString();
+ if(utente==null || oldPass==null || newPass==null)
+ Toast.makeText(getApplicationContext(), "devi riempire tutti i campi", Toast.LENGTH_SHORT).show();
+ else if(!utente.contains("@studio.unibo.it"))
+ Toast.makeText(getApplicationContext(), "email non valida", Toast.LENGTH_SHORT).show();
+ else if(newPass.contains("/"))
+ Toast.makeText(getApplicationContext(), "la password non deve contenere /", Toast.LENGTH_SHORT).show();
+ else
+ {
+ String request = serverComunication.connessioneMain("a0/" + utente + "/" + oldPass + "/" + newPass );
+ if(!request.contains("error"))
+ {
+ Intent i = new Intent(getApplicationContext(), mainActivity.class);
+ i.putExtra("logout", "si");
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getApplicationContext().startActivity(i);
+ }
+ else
+ Toast.makeText(getApplicationContext(), "errore", Toast.LENGTH_SHORT).show();
+ }
+ }
+ });
+ Button annulla=(Button) findViewById(R.id.annulla);
+ annulla.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent i = new Intent(getApplicationContext(), mainActivity.class);
+ i.putExtra("logout", "si");
+ i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ getApplicationContext().startActivity(i);
+ }
+ });
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+
+import android.content.res.Resources;
+import android.os.AsyncTask;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.Socket;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.concurrent.ExecutionException;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManagerFactory;
+
+public class serverComunication
+{
+
+ serverComunication(){}
+
+ public static String connessione(String parametri)
+ {
+ try {
+ return new richiestaServer().execute(parametri).get();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (ExecutionException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+
+
+ static class richiestaServer extends AsyncTask<String, String, String> {
+ @Override
+ protected String doInBackground(String... params)
+ {
+ Resources risorse= aggiornamento.t.getResources();
+ try {
+// (could be from a resource or ByteArrayInputStream or ...)
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+// From https://www.washington.edu/itconnect/security/ca/load-der.crt
+ InputStream caInput = risorse.openRawResource(R.raw.halloween);
+ Certificate ca;
+ try {
+ ca = cf.generateCertificate(caInput);
+ System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
+ } finally {
+ caInput.close();
+ }
+
+// Create a KeyStore containing our trusted CAs
+ String keyStoreType = KeyStore.getDefaultType();
+ KeyStore keyStore = KeyStore.getInstance(keyStoreType);
+ keyStore.load(null, null);
+ keyStore.setCertificateEntry("ca", ca);
+
+// Create a TrustManager that trusts the CAs in our KeyStore
+ String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
+ tmf.init(keyStore);
+
+// Create an SSLContext that uses our TrustManager
+ SSLContext context = SSLContext.getInstance("TLS");
+ context.init(null, tmf.getTrustManagers(), null);
+
+ Socket socket;
+ SSLSocketFactory sf=context.getSocketFactory();
+ socket=sf.createSocket(global.hostName,global.port);
+ OutputStream os = socket.getOutputStream();
+ OutputStreamWriter osw = new OutputStreamWriter(os);
+ BufferedWriter bw = new BufferedWriter(osw);
+ bw.write(params[0]+"\n");
+ bw.flush();
+ BufferedReader r = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+ String returnValue=r.readLine();
+ socket.close();
+ return returnValue;
+ } catch (KeyStoreException g) {
+ g.printStackTrace();
+ } catch (CertificateException a) {
+ a.printStackTrace();
+ } catch (NoSuchAlgorithmException b) {
+ b.printStackTrace();
+ } catch (IOException c) {
+ c.printStackTrace();
+ } catch (KeyManagementException f) {
+ f.printStackTrace();
+ }
+ return "error";
+ }
+ }
+
+ public static String connessioneMain(String parametri)
+ {
+ try {
+ return new richiestaServerMain().execute(parametri).get();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ } catch (ExecutionException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+
+
+ static class richiestaServerMain extends AsyncTask<String, String, String> {
+ @Override
+ protected String doInBackground(String... params)
+ {
+ Resources risorse= mainActivity.t.getResources();
+ try {
+// (could be from a resource or ByteArrayInputStream or ...)
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+// From https://www.washington.edu/itconnect/security/ca/load-der.crt
+ InputStream caInput = risorse.openRawResource(R.raw.halloween);
+ Certificate ca;
+ try {
+ ca = cf.generateCertificate(caInput);
+ System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
+ } finally {
+ caInput.close();
+ }
+
+// Create a KeyStore containing our trusted CAs
+ String keyStoreType = KeyStore.getDefaultType();
+ KeyStore keyStore = KeyStore.getInstance(keyStoreType);
+ keyStore.load(null, null);
+ keyStore.setCertificateEntry("ca", ca);
+
+// Create a TrustManager that trusts the CAs in our KeyStore
+ String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
+ tmf.init(keyStore);
+
+// Create an SSLContext that uses our TrustManager
+ SSLContext context = SSLContext.getInstance("TLS");
+ context.init(null, tmf.getTrustManagers(), null);
+
+ Socket socket;
+ SSLSocketFactory sf=context.getSocketFactory();
+ socket=sf.createSocket(global.hostName,global.port);
+ OutputStream os = socket.getOutputStream();
+ OutputStreamWriter osw = new OutputStreamWriter(os);
+ BufferedWriter bw = new BufferedWriter(osw);
+ bw.write(params[0]+"\n");
+ bw.flush();
+ BufferedReader r = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+ String returnValue=r.readLine();
+ socket.close();
+ return returnValue;
+ } catch (KeyStoreException g) {
+ g.printStackTrace();
+ } catch (CertificateException a) {
+ a.printStackTrace();
+ } catch (NoSuchAlgorithmException b) {
+ b.printStackTrace();
+ } catch (IOException c) {
+ c.printStackTrace();
+ } catch (KeyManagementException f) {
+ f.printStackTrace();
+ }
+ return "error";
+ }
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import java.util.ArrayList;
+
+class suString
+{
+ suString()
+ {};
+
+ public static ArrayList<String> stringToArrayList(String string)
+ {
+ ArrayList<String> returnValue=new ArrayList<String>();
+ int j=0;
+ for(int i=0;i<string.length();i++)
+ {
+ if(string.charAt(i)=='/')
+ {
+ returnValue.add(string.substring(j,i));
+ j=i+1;
+ }
+ else if(i==string.length()-1)
+ returnValue.add(string.substring(j));
+ }
+ return returnValue;
+ }
+
+ public static ArrayList<String> vectorStringToArrayList(String[] vectorString)
+ {
+ ArrayList<String> returnValue=new ArrayList<String>();
+ for(String name : vectorString)
+ returnValue.add(name);
+ return returnValue;
+ }
+
+ public static String arrayListToString (ArrayList<String> arraylist)
+ {
+ String returnValue=new String();
+ for(int i=0;i<arraylist.size();i++)
+ {
+ if(i<arraylist.size()-1)
+ returnValue=returnValue+arraylist.get(i)+"/";
+ else
+ returnValue=returnValue+arraylist.get(i);
+ }
+ return returnValue;
+ }
+
+ public static String vectorStringToString(String[] vectorString)
+ {
+ return arrayListToString(vectorStringToArrayList(vectorString));
+ }
+
+ public static String[] arrayListToVectorString (ArrayList<String> arraylist)
+ {
+ String[] returnValue=new String[arraylist.size()];
+ for(int i=0;i<arraylist.size();i++)
+ returnValue[i]=arraylist.get(i);
+ return returnValue;
+ }
+
+ public static String[] stringToVectorString(String string)
+ {
+ return arrayListToVectorString(stringToArrayList(string));
+ }
+
+ public static String multiToString(ArrayList<String> input)
+ {
+ String returnValue=null;
+ for(int i=0;i<input.size();i++)
+ {
+ if(i==0)
+ returnValue=input.get(i)+"//";
+ else if(i==input.size()-1)
+ returnValue=returnValue+input.get(i);
+ else
+ returnValue=returnValue+input.get(i)+"//";
+ }
+ return returnValue;
+ }
+
+ public static ArrayList<String> stringToMultiArray(String input)
+ {
+ ArrayList<String> result=new ArrayList<String>();
+ int j=0;
+ if(input==null)
+ return result;
+ for(int i=0;i<input.length();i++)
+ {
+ if(input.charAt(i)=='/') {
+ if (input.charAt(i + 1) == '/') {
+ result.add(input.substring(j, i));
+ j=i+2;
+ }
+ }
+ }
+ if(j<input.length())
+ result.add(input.substring(j,input.length()-1));
+ return result;
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.view.View;
+
+public class touchHPHandler implements View.OnClickListener
+{
+ Node L;
+ boolean discard;
+ Hypothesis thisHP; //ipotesi che sto eliminando
+ touchHPHandler(Node n,Hypothesis hp)
+ {
+ L=n;
+ thisHP=hp;
+ discard=true;//di default il ramo della formula scartata viene chiuso
+ }
+ public void onClick(View view)
+ {
+ if (DrawActivity.selectedNode==null) //non-existent selectedNode (should never happen)
+ return;
+ if (DrawActivity.selectedNode.Children.size()!=0) //not a leaf: can't add children
+ {
+ return;
+ }
+ if (thisHP.HP.toString().equals(DrawActivity.selectedNode.F.toString())) //close current Node
+ {
+ if (thisHP.isDeleted) {
+ if (DrawActivity.selectedNode.status == Node.OPEN)
+ DrawActivity.selectedNode.status = Node.CANCELED;
+ else if (DrawActivity.selectedNode.status == Node.FAKE)
+ DrawActivity.selectedNode.status = Node.FAKE_CANCELED;
+ } else {
+ if (DrawActivity.selectedNode.status == Node.OPEN)
+ DrawActivity.selectedNode.status = Node.CLOSED;
+ else if (DrawActivity.selectedNode.status == Node.FAKE)
+ DrawActivity.selectedNode.status = Node.FAKE_CLOSED;
+ }
+ DrawActivity.nmoves++;
+ DrawActivity.rootNode.Clean();
+ DrawActivity.startDraw();
+ return;
+ }
+ if (L==null) //incompatible elimination
+ return;
+ for (Node n:L.Children) {
+ for (Hypothesis hp:n.NodeHP)
+ hp.fromNode= DrawActivity.selectedNode; //le ipotesi dei nuovi figli provengono dal nodo in cui stanno per essere inserite
+ n.addHPList(DrawActivity.selectedNode.NodeHP);
+ DrawActivity.selectedNode.addChild(n);
+ }
+ DrawActivity.selectedNode.hasFocus=false;
+ DrawActivity.selectedNode.Children.get(0).hasFocus=true;
+ if(discard) {
+ if (thisHP.isDeleted)
+ DrawActivity.selectedNode.Children.get(0).status = Node.CANCELED;
+ else
+ DrawActivity.selectedNode.Children.get(0).status = Node.CLOSED;
+ }
+ else
+ DrawActivity.selectedNode.Children.get(0).status= Node.OPEN;
+ DrawActivity.selectedNode.hasFocus = false;
+ DrawActivity.selectedNode.ruleName = L.ruleName;
+ DrawActivity.nmoves++;
+ DrawActivity.rootNode.Clean();
+ DrawActivity.startDraw();
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.view.View;
+import android.widget.TextView;
+
+public class touchParserHandler implements View.OnClickListener
+{
+ int type; //0=and 1=or 2=impl 3=not 4=literal
+ char l; //for literals
+ touchParserHandler(int t,char l)
+ {
+ type=t;
+ this.l=l;
+ }
+ public void onClick(View view)
+ {
+ parserDialog.undo.add(parserDialog.F.duplicate());
+ parserDialog.formulaLayout.removeAllViews();
+ if(type==0)
+ {
+ UndefinedFormula newCursor=new UndefinedFormula();
+ newCursor.currentF=true;
+ Formula newF=new FormulaAnd(newCursor,new UndefinedFormula());
+ if ((parserDialog.F).toString().equals("_"))
+ {
+ parserDialog.F=newF;
+ }
+ else {
+ parserDialog.F.Fill(newF);
+ parserDialog.F.setCursor();
+ }
+ }
+ else if(type==1)
+ {
+ UndefinedFormula newCursor=new UndefinedFormula();
+ newCursor.currentF=true;
+ Formula newF=new FormulaOr(newCursor,new UndefinedFormula());
+ if ((parserDialog.F).toString().equals("_"))
+ {
+ parserDialog.F=newF;
+ }
+ else
+ parserDialog.F.Fill(newF);
+ }
+ else if(type==2)
+ {
+ UndefinedFormula newCursor=new UndefinedFormula();
+ newCursor.currentF=true;
+ Formula newF=new FormulaImpl(newCursor,new UndefinedFormula());
+ if ((parserDialog.F).toString().equals("_"))
+ {
+ parserDialog.F=newF;
+ }
+ else {
+ parserDialog.F.Fill(newF);
+ parserDialog.F.setCursor();
+ }
+ }
+ else if(type==3)
+ {
+ UndefinedFormula newCursor=new UndefinedFormula();
+ newCursor.currentF=true;
+ Formula newF=new FormulaNot(newCursor);
+ if ((parserDialog.F).toString().equals("_"))
+ {
+ parserDialog.F=newF;
+ }
+ else {
+ parserDialog.F.Fill(newF);
+ parserDialog.F.setCursor();
+ }
+ }
+ else if(type==4)
+ {
+ Formula newF;
+ if(l=='⊥')
+ newF=new FormulaBOT();
+ else if(l=='T')
+ newF=new FormulaTOP();
+ else
+ newF=new Literal(l);
+ if ((parserDialog.F).toString().equals("_"))
+ {
+ parserDialog.F=newF;
+ }
+ else {
+ parserDialog.F.Fill(newF);
+ parserDialog.F.setCursor();
+ }
+ }
+ TextView FView=new TextView(parserDialog.formulaLayout.getContext());
+ FView.setText(parserDialog.F.toString());
+ FView.setTextSize(DrawActivity.textSize);
+ parserDialog.formulaLayout.addView(FView);
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+import android.view.View;
+
+import java.util.List;
+
+public class touchRuleHandler implements View.OnClickListener
+{
+ List<Node> L;
+ touchRuleHandler(List<Node> list)
+ {
+ L=list;
+ }
+ public void onClick(View view)
+ {
+ if (DrawActivity.selectedNode.Children.size()!=0) //not a leaf: can't add children
+ return;
+ for (Node n:L) {
+ for (Hypothesis hp:n.NodeHP)
+ hp.fromNode= DrawActivity.selectedNode; //le ipotesi dei nuovi figli provengono dal nodo in cui stanno per essere inserite
+ n.addHPList(DrawActivity.selectedNode.NodeHP);
+ DrawActivity.selectedNode.addChild(n);
+ }
+ DrawActivity.selectedNode.hasFocus=false;
+ DrawActivity.selectedNode.ruleName=L.get(0).ruleName;
+ DrawActivity.selectedNode.Children.get(0).hasFocus=true;
+ DrawActivity.nmoves++;
+ DrawActivity.rootNode.Clean();
+ DrawActivity.startDraw();
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+import android.graphics.Color;
+import android.util.TypedValue;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.util.Log;
+import android.graphics.Paint;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class touchnodeHandler implements View.OnClickListener {
+
+ Node n;
+ touchnodeHandler(Node node) {
+ n=node;
+ }
+ @Override
+ public void onClick(View view) {
+ TextView v=(TextView)view;
+ v.setTextColor(Color.RED);
+ if (DrawActivity.selectedNode!=null)
+ if (DrawActivity.selectedNode.view==view) {
+ if (DrawActivity.selectedNode.Children.size()==0){
+ List<IntroductionRule> L=new ArrayList<IntroductionRule>();
+
+ for (IntroductionRule r: DrawActivity.selectedNode.F.introductionRules())
+ {
+ if (r.getPriority()!=0)
+ L.add(r);
+ }
+ if (L.size()==1)
+ {
+ Node selectedRule=L.get(0).createNodes(new askFormula());
+ for (Node n : selectedRule.Children) {
+ for (Hypothesis hp : n.NodeHP)
+ hp.fromNode = DrawActivity.selectedNode; //le ipotesi dei nuovi figli provengono dal nodo in cui stanno per essere inserite
+ n.addHPList(DrawActivity.selectedNode.NodeHP);
+ n.handler = null;
+ DrawActivity.selectedNode.addChild(n);
+ }
+ DrawActivity.selectedNode.hasFocus = false;
+ DrawActivity.selectedNode.ruleName = selectedRule.Children.get(0).ruleName;
+ DrawActivity.selectedNode.Children.get(0).hasFocus = true;
+ DrawActivity.nmoves++;
+ DrawActivity.rootNode.Clean();
+ DrawActivity.startDraw();
+ }
+ else {
+ RuleDialog ruleDialog = new RuleDialog(DrawActivity.selectedNode.F.introductionRules());
+ ruleDialog.show(DrawActivity.fragmentManager, "CIAO");
+ }
+ }
+ else
+ {
+ CopyPasteDialog copyPasteDialog=new CopyPasteDialog(DrawActivity.selectedNode);
+ copyPasteDialog.show(DrawActivity.fragmentManager,"");
+ }
+ return;
+ }
+ int i,size;
+ if (DrawActivity.selectedNode!=null) {
+ if(DrawActivity.selectedNode.status==Node.OPEN || DrawActivity.selectedNode.status==Node.FAKE)
+ DrawActivity.selectedNode.view.setTextColor(Color.BLACK);
+ else
+ DrawActivity.selectedNode.view.setTextColor(Color.GRAY);
+ }
+ DrawActivity.selectedNode = n;
+ DrawActivity.globalHP.removeAllViews();
+ size = n.NodeHP.size();
+ int leftID=0;
+ int headID=0;
+ float sum=0;
+ final Button elim=new Button(view.getContext());
+ String newText = "Nuova";
+ elim.setText(newText);
+ elim.setTextSize(TypedValue.COMPLEX_UNIT_SP,16);
+ elim.setId(DrawActivity.globalId++);
+ RelativeLayout.LayoutParams myP2=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ elim.setLayoutParams(myP2);
+ elim.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ parserDialog p=new parserDialog();
+ p.show(DrawActivity.fragmentManager, ""); //parte l'editor per inserire nuove formule
+ }
+ });
+ DrawActivity.globalHP.addView(elim);
+ Paint p = new Paint();
+ p.setTextSize(DrawActivity.textSize);
+ float newSize=p.measureText(newText)+(float)(p.measureText(newText)*0.20) + 200;
+ sum+=newSize;
+ leftID=elim.getId();
+ for (i = 0; i<size; i++) //fa apparire le ipotesi cancellate
+ {
+ final TextView newT=new TextView(view.getContext());
+ RelativeLayout.LayoutParams myP=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ newT.setText(n.NodeHP.get(i).HP.toString());
+ newT.setTextSize(TypedValue.COMPLEX_UNIT_SP,30);
+ newT.setId(DrawActivity.globalId++);
+ myP.setMargins(50,0,0,0);
+ sum+=n.NodeHP.get(i).HP.size();
+ if (sum>(DrawActivity.v.widthPixels/1.5)) //ho superato la larghezza dello schermo: devo andare a capo
+ {
+ sum=n.NodeHP.get(i).HP.size();
+ headID=leftID;
+ }
+ else
+ myP.addRule(RelativeLayout.RIGHT_OF,leftID);
+ if (headID!=0)
+ myP.addRule(RelativeLayout.BELOW,headID);
+ newT.setLayoutParams(myP);
+ List<EliminationRule> R=n.NodeHP.get(i).HP.EliminationRules();
+ if (R.size()!=0) {
+ Node L= R.get(0).createNodes(null,new askFormula());
+ newT.setOnClickListener(new touchHPHandler(L,n.NodeHP.get(i)));
+ }
+ else
+ newT.setOnClickListener(new touchHPHandler(null,n.NodeHP.get(i)));
+ newT.setOnLongClickListener(new LongHPClick(n.NodeHP.get(i).fromNode));
+ leftID=newT.getId();
+ DrawActivity.globalHP.addView(newT);
+ }
+/*
+ final Button elim=new Button(view.getContext());
+ RelativeLayout.LayoutParams myP=new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+ elim.setText("Nuova");
+ elim.setTextSize(TypedValue.COMPLEX_UNIT_SP,16);
+ elim.setId(DrawActivity.globalId++);
+ myP.setMargins(50,0,0,0);
+ sum+=elim.getWidth();
+ if (sum>(DrawActivity.v.widthPixels/1.5)) //ho superato la larghezza dello schermo: devo andare a capo
+ {
+ sum=n.NodeHP.get(i).HP.size();
+ headID=leftID;
+ }
+ else
+ myP.addRule(RelativeLayout.RIGHT_OF,leftID);
+ if (headID!=0)
+ myP.addRule(RelativeLayout.BELOW, headID);
+ elim.setLayoutParams(myP);
+ elim.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ parserDialog p=new parserDialog();
+ p.show(DrawActivity.fragmentManager, ""); //parte l'editor per inserire nuove formule
+ }
+ });
+ DrawActivity.globalHP.addView(elim);
+*/
+
+ }
+}
--- /dev/null
+package com.example.furt.myapplication;
+
+
+import java.util.ArrayList;
+
+public class valutazione {
+ valutazione(){}
+
+ public static int voto (String esercizio, int click, int tempo, int altezza, int errori)
+ {
+ int value=0;
+ ArrayList<String> parametri= parser.getParameters(esercizio);
+ int minClick, minTempo, minAltezza;
+ if(parametri!=null && !parametri.isEmpty())
+ {
+ minClick=Integer.valueOf(parametri.get(0));
+ minTempo=Integer.valueOf(parametri.get(1));
+ minAltezza=Integer.valueOf(parametri.get(2));
+ // minClick : click = x : 14
+ // minTempo : tempo = x : 8
+ // minAltezza : altezza= x : 8
+ value=((minClick*14)/click)+((minTempo*8)/tempo)+((minAltezza*8)/altezza)-errori;
+ if (value>30)
+ value=30;
+ }
+ return value;
+ }
+}