Commit 785cb58a authored by rahadi's avatar rahadi

Added ListingTableView

parent 0ee62465
......@@ -78,7 +78,7 @@ the specific language governing permissions and limitations under the License.
android:xlargeScreens="true" />
<application
android:name="id.ac.stis.capi.application.Collect"
android:name="id.ac.stis.capi.odk.application.Collect"
android:icon="@mipmap/ic_launcher"
android:installLocation="auto"
android:label="@string/app_name"
......
......@@ -2,25 +2,22 @@ package id.ac.stis.capi.collectiva.activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.DragEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.Button;
import android.widget.EditText;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.google.gson.GsonBuilder;
import com.rahadi.vsen.contexts.Vsen;
import com.rahadi.vsen.listeners.OnSynchronizationCompletedListener;
import com.rahadi.vsen.models.UserModel;
import com.rahadi.vsen.tasks.BSSynchronizationTask;
import com.rahadi.vsen.tasks.UserRegisterTask;
import org.json.JSONArray;
import org.json.JSONObject;
import id.ac.stis.capi.R;
import id.ac.stis.capi.odk.preferences.GeneralSharedPreferences;
import id.ac.stis.capi.odk.preferences.PreferenceKeys;
......@@ -44,7 +41,7 @@ public class CapiLoginActivity extends AppCompatActivity
super.onCreate(savedInstanceState);
setContentView(R.layout.capi_activity_login);
TextView serverText = (TextView) findViewById(R.id.server_config_text);
final TextView serverText = (TextView) findViewById(R.id.server_config_text);
loginBtn = (Button) findViewById(R.id.btn_login);
username = (EditText) findViewById(R.id.username);
password = (EditText) findViewById(R.id.password);
......
......@@ -3,7 +3,7 @@ package id.ac.stis.capi.lessthink.binders;
import android.view.View;
import android.widget.TextView;
import id.rahadi.skripsi.R;
import id.ac.stis.capi.R;
import me.texy.treeview.TreeNode;
import me.texy.treeview.base.BaseNodeViewBinder;
......
package id.ac.stis.capi.lessthink.exceptions;
/**
* Author : Rahadi Jalu
* Email : 14.8325@stis.ac.id
* Company: Politeknik Statistika STIS
*/
public class DimensionInvalidException extends Exception {
public DimensionInvalidException(String message) {
super(message);
}
}
......@@ -3,7 +3,8 @@ package id.ac.stis.capi.lessthink.listeners;
import java.util.HashMap;
import java.util.List;
import id.rahadi.skripsi.odk.logic.FormDetails;
import id.ac.stis.capi.odk.logic.FormDetails;
/**
* Author : Rahadi Jalu
......
......@@ -84,7 +84,7 @@ public class DependenciesResolverTask extends AsyncTask<List<FormDetails>, Strin
matcher.setListener(this);
matcher.execute(formDetailsListHashMap);
} else {
onDependenciesResolvingCompleted(new HashMap<>());
onDependenciesResolvingCompleted(new HashMap<FormDetails, List<FormDetails>>());
}
}
......@@ -97,9 +97,9 @@ public class DependenciesResolverTask extends AsyncTask<List<FormDetails>, Strin
* @return list of all dependencies in one form
*/
private List<DependencyDetails> processOneForm(FormDetails formDetails, int total, int count) {
publishProgress(formDetails.getFormName(), String.valueOf(count), String.valueOf(total));
publishProgress(formDetails.formName, String.valueOf(count), String.valueOf(total));
String formId = formDetails.getFormID();
String formId = formDetails.formID;
// FormDetails contains only some basic information.
// To get the file path, we need to get the corresponding Form
......@@ -169,7 +169,7 @@ public class DependenciesResolverTask extends AsyncTask<List<FormDetails>, Strin
for (FormDetails k : keys) {
List<DependencyDetails> evaluateMe = details.get(k);
List<FormDetails> evaluated = evaluateOneFormDependencies(evaluateMe,
k.getFormName(), total, count++);
k.formName, total, count++);
if (evaluated.size() > 0) {
result.put(k, evaluated);
......@@ -206,7 +206,7 @@ public class DependenciesResolverTask extends AsyncTask<List<FormDetails>, Strin
key = keys.get(start);
FormDetails availableForm = formList.get(key);
if (availableForm.getFormID().equals(dependency.getFormID())) {
if (availableForm.formID.equals(dependency.getFormID())) {
break;
}
}
......@@ -228,10 +228,9 @@ public class DependenciesResolverTask extends AsyncTask<List<FormDetails>, Strin
private boolean isFormDownloadNeeded(FormDetails formDetails) {
return formDetails.isNewerFormVersionAvailable() || formDetails.areNewerMediaFilesAvailable()
|| formsDao.getFormsCursorForFormId(formDetails.getFormID()).getCount() == 0;
|| formsDao.getFormsCursorForFormId(formDetails.formID).getCount() == 0;
}
@Override
public void updatedCredentials() {
downloadFormListTask.execute();
......
package id.ac.stis.capi.lessthink.views;
import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
import id.ac.stis.capi.R;
/**
* Author : Rahadi Jalu
* Email : 14.8325@stis.ac.id
* Company: Politeknik Statistika STIS
*/
public class ListingTableView extends View {
public static final int COLUMN_TYPE_HEADER = 1;
public static final int COLUMN_TYPE_BODY = 2;
public static final int SEP_TYPE_HEADER = 3;
public static final int SEP_TYPE_BODY = 4;
private static final int KEY_COLUMN_IDX = 0;
/*
The HashMap<String, String> should be in the form of:
key: header key
value: header name value
*/
private HashMap<String, String> headerList;
/*
ArrayList<> denotes as rows.
The HashMap<String, String> should be in the form of:
key: header key
value: row value
*/
private ArrayList<HashMap<String, String>> rowData;
private LinearLayout headerContainer, rowContainer;
public ListingTableView(Context context) {
super(context);
}
public ListingTableView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public ListingTableView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void init(HashMap<String, String> headerList, ArrayList<HashMap<String, String>> rowData) {
this.headerList = headerList;
this.rowData = rowData;
init();
}
private void init() {
// TODO: 06/06/2018 Proper exception
// if (headerList.size() != rowData.size()) {
// throw new DimensionInvalidException("Number of Column is Invalid");
// }
View v = LayoutInflater.from(getContext()).inflate(R.layout.view_listing_table,
null, false);
headerContainer = v.findViewById(R.id.header_container);
rowContainer = v.findViewById(R.id.row_container);
// Creates Header
int headerIdx = 0;
Set<String> headerKeySet = headerList.keySet();
for (String headerKey : headerKeySet) {
TextView header = createNewColumn(COLUMN_TYPE_HEADER, headerKey,
headerList.get(headerKey), headerIdx);
headerContainer.addView(header);
View separator = createNewSeparator(SEP_TYPE_HEADER, headerKey, headerIdx);
headerContainer.addView(separator);
headerIdx++;
}
// Creates Row
for (int i = 0; i < rowData.size(); i++) {
LinearLayout row = createNewRow(rowData.get(i), i);
rowContainer.addView(row);
}
}
private TextView createNewColumn(int type, String key, String value, int columnIdx) {
TextView column = new TextView(getContext());
column.setTag(key);
column.setTag(KEY_COLUMN_IDX, columnIdx);
column.setText(value);
switch (type) {
case COLUMN_TYPE_HEADER:
column.setContentDescription("h-" + columnIdx);
return column;
case COLUMN_TYPE_BODY:
column.setContentDescription("b-" + columnIdx);
column.setTag(key);
return column;
}
return null;
}
private View createNewSeparator(int type, String key, int columnIdx) {
View separator = new View(getContext());
separator.setTag(key);
separator.setTag(KEY_COLUMN_IDX, columnIdx);
switch (type) {
case SEP_TYPE_HEADER:
separator.setContentDescription("sh-" + columnIdx);
final TextView column = headerContainer.findViewWithTag(key);
column.measure(0, 0);
final int oriWidth = column.getMeasuredWidth();
final ArrayList<View> rowInBodyList = new ArrayList<>();
headerContainer.findViewsWithText(rowInBodyList, "b-" + columnIdx,
FIND_VIEWS_WITH_CONTENT_DESCRIPTION);
separator.setOnTouchListener(new View.OnTouchListener() {
int prevX;
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
view.getParent().requestDisallowInterceptTouchEvent(true);
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
prevX = (int) motionEvent.getRawX();
return true;
case MotionEvent.ACTION_MOVE:
if (column.getMeasuredWidth() + (int) motionEvent.getRawX() - prevX >= oriWidth) {
column.setWidth(column.getMeasuredWidth() + (int) motionEvent.getRawX() - prevX);
for (View rowInBody : rowInBodyList) {
((TextView) rowInBody).setWidth(rowInBody.getMeasuredWidth()
+ (int) motionEvent.getRawX() - prevX);
}
prevX = (int) motionEvent.getRawX();
}
return true;
}
return false;
}
});
return separator;
case SEP_TYPE_BODY:
separator.setContentDescription("sb-" + columnIdx);
return separator;
}
return null;
}
private LinearLayout createNewRow(HashMap<String, String> data, int rowIdx) {
LinearLayout row = new LinearLayout(getContext());
row.setContentDescription("r-" + rowIdx);
row.setOrientation(LinearLayout.HORIZONTAL);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) row.getLayoutParams();
params.width = LinearLayout.LayoutParams.WRAP_CONTENT;
params.height = LinearLayout.LayoutParams.WRAP_CONTENT;
row.setLayoutParams(params);
Set<String> dataKeySet = data.keySet();
for (String dataKey : dataKeySet) {
int idxPosition = (Integer) headerContainer.findViewWithTag(dataKey).getTag(KEY_COLUMN_IDX);
TextView column = createNewColumn(COLUMN_TYPE_BODY, dataKey, data.get(dataKey), idxPosition);
row.addView(column);
View separator = createNewSeparator(SEP_TYPE_BODY, dataKey, idxPosition);
headerContainer.addView(separator);
}
return row;
}
// final HorizontalScrollView header = findViewById(R.id.header_layout);
// header.setOnTouchListener(new View.OnTouchListener() {
// @Override
// public boolean onTouch(View view, MotionEvent motionEvent) {
// return true;
// }
// });
//
// final TextView column1 = findViewById(R.id.column_1);
// column1.measure(0, 0);
//
// final TextView row1 = findViewById(R.id.row_1);
//
// final View dragme = findViewById(R.id.dragme);
// final int oriWidth = column1.getMeasuredWidth();
// dragme.setOnTouchListener(new View.OnTouchListener() {
//
// int prevX;
//
// @Override
// public boolean onTouch(View view, MotionEvent motionEvent) {
// view.getParent().requestDisallowInterceptTouchEvent(true);
// switch (motionEvent.getAction()) {
// case MotionEvent.ACTION_DOWN:
// prevX = (int) motionEvent.getRawX();
// return true;
// case MotionEvent.ACTION_MOVE:
// if(column1.getMeasuredWidth() + (int) motionEvent.getRawX() - prevX >= oriWidth) {
// column1.setWidth(column1.getMeasuredWidth() + (int) motionEvent.getRawX() - prevX);
// row1.setWidth(row1.getMeasuredWidth() + (int) motionEvent.getRawX() - prevX);
// prevX = (int) motionEvent.getRawX();
// }
// return true;
// }
// return false;
// }
// });
//
// final HorizontalScrollView scrollView = findViewById(R.id.scroll_view);
//
// scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
// @Override
// public void onScrollChanged() {
// header.scrollTo(scrollView.getScrollX(), 0);
// }
// });
}
/*
* Copyright (C) 2011 University of Washington
*
*
* 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
......@@ -29,7 +29,8 @@ public class FormDetails implements Serializable {
public final String manifestUrl;
public final String formID;
public final String formVersion;
public boolean isNewerFormVersionAvailable;
public boolean areNewerMediaFilesAvailable;
public FormDetails(String error) {
manifestUrl = null;
......@@ -40,7 +41,6 @@ public class FormDetails implements Serializable {
errorStr = error;
}
public FormDetails(String name, String url, String manifest, String id, String version) {
manifestUrl = manifest;
downloadUrl = url;
......@@ -50,4 +50,50 @@ public class FormDetails implements Serializable {
errorStr = null;
}
public FormDetails(String formName, String downloadUrl, String manifestUrl, String formID,
String formVersion, boolean isNewerFormVersionAvailable,
boolean areNewerMediaFilesAvailable) {
this.formName = formName;
this.downloadUrl = downloadUrl;
this.manifestUrl = manifestUrl;
this.formID = formID;
this.formVersion = formVersion;
errorStr = null;
this.isNewerFormVersionAvailable = isNewerFormVersionAvailable;
this.areNewerMediaFilesAvailable = areNewerMediaFilesAvailable;
}
public String getErrorStr() {
return errorStr;
}
public String getFormName() {
return formName;
}
public String getDownloadUrl() {
return downloadUrl;
}
public String getManifestUrl() {
return manifestUrl;
}
public String getFormID() {
return formID;
}
public String getFormVersion() {
return formVersion;
}
public boolean isNewerFormVersionAvailable() {
return isNewerFormVersionAvailable;
}
public boolean areNewerMediaFilesAvailable() {
return areNewerMediaFilesAvailable;
}
}
......@@ -23,6 +23,7 @@ import org.kxml2.kdom.Document;
import org.kxml2.kdom.Element;
import org.kxml2.kdom.Node;
import id.ac.stis.capi.R;
import id.ac.stis.capi.lessthink.logics.DependencyDetails;
import id.ac.stis.capi.odk.application.Collect;
import java.io.File;
......@@ -39,7 +40,9 @@ import java.net.URLConnection;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import timber.log.Timber;
......@@ -474,4 +477,64 @@ public class FileUtils {
deleteAndReport(tempMediaFolder);
}
}
/**
* Parse the dependencies defined from the form's XML definition
*
* @param file file that are being parsed
* @return the parsed dependencies
*/
public static List<DependencyDetails> parseFormDependencies(File file) {
Timber.d("Parsing dependencies from %s file", file.getAbsolutePath());
final InputStream is;
try {
is = new FileInputStream(file);
} catch (FileNotFoundException e1) {
Timber.e(e1);
throw new IllegalStateException(e1);
}
InputStreamReader isr;
try {
isr = new InputStreamReader(is, "UTF-8");
} catch (UnsupportedEncodingException uee) {
Timber.w(uee, "Trying default encoding as UTF 8 encoding unavailable");
isr = new InputStreamReader(is);
}
final Document doc;
try {
doc = XFormParser.getXMLDocument(isr);
} catch (IOException e) {
Timber.e(e, "Unable to parse XML document %s", file.getAbsolutePath());
throw new IllegalStateException("Unable to parse XML document", e);
} finally {
try {
isr.close();
} catch (IOException e) {
Timber.w("%s error closing from reader", file.getAbsolutePath());
}
}
final String html = doc.getRootElement().getNamespace();
final Element head = doc.getRootElement().getElement(html, "head");
List<DependencyDetails> result = new ArrayList<>();
Element dependencies = getChildElement(head, "dependencies");
if (dependencies != null) {
for (int i = 0; i < dependencies.getChildCount(); i++) {
if (dependencies.getType(i) == Element.ELEMENT) {
Element dependency = dependencies.getElement(i);
String name = dependency.getName();
String id = dependency.getAttributeValue(null, "id");
String version = dependency.getAttributeValue(null, "version");
String on = dependency.getAttributeValue(null, "on");
DependencyDetails details = new DependencyDetails(name, id, version, on);
result.add(details);
}
}
}
return result;
}
}
......@@ -13,24 +13,26 @@
android:layout_height="0dp"
android:layout_weight="3"
android:background="@color/colorPrimary">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:adjustViewBounds="true"
android:src="@drawable/capi_bg_custom"
android:layout_alignParentBottom="true"/>
android:src="@drawable/capi_bg_custom" />
<ImageView
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginTop="16dp"
android:src="@drawable/capi_logo"
android:layout_centerInParent="true" />
android:src="@drawable/capi_logo" />
<!-- view to delete border color in bottom of parent -->
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/white"
android:layout_alignParentBottom="true"/>
android:layout_alignParentBottom="true"
android:background="@color/white" />
</RelativeLayout>
<RelativeLayout
......
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<HorizontalScrollView
android:id="@+id/horizontalScrollView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<LinearLayout
android:id="@+id/header_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal" />
</HorizontalScrollView>
<HorizontalScrollView
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/horizontalScrollView">
<LinearLayout
android:id="@+id/row_container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="vertical" />
</HorizontalScrollView>
</android.support.constraint.ConstraintLayout>
\ No newline at end of file
......@@ -530,4 +530,6 @@
<!-- edit capi peta wb -->
<string name="access_token">pk.eyJ1Ijoia2FkZGFmaSIsImEiOiJjajMwOWlmazkwMDZmMnhvaDA5NnZzbXE0In0.Y9TXg0rJjTybmb3T-z76qw</string>
<string name="fetching_dependencies">Resolving dependencies of %1$s.\n\nForm %2$s of %3$s form(s).</string>
</resources>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment