New version a bit more up to date.

This commit is contained in:
Samy Avrillon 2021-12-10 19:46:45 +01:00
parent 4a851f73d4
commit dbb108dd73
18 changed files with 1271 additions and 15 deletions

View File

@ -33,6 +33,7 @@ android {
dependencies {
implementation 'com.jjoe64:graphview:4.2.2'
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'

View File

@ -13,9 +13,10 @@
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
<activity
android:name=".activities.GraphActivity"
android:exported="false" />
android:exported="false"
android:screenOrientation="landscape"/>
<activity
android:name=".activities.PrepareMeasureActivity"
android:name=".activities.PrepareGraphActivity"
android:exported="false" />
<activity
android:name=".activities.NewMeasureOnSubjectActivity"

View File

@ -11,9 +11,12 @@ import android.util.Log;
import com.bernard.emorph.model.Group;
import com.bernard.emorph.model.MeasureOnSubject;
import com.bernard.emorph.model.Subject;
import com.jjoe64.graphview.series.DataPoint;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class EMorphApplication extends Application {
@ -30,6 +33,14 @@ public class EMorphApplication extends Application {
//putInitialData(db);
}
public static double img(MeasureOnSubject mos, double age){
return 0.098*mos.abdomen-0.170*age + 0.182*mos.bras-0.061*mos.epaules + 0.069*mos.taille + 0.036*mos.cuisse-0.077*mos.cheville-4.266;
}
public static double imm(MeasureOnSubject mos){
Log.d("IMM",mos.toString()+"->"+(0.109*mos.bras + 0.093*mos.cuisse + 0.276*mos.avantBras + 0.078*mos.abdomen - 0.056*mos.taille + 0.703));
return 0.109*mos.bras + 0.093*mos.cuisse + 0.276*mos.avantBras + 0.078*mos.abdomen - 0.056*mos.taille + 0.703;
}
@Override
public void onTerminate() {
super.onTerminate();
@ -145,6 +156,113 @@ public class EMorphApplication extends Application {
return new MeasureOnSubject(newId, subjectId, abdomen, bras, epaules, taille, cuisse, cheville, avantBras);
}
public Long getLastMeasureID(long groupID) {
Cursor dbResult = db.query("measures",new String[]{"ID"},
"groupID=?",new String[]{Long.toString(groupID)}, null, null, "time DESC");
dbResult.moveToFirst();
Long out;
if(dbResult.isAfterLast())
out = null;
else
out = dbResult.getLong(0);
dbResult.close();
return out;
}
public Set<Long> getXLastMeasures(long groupID, int x){
Cursor dbResult = db.query("measures",new String[]{"ID"},
"groupID=?",new String[]{Long.toString(groupID)}, null, null, "time DESC");
dbResult.moveToFirst();
Set<Long> out = new HashSet<>();
for(int i=0;i<x && !dbResult.isAfterLast();i++) {
out.add(dbResult.getLong(0));
dbResult.moveToNext();
}
dbResult.close();
return out;
}
public Set<Long> getMeasuresIDs(long groupID){
Cursor dbResult = db.query("measures",new String[]{"ID"},
"groupID=?",new String[]{Long.toString(groupID)}, null, null, null);
dbResult.moveToFirst();
Set<Long> out = new HashSet<>();
while(!dbResult.isAfterLast()) {
out.add(dbResult.getLong(0));
dbResult.moveToNext();
}
dbResult.close();
return out;
}
public Set<Long> getMeasuresSince(long groupID, long oldDate) {
Cursor dbResult = db.query("measures",new String[]{"ID"},
"groupID=? AND time>?",new String[]{Long.toString(groupID),Long.toString(oldDate)},
null, null, null);
dbResult.moveToFirst();
Set<Long> out = new HashSet<>();
while(!dbResult.isAfterLast()) {
out.add(dbResult.getLong(0));
dbResult.moveToNext();
}
dbResult.close();
return out;
}
public MeasureOnSubject getMos(long subjectID, long measureID){
Cursor dbResult = db.query("measuresOnSubjects",new String[]{"ID","subjectID","circAbdomen","circBras","circEpaules","circTaille","circCuisse","circCheville","circAvantBras"},
"subjectID = ?",new String[]{Long.toString(subjectID)/*,Long.toString(measureID)*/},
null, null, null);
dbResult.moveToFirst();
MeasureOnSubject out;
if(dbResult.isAfterLast())
out = null;
else
out = new MeasureOnSubject(
dbResult.getLong(0),
dbResult.getLong(1),
dbResult.getFloat(2),
dbResult.getFloat(3),
dbResult.getFloat(4),
dbResult.getFloat(5),
dbResult.getFloat(6),
dbResult.getFloat(7),
dbResult.getFloat(8)
);
dbResult.close();
return out;
}
public long dateNaissance(long subjectID){
Cursor result = db.query("subjects",new String[]{"dateNaissance"},"ID=?", new String[]{Long.toString(subjectID)},null,null,null);
if(result.getCount()==0)return -1;
result.moveToFirst();
long out = result.getLong(0);
result.close();
return out;
}
public void dumpTable(String tableName){
Cursor c = db.rawQuery("SELECT * FROM "+tableName,new String[0]);
c.moveToFirst();
StringBuilder sb = new StringBuilder("Dumping table "+tableName+" :\n");
while(!c.isAfterLast()){
for(int i=0;i<c.getColumnCount();i++)
sb.append(c.getString(i)).append(";");
sb.append("\n");
Log.d("DbDump",sb.toString());
c.moveToNext();
}
c.close();
}
public DataPoint point(long subjectID, long measureID){
float age = ((((float)System.currentTimeMillis())/(1000.f))-dateNaissance(subjectID))/3600f/365.24f;
MeasureOnSubject mos = getMos(subjectID,measureID);
if(mos==null)return null;
return new DataPoint(imm(mos),img(mos, age));
}
public static class EMorphDbHelper extends SQLiteOpenHelper {
// If you change the database schema, you must increment the database version.
@ -189,13 +307,13 @@ public class EMorphApplication extends Application {
cv.put("ID", testDatum[0]);
cv.put("measureID", testDatum[1]);
cv.put("subjectID", testDatum[2]);
cv.put("circAbdomen", testDatum[3]);
cv.put("circBras", testDatum[4]);
cv.put("circEpaules", testDatum[5]);
cv.put("circTaille", testDatum[6]);
cv.put("circCuisse", testDatum[7]);
cv.put("circCheville", testDatum[8]);
cv.put("circAvantBras", testDatum[9]);
cv.put("circAbdomen", testDatum[8]);
cv.put("circBras", testDatum[6]);
cv.put("circEpaules", testDatum[7]);
cv.put("circTaille", testDatum[9]);
cv.put("circCuisse", testDatum[4]);
cv.put("circCheville", testDatum[3]);
cv.put("circAvantBras", testDatum[5]);
db.insert("measuresOnSubjects", null, cv);
}
for (Object[] testDatum : testData2) {

View File

@ -0,0 +1,249 @@
package com.bernard.emorph;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.Log;
import com.jjoe64.graphview.GraphView;
import com.jjoe64.graphview.RectD;
import com.jjoe64.graphview.series.BaseSeries;
import com.jjoe64.graphview.series.DataPointInterface;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class SquaringGraphSeries extends BaseSeries<SquaringGraphSeries.DirectionalRectanglePoint> {
/**
* paint to do drawing on canvas
*/
private final Paint mPaint;
/**
* stores the coordinates of the bars to
* trigger tap on series events.
*/
private final Map<RectD, SquaringGraphSeries.DirectionalRectanglePoint> mDataPoints = new HashMap<>();
/**
* creates bar series with data
*
* @param data data points
* important: array has to be sorted from lowest x-value to the highest
*/
public SquaringGraphSeries(SquaringGraphSeries.DirectionalRectanglePoint[] data) {
super(data);
mPaint = new Paint();
}
/**
* draws the bars on the canvas
*
* @param graphView corresponding graphview
* @param canvas canvas
* @param isSecondScale whether we are plotting the second scale or not
*/
@Override
public void draw(GraphView graphView, Canvas canvas, boolean isSecondScale) {
resetDataPoints();
// get data
double maxX = graphView.getViewport().getMaxX(false);
double minX = graphView.getViewport().getMinX(false);
double maxY;
double minY;
if (isSecondScale) {
maxY = graphView.getSecondScale().getMaxY(false);
minY = graphView.getSecondScale().getMinY(false);
} else {
maxY = graphView.getViewport().getMaxY(false);
minY = graphView.getViewport().getMinY(false);
}
/*
// Iterate through all bar graph series
// so we know how wide to make our bar,
// and in what position to put it in
int numBarSeries = 0;
int currentSeriesOrder = 0;
int numValues = 0;
boolean isCurrentSeries;
SortedSet<Double> xVals = new TreeSet<Double>();
for(Series<?> inspectedSeries: graphView.getSeries()) {
if(inspectedSeries instanceof SquaringGraphSeries) {
isCurrentSeries = (inspectedSeries == this);
if(isCurrentSeries) {
currentSeriesOrder = numBarSeries;
}
numBarSeries++;
// calculate the number of slots for bars based on the minimum distance between
// x coordinates in the series. This is divided into the range to find
// the placement and width of bar slots
// (sections of the x axis for each bar or set of bars)
// TODO: Move this somewhere more general and cache it, so we don't recalculate it for each series
Iterator<?> curValues = inspectedSeries.getValues(minX, maxX);
if (curValues.hasNext()) {
xVals.add(((DirectionalRectanglePoint)curValues.next()).getX());
if(isCurrentSeries) { numValues++; }
while (curValues.hasNext()) {
xVals.add(((DirectionalRectanglePoint)curValues.next()).getX());
if(isCurrentSeries) { numValues++; }
}
}
}
}
if (numValues == 0) {
return;
}
double minGap = 0;
if(mDataWidth > 0.0) {
minGap = mDataWidth;
} else {
Double lastVal = null;
for(Double curVal: xVals) {
if(lastVal != null) {
double curGap = Math.abs(curVal - lastVal);
if (minGap == 0 || (curGap > 0 && curGap < minGap)) {
minGap = curGap;
}
}
lastVal = curVal;
}
}
int numBarSlots = (minGap == 0) ? 1 : (int)Math.round((maxX - minX)/minGap) + 1;
*/
Iterator<SquaringGraphSeries.DirectionalRectanglePoint> values = getValues(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY);
// Calculate the overall bar slot width - this includes all bars across
// all series, and any spacing between sets of bars
double diffY = maxY - minY;
double diffX = maxX - minX;
double contentHeight = graphView.getGraphContentHeight();
double contentWidth = graphView.getGraphContentWidth();
double contentLeft = graphView.getGraphContentLeft();
double contentTop = graphView.getGraphContentTop();
// draw data
while (values.hasNext()) {
SquaringGraphSeries.DirectionalRectanglePoint value = values.next();
double top = contentTop + (maxY-value.top)*contentHeight/diffY;
double bottom = contentTop + (maxY-value.bottom)*contentHeight/diffY;
double left = contentLeft + contentWidth*(value.left-minX)/diffX;
double right = contentLeft + contentWidth*(value.right-minX)/diffX;
// hook for value dependent color
if (value.color != -1) {
int ncol = value.color&0xFFFFFF, nalp = value.color>>24;
mPaint.setColor(ncol);
mPaint.setAlpha(nalp);
} else {
mPaint.setColor(getColor());
}
// overdraw
top = forceBetween(top, contentTop, contentTop+contentHeight);
right = forceBetween(right, contentLeft,contentLeft+contentWidth);
bottom = forceBetween(bottom, contentTop, contentTop+contentHeight);
left = forceBetween(left, contentLeft,contentLeft+contentWidth);
Log.d("SquaringGraphDrawer","Drawing rectangle "+top+";"+left+";"+bottom+";"+right);
mDataPoints.put(new RectD(left, top, right, bottom), value);
canvas.drawRect((float)left, (float)top, (float)right, (float)bottom, mPaint);
/*
// set values on top of graph
if (mDrawValuesOnTop) {
if (reverse) {
top = bottom + mValuesOnTopSize + 4;
if (top > contentTop+contentHeight) top = contentTop + contentHeight;
} else {
top -= 4;
if (top<=contentTop) top+=contentTop+4;
}
mPaint.setColor(mValuesOnTopColor);
canvas.drawText(
graphView.getGridLabelRenderer().getLabelFormatter().formatLabel(value.getY(), false)
, (float) (left+right)/2, (float) top, mPaint);
}
*/
}
}
public static double forceBetween(double value, double min, double max){
return Math.max(Math.min(value,max),min);
}
/**
* resets the cached coordinates of the bars
*/
@Override
protected void resetDataPoints() {
mDataPoints.clear();
}
/**
* find the corresponding data point by
* coordinates.
*
* @param x pixels
* @param y pixels
* @return datapoint or null
*/
@Override
protected SquaringGraphSeries.DirectionalRectanglePoint findDataPoint(float x, float y) {
for (Map.Entry<RectD, SquaringGraphSeries.DirectionalRectanglePoint> entry : mDataPoints.entrySet()) {
if (x >= entry.getKey().left && x <= entry.getKey().right
&& y >= entry.getKey().top && y <= entry.getKey().bottom) {
return entry.getValue();
}
}
return null;
}
@Override
public void drawSelection(GraphView mGraphView, Canvas canvas, boolean b, DataPointInterface value) {
// We do nothing more
}
public static class DirectionalRectanglePoint implements DataPointInterface {
double top,left,bottom,right;
int color;
public DirectionalRectanglePoint(double top, double left, double bottom, double right, int color) {
this.top = top;
this.left = left;
this.bottom = bottom;
this.right = right;
this.color = color;
}
@Override
public double getX() {
return left;
}
@Override
public double getY() {
return top;
}
}
}

View File

@ -1,14 +1,167 @@
package com.bernard.emorph.activities;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import com.bernard.emorph.EMorphApplication;
import com.bernard.emorph.R;
import com.bernard.emorph.SquaringGraphSeries;
import com.bernard.emorph.model.ToGraph;
import com.jjoe64.graphview.GraphView;
import com.jjoe64.graphview.Viewport;
import com.jjoe64.graphview.series.DataPoint;
import com.jjoe64.graphview.series.PointsGraphSeries;
import com.jjoe64.graphview.series.Series;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Random;
public class GraphActivity extends AppCompatActivity {
public static final String TOGRAPH_TO_GRAPH_EXTRA = "com.bernard.emorph.activities.GraphActivity.toGraph";
ToGraph toGraph;
GraphView gv;
EMorphApplication theApp;
int[] colors;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_graph);
Intent theIntent = getIntent();
toGraph = theIntent.getParcelableExtra(TOGRAPH_TO_GRAPH_EXTRA);
theApp = (EMorphApplication) getApplication();
gv = findViewById(R.id.theGraphView);
String[] cs = getResources().getStringArray(R.array.distinctGraphColors);
colors = new int[cs.length];
for (int i = 0; i < colors.length; i++)
colors[i] = Integer.parseInt(cs[i].substring(1),16);
initGraph();
}
public static final double MEGA_MAX_IMG = 50;
public static final double MEGA_MIN_IMG = -50;
public static final double MEGA_MAX_IMM = 100;
public static final double MEGA_MIN_IMM = 0;
public void initGraph(){
int subjectCount = toGraph.getSubjectsID().length;
DataPoint[] points0 = new DataPoint[subjectCount];
double minx=1e10f,maxx=0f,miny=1e10f,maxy=0f;
PointsGraphSeries[] pgs = new PointsGraphSeries[toGraph.getMeasuresID().length];
for(int j=0; j<toGraph.getMeasuresID().length; j++) {
int realSize = 0;
for (int i = 0; i < subjectCount; i++) {
points0[i] = theApp.point(toGraph.getSubjectsID()[i], toGraph.getMeasuresID()[j]);
if (points0[i] != null) {
realSize++;
if(minx>points0[i].getX())minx = points0[i].getX();
if(maxx<points0[i].getX())maxx = points0[i].getX();
if(miny>points0[i].getY())miny = points0[i].getY();
if(maxy<points0[i].getY())maxy = points0[i].getY();
}
}
Arrays.sort(points0,(d1,d2)->(d1==null)?((d2==null)?0:-1):((d2==null)?1:Double.compare(d1.getX(),d2.getX())));
DataPoint[] points = new DataPoint[realSize];
System.arraycopy(points0,0,points,0,realSize);
PointsGraphSeries<DataPoint> series = new PointsGraphSeries<>(points);
series.setShape(PointsGraphSeries.Shape.POINT);
series.setColor(colors[j]|0xFF000000);
series.setSize(10);
pgs[j] = series;
Log.d("NewSeries","Nouvelle serie de "+realSize+" points: couleur #"+Integer.toHexString(colors[j]));
}
// Calcul des valeurs limites
double moyIMM, sdIMM, moyIMG, sdIMG;
switch(toGraph.getBase()){
case LABO_U11:
moyIMM=14.9;
sdIMM=1.3;
moyIMG=4.4;
sdIMG=2.5;
break;
case LABO_U13:
moyIMM=15.6;
sdIMM=1.8;
moyIMG=4.7;
sdIMG=1.9;
break;
case LABO_U15:
moyIMM=18.5;
sdIMM=2.0;
moyIMG=6.7;
sdIMG=2.4;
break;
default:
// on s'amuse
// On prend la moyenne et l'ecart type d'absolument toutes les valeurs.
moyIMM = sdIMM = moyIMG = sdIMG = 0;
int c = 0;
for(PointsGraphSeries<?> s : pgs){
Iterator<?> it = s.getValues(s.getLowestValueX(),s.getHighestValueX());
while(it.hasNext()){
DataPoint dp = (DataPoint) it.next(); // Ne devrait pas poser de problème.
moyIMM += dp.getX();
sdIMM += dp.getX()*dp.getX();
moyIMG += dp.getY();
sdIMG += dp.getY()*dp.getY();
c++;
}
}
moyIMM /= c;
moyIMG /= c;
sdIMM = Math.sqrt((sdIMM/c)-moyIMM*moyIMM);
sdIMG = Math.sqrt((sdIMG/c)-moyIMG*moyIMG); // Je crois que les formules sont bonnes.
}
Viewport theVP = gv.getViewport();
theVP.setXAxisBoundsManual(true);
theVP.setMinX(Math.min(minx,moyIMM-sdIMM)-.4);
theVP.setMaxX(Math.max(maxx,moyIMM+sdIMM)+.4);
theVP.setYAxisBoundsManual(true);
theVP.setMinY(Math.min(miny,moyIMG-sdIMG)-.4);
theVP.setMaxY(Math.max(maxy,moyIMG+sdIMG)+.4);
int interColor = 0x53FFFF00;
int extremeColor = 0x53FF0000;
SquaringGraphSeries sgs = new SquaringGraphSeries(new SquaringGraphSeries.DirectionalRectanglePoint[]{
new SquaringGraphSeries.DirectionalRectanglePoint(MEGA_MAX_IMG ,MEGA_MIN_IMM ,moyIMG+sdIMG,moyIMM-sdIMM,extremeColor),
new SquaringGraphSeries.DirectionalRectanglePoint(moyIMG-sdIMG,MEGA_MIN_IMM ,MEGA_MIN_IMG,moyIMM-sdIMM,extremeColor),
new SquaringGraphSeries.DirectionalRectanglePoint(moyIMG+sdIMG,MEGA_MIN_IMM ,moyIMG-sdIMG,moyIMM-sdIMM,interColor),
new SquaringGraphSeries.DirectionalRectanglePoint(MEGA_MAX_IMG ,moyIMM-sdIMM,moyIMG+sdIMG,moyIMM+sdIMM,interColor),
new SquaringGraphSeries.DirectionalRectanglePoint(moyIMG-sdIMG,moyIMM-sdIMM,MEGA_MIN_IMG,moyIMM+sdIMM, interColor),
new SquaringGraphSeries.DirectionalRectanglePoint(MEGA_MAX_IMG ,moyIMM+sdIMM,moyIMG+sdIMG,MEGA_MAX_IMM,extremeColor),
new SquaringGraphSeries.DirectionalRectanglePoint(moyIMG-sdIMG,moyIMM+sdIMM,MEGA_MIN_IMG,MEGA_MAX_IMM,extremeColor),
new SquaringGraphSeries.DirectionalRectanglePoint(moyIMG+sdIMG,moyIMM+sdIMM,moyIMG-sdIMG,MEGA_MAX_IMM,interColor)
});
gv.addSeries(sgs);
for (PointsGraphSeries<?> pg : pgs) gv.addSeries(pg);
}
public final int randCol(){
Random r = new Random();
return Color.HSVToColor(255, new float[]{r.nextFloat()*360,1.0f,1.0f});
}
}

View File

@ -49,6 +49,11 @@ public class GroupListActivity extends AppCompatActivity {
}
public void startGraphGroup(Group g){
Intent theIntent = new Intent(this, PrepareGraphActivity.class);
theIntent.putExtra(PrepareGraphActivity.GROUPID_TO_GRAPH_EXTRA, g.id);
startActivity(theIntent);
}
public void startModifyGroup(Group g){
Intent theIntent = new Intent(this, EditSubjectListActivity.class);
theIntent.putExtra(EditSubjectListActivity.GROUPID_EXTRA, g.id);
@ -81,6 +86,9 @@ public class GroupListActivity extends AppCompatActivity {
this.newDataButton = buttonsLayout.findViewById(R.id.new_data_button);
this.modifyGroupButton = buttonsLayout.findViewById(R.id.modify_group_button);
this.dataViewButton.setOnClickListener((e)->{
if(selectedIndex!=groups.size())startGraphGroup(groups.get(selectedIndex));
});
this.modifyGroupButton.setOnClickListener((e)->{
if(selectedIndex==groups.size())
startNewGroup();

View File

@ -109,6 +109,8 @@ public class NewMeasureActivity extends AppCompatActivity {
.show();
return;
}
finish();
}
class SubjectListAdapter extends RecyclerView.Adapter<NewMeasureActivity.SubjectListAdapter.ViewHolder> {

View File

@ -0,0 +1,252 @@
package com.bernard.emorph.activities;
import android.app.DatePickerDialog;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.NumberPicker;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.bernard.emorph.EMorphApplication;
import com.bernard.emorph.R;
import com.bernard.emorph.model.Subject;
import com.bernard.emorph.model.ToGraph;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class PrepareGraphActivity extends AppCompatActivity {
public static final String GROUPID_TO_GRAPH_EXTRA = "com.bernard.emorph.activities.PrepareGraphActivity.GroupIDToGraph";
long groupID;
Spinner measuresSelectorSpinner;
Set<Long> selectedMeasuresIDs;
CheckBox everySubjectCheckbox;
List<Subject> subjects;
Set<Long> selectedSubjects;
RecyclerView rv;
Spinner basisSelectorSpinner;
Button okButton;
EMorphApplication theApp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_prepare_graph);
Intent theIntent = getIntent();
groupID = theIntent.getLongExtra(GROUPID_TO_GRAPH_EXTRA,-1L);
theApp = (EMorphApplication) getApplication();
measuresSelectorSpinner = findViewById(R.id.measureSelector);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
R.array.measureSelectorsTypes, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
measuresSelectorSpinner.setAdapter(adapter);
everySubjectCheckbox = findViewById(R.id.everySubjectCheckbox);
rv = findViewById(R.id.subjectsList);
SubjectListAdapter sla = new SubjectListAdapter();
rv.setAdapter(sla);
rv.setLayoutManager(new LinearLayoutManager(this));
basisSelectorSpinner = findViewById(R.id.basisSelector);
ArrayAdapter<CharSequence> adapter2 = ArrayAdapter.createFromResource(this,
R.array.basisTypes, android.R.layout.simple_spinner_item);
adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
basisSelectorSpinner.setAdapter(adapter2);
okButton = findViewById(R.id.okButton);
selectedMeasuresIDs = Collections.singleton(theApp.getLastMeasureID(groupID));
measuresSelectorSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
switch(i){
case 0: // Dernière
selectedMeasuresIDs = Collections.singleton(theApp.getLastMeasureID(groupID));
return;
case 1: // 5 dernières
selectedMeasuresIDs = theApp.getXLastMeasures(groupID, 5);
return;
case 2: // x dernières
final AlertDialog.Builder d = new AlertDialog.Builder(PrepareGraphActivity.this);
LayoutInflater inflater = PrepareGraphActivity.this.getLayoutInflater();
View dialogView = inflater.inflate(R.layout.number_picker_dialog, null);
d.setTitle(R.string.measureCountDialogTitle);
d.setMessage(R.string.measureCountDialogMessage);
d.setView(dialogView);
final NumberPicker numberPicker = (NumberPicker) dialogView.findViewById(R.id.dialog_number_picker);
numberPicker.setMaxValue(100);
numberPicker.setMinValue(1);
numberPicker.setWrapSelectorWheel(false);
d.setPositiveButton(android.R.string.ok, (di,j)->selectedMeasuresIDs = theApp.getXLastMeasures(groupID, numberPicker.getValue()));
d.setNegativeButton(android.R.string.cancel, (di,j)->selectedMeasuresIDs = Collections.singleton(theApp.getLastMeasureID(groupID)));
AlertDialog alertDialog = d.create();
alertDialog.show();
return;
case 3: // à partir du
Calendar mcurrentDate=Calendar.getInstance();
int year = mcurrentDate.get(Calendar.YEAR);
int month = mcurrentDate.get(Calendar.MONTH);
int day = mcurrentDate.get(Calendar.DAY_OF_MONTH);
DatePickerDialog mDatePicker=new DatePickerDialog(PrepareGraphActivity.this,
(datepicker, selectedYear, selectedMonth, selectedDay) -> {
Log.d("Date Selected", "Month: " + selectedMonth + " Day: " + selectedDay + " Year: " + selectedYear);
Calendar selected = Calendar.getInstance();
selected.set(selectedYear, selectedMonth, selectedDay);
selectedMeasuresIDs = theApp.getMeasuresSince(groupID, selected.getTimeInMillis()/1000);
},year, month, day);
mDatePicker.setOnDismissListener((e) -> measuresSelectorSpinner.setSelection(0));
mDatePicker.setOnCancelListener((e) -> measuresSelectorSpinner.setSelection(0));
mDatePicker.setTitle(R.string.sinceWhenDialog);
mDatePicker.show();
return;
case 4: // Toutes
selectedMeasuresIDs = theApp.getMeasuresIDs(groupID);
return;
default: // Spécifique
//TODO: Faire un dialog permetant de sélectionner les mesures
selectedMeasuresIDs = Collections.singleton(theApp.getLastMeasureID(groupID));
measuresSelectorSpinner.setSelection(0);
Toast.makeText(PrepareGraphActivity.this, R.string.notImplementedYet, Toast.LENGTH_SHORT).show();
}
}
@Override
public void onNothingSelected(AdapterView<?> adapterView) {
selectedMeasuresIDs = Collections.emptySet();
}
});
everySubjectCheckbox.setSelected(true);
rv.setEnabled(false);
everySubjectCheckbox.setOnCheckedChangeListener((e,b)-> {rv.setEnabled(!b);Log.d("Résultat","Check: "+b+"; Enablé: "+rv.isEnabled());});
subjects = theApp.getSubjects(groupID);
selectedSubjects = new HashSet<>();
for(Subject s : subjects)
selectedSubjects.add(s.id);
okButton.setOnClickListener((e)->drawGraph());
}
public ToGraph.Base selectedBasis(){
//TODO Rework this
switch(basisSelectorSpinner.getSelectedItemPosition()) {
case 0:
return ToGraph.Base.LABO_U11;
case 1:
return ToGraph.Base.LABO_U13;
case 2:
return ToGraph.Base.LABO_U15;
default:
return ToGraph.Base.GROUPE;
}
}
public void drawGraph(){
ToGraph tg;
if(everySubjectCheckbox.isChecked())
tg = ToGraph.getS(selectedMeasuresIDs, subjects, selectedBasis());
else
tg = ToGraph.get(selectedMeasuresIDs, selectedSubjects, selectedBasis());
if(tg.getMeasuresID().length==0 || tg.getSubjectsID().length==0){
Toast.makeText(this, R.string.cantGraphNoInput, Toast.LENGTH_SHORT).show();
return;
}
Intent drawGraphIntent = new Intent(this, GraphActivity.class);
drawGraphIntent.putExtra(GraphActivity.TOGRAPH_TO_GRAPH_EXTRA, tg);
startActivity(drawGraphIntent);
}
class SubjectListAdapter extends RecyclerView.Adapter<PrepareGraphActivity.SubjectListAdapter.ViewHolder> {
public SubjectListAdapter(){}
@NonNull
@Override
public PrepareGraphActivity.SubjectListAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View theView = LayoutInflater.from(parent.getContext()).inflate(R.layout.preparegraph_subject_list_item, parent, false);
return new PrepareGraphActivity.SubjectListAdapter.ViewHolder(theView);
}
@Override
public void onBindViewHolder(@NonNull PrepareGraphActivity.SubjectListAdapter.ViewHolder holder, int position) {
holder.titleText.setText(subjects.get(position).name);
holder.subjectBox.setOnCheckedChangeListener((e,b) -> checkSubject(subjects.get(position),b));
}
public void checkSubject(Subject s, boolean isChecked){
if(isChecked)
selectedSubjects.add(s.id);
else
selectedSubjects.remove(s.id);
}
@Override
public int getItemCount() {
return subjects.size();
}
class ViewHolder extends RecyclerView.ViewHolder{
TextView titleText;
CheckBox subjectBox;
View theView;
public ViewHolder(View theView) {
super(theView);
this.theView = theView;
this.titleText = theView.findViewById(R.id.subjectNameText);
this.subjectBox = theView.findViewById(R.id.subjectCheckbox);
}
}
}
}

View File

@ -64,4 +64,19 @@ public class MeasureOnSubject implements Parcelable {
p.writeFloat(cheville);
p.writeFloat(avantBras);
}
@Override
public String toString() {
return "MeasureOnSubject{" +
"mosId=" + mosId +
", subjectID=" + subjectID +
", abdomen=" + abdomen +
", bras=" + bras +
", epaules=" + epaules +
", taille=" + taille +
", cuisse=" + cuisse +
", cheville=" + cheville +
", avantBras=" + avantBras +
'}';
}
}

View File

@ -1,6 +1,11 @@
package com.bernard.emorph.model;
public class ToGraph {
import android.os.Parcel;
import android.os.Parcelable;
import java.util.Collection;
public class ToGraph implements Parcelable {
long[] measuresID;
@ -8,8 +13,86 @@ public class ToGraph {
Base base;
enum Base {
LABO, GROUPE;
public enum Base {
LABO_U11, LABO_U13, LABO_U15, GROUPE
}
public ToGraph(long[] measuresID, long[] subjectsID, Base base) {
this.measuresID = measuresID;
this.subjectsID = subjectsID;
this.base = base;
}
public static ToGraph get(Collection<Long> measuresID, Collection<Long> subjectsID, Base base) {
return new ToGraph(longCollectionToLongArray(measuresID),longCollectionToLongArray(subjectsID),base);
}
public static ToGraph getS(Collection<Long> measuresID, Collection<Subject> subjects, Base base) {
return new ToGraph(longCollectionToLongArray(measuresID),subjectsCollectionToLongArray(subjects),base);
}
private ToGraph(Parcel p){
this.measuresID = new long[p.readInt()];
p.readLongArray(this.measuresID);
this.subjectsID = new long[p.readInt()];
p.readLongArray(this.subjectsID);
base = Base.values()[p.readInt()];
}
public static final Creator<ToGraph> CREATOR = new Creator<ToGraph>() {
@Override
public ToGraph createFromParcel(Parcel parcel) {
return new ToGraph(parcel);
}
@Override
public ToGraph[] newArray(int i) {
return new ToGraph[i];
}
};
public long[] getMeasuresID() {
return measuresID;
}
public long[] getSubjectsID() {
return subjectsID;
}
public Base getBase() {
return base;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel parcel, int i) {
parcel.writeInt(measuresID.length);
parcel.writeLongArray(this.measuresID);
parcel.writeInt(subjectsID.length);
parcel.writeLongArray(this.subjectsID);
parcel.writeInt(base.ordinal());
}
public static long[] longCollectionToLongArray(Collection<Long> c){
long[] mi = new long[c.size()];
int i=0;
for(Long m : c){
mi[i] = m;
i++;
}
return mi;
}
public static long[] subjectsCollectionToLongArray(Collection<Subject> c){
long[] mi = new long[c.size()];
int i=0;
for(Subject s : c){
mi[i] = s.id;
i++;
}
return mi;
}
}

View File

@ -1,9 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
tools:context=".activities.GraphActivity">
<com.jjoe64.graphview.GraphView
android:id="@+id/theGraphView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,148 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
tools:context=".activities.PrepareGraphActivity">
<androidx.appcompat.widget.Toolbar
android:id="@+id/app_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/measureSelectorLayout"
android:background="?attr/colorPrimary"
android:elevation="4dp"
app:title="@string/prepareGraphTitle"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/measureSelectorLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/app_toolbar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/subjectsFieldLayout">
<TextView
android:id="@+id/measureSelectorLabel"
android:labelFor="@id/measureSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/measureSelector"
android:text="@string/measureSelectorTitle"
android:minHeight="48dp"/>
<Spinner
android:id="@+id/measureSelector"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/measureSelectorLabel"
app:layout_constraintEnd_toEndOf="parent"
android:minHeight="48dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/subjectsFieldLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintTop_toBottomOf="@id/measureSelectorLayout"
app:layout_constraintBottom_toTopOf="@id/basisSelectorLayout"
android:paddingTop="3dp"
android:paddingBottom="3dp">
<TextView
android:id="@+id/subjectFieldLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/subjectSelectTitle"
app:layout_constraintBottom_toTopOf="@id/subjectsListScroll"
app:layout_constraintEnd_toStartOf="@id/everySubjectCheckbox"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<CheckBox
android:id="@+id/everySubjectCheckbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/subjectsListScroll"
app:layout_constraintStart_toEndOf="@id/subjectFieldLabel"
app:layout_constraintEnd_toStartOf="@id/everySubjectCheckboxLabel"
android:checked="true"/>
<TextView
android:id="@+id/everySubjectCheckboxLabel"
android:labelFor="@id/everySubjectCheckbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/subjectsListScroll"
app:layout_constraintStart_toEndOf="@id/everySubjectCheckbox"
app:layout_constraintEnd_toEndOf="parent"
android:textAppearance="@style/preparegraph_subjects_list_item"
android:text="@string/everybody"/>
<ScrollView
android:id="@+id/subjectsListScroll"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/subjectFieldLabel">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/subjectsList"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</ScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/basisSelectorLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/subjectsFieldLayout"
app:layout_constraintBottom_toTopOf="@id/okButton">
<TextView
android:id="@+id/basisSelectorLabel"
android:labelFor="@id/basisSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/basisSelector"
android:minHeight="48dp"
android:text="@string/basis"/>
<Spinner
android:id="@+id/basisSelector"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/basisSelectorLabel"
app:layout_constraintEnd_toEndOf="parent"
android:minHeight="48dp"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<Button
android:id="@+id/okButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/basisSelectorLayout"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="@string/drawGraph"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:gravity="center_horizontal">
<NumberPicker
android:id="@+id/dialog_number_picker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<CheckBox
android:id="@+id/subjectCheckbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/subjectNameText"
android:checked="true"/>
<TextView
android:id="@+id/subjectNameText"
android:labelFor="@id/subjectCheckbox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/subjectCheckbox"
app:layout_constraintEnd_toEndOf="parent"
android:contentDescription="@string/subjectNameDesc"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="basisTypes">
<item>@string/lab11Basis</item>
<item>@string/lab13Basis</item>
<item>@string/lab15Basis</item>
<item>@string/localBasis</item>
</string-array>
<string-array name="measureSelectorsTypes">
<item>@string/lastMeasure</item>
<item>@string/last5Measures</item>
<item>@string/xlastMeasures</item>
<item>@string/sinceMeasures</item>
<item>@string/everyMeasure</item>
<item>@string/customMeasures</item>
</string-array>
<string name="lab11Basis">Données U11</string>
<string name="lab13Basis">Données U13</string>
<string name="lab15Basis">Données U15</string>
</resources>

View File

@ -7,4 +7,136 @@
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<string-array name="distinctGraphColors">
<item>#000000</item>
<item>#FFFF00</item>
<item>#1CE6FF</item>
<item>#FF34FF</item>
<item>#FF4A46</item>
<item>#008941</item>
<item>#006FA6</item>
<item>#A30059</item>
<item>#FFDBE5</item>
<item>#7A4900</item>
<item>#0000A6</item>
<item>#63FFAC</item>
<item>#B79762</item>
<item>#004D43</item>
<item>#8FB0FF</item>
<item>#997D87</item>
<item>#5A0007</item>
<item>#809693</item>
<item>#FEFFE6</item>
<item>#1B4400</item>
<item>#4FC601</item>
<item>#3B5DFF</item>
<item>#4A3B53</item>
<item>#FF2F80</item>
<item>#61615A</item>
<item>#BA0900</item>
<item>#6B7900</item>
<item>#00C2A0</item>
<item>#FFAA92</item>
<item>#FF90C9</item>
<item>#B903AA</item>
<item>#D16100</item>
<item>#DDEFFF</item>
<item>#000035</item>
<item>#7B4F4B</item>
<item>#A1C299</item>
<item>#300018</item>
<item>#0AA6D8</item>
<item>#013349</item>
<item>#00846F</item>
<item>#372101</item>
<item>#FFB500</item>
<item>#C2FFED</item>
<item>#A079BF</item>
<item>#CC0744</item>
<item>#C0B9B2</item>
<item>#C2FF99</item>
<item>#001E09</item>
<item>#00489C</item>
<item>#6F0062</item>
<item>#0CBD66</item>
<item>#EEC3FF</item>
<item>#456D75</item>
<item>#B77B68</item>
<item>#7A87A1</item>
<item>#788D66</item>
<item>#885578</item>
<item>#FAD09F</item>
<item>#FF8A9A</item>
<item>#D157A0</item>
<item>#BEC459</item>
<item>#456648</item>
<item>#0086ED</item>
<item>#886F4C</item>
<item>#34362D</item>
<item>#B4A8BD</item>
<item>#00A6AA</item>
<item>#452C2C</item>
<item>#636375</item>
<item>#A3C8C9</item>
<item>#FF913F</item>
<item>#938A81</item>
<item>#575329</item>
<item>#00FECF</item>
<item>#B05B6F</item>
<item>#8CD0FF</item>
<item>#3B9700</item>
<item>#04F757</item>
<item>#C8A1A1</item>
<item>#1E6E00</item>
<item>#7900D7</item>
<item>#A77500</item>
<item>#6367A9</item>
<item>#A05837</item>
<item>#6B002C</item>
<item>#772600</item>
<item>#D790FF</item>
<item>#9B9700</item>
<item>#549E79</item>
<item>#FFF69F</item>
<item>#201625</item>
<item>#72418F</item>
<item>#BC23FF</item>
<item>#99ADC0</item>
<item>#3A2465</item>
<item>#922329</item>
<item>#5B4534</item>
<item>#FDE8DC</item>
<item>#404E55</item>
<item>#0089A3</item>
<item>#CB7E98</item>
<item>#A4E804</item>
<item>#324E72</item>
<item>#6A3A4C</item>
<item>#83AB58</item>
<item>#001C1E</item>
<item>#D1F7CE</item>
<item>#004B28</item>
<item>#C8D0F6</item>
<item>#A3A489</item>
<item>#806C66</item>
<item>#222800</item>
<item>#BF5650</item>
<item>#E83000</item>
<item>#66796D</item>
<item>#DA007C</item>
<item>#FF1A59</item>
<item>#8ADBB4</item>
<item>#1E0200</item>
<item>#5B4E51</item>
<item>#C895C5</item>
<item>#320033</item>
<item>#FF6832</item>
<item>#66E1D3</item>
<item>#CFCDAC</item>
<item>#D0AC94</item>
<item>#7ED379</item>
<item>#012C58</item>
</string-array>
</resources>

View File

@ -48,5 +48,24 @@
<string name="terminerLaMesure">Terminer la mesure</string>
<string name="completeMeasureWithoutEveryoneTitle">Terminer la mesure ?</string>
<string name="completeMeasureWithoutEveryone">Voulez-vous vraiment terminer la mesure, bien que %s n\'ai pas de nouvelle entrée ?</string>
<string name="measureSelectorTitle">"Mesure : "</string>
<string name="everybody">Tous</string>
<string name="basis">"Base : "</string>
<string name="drawGraph">Dessiner !</string>
<string name="labBasis">Échantillon du labo</string>
<string name="localBasis">Échantillon local</string>
<string name="lastMeasure">Dernière</string>
<string name="last5Measures">5 dernières</string>
<string name="xlastMeasures">x dernières</string>
<string name="sinceMeasures">depuis le</string>
<string name="everyMeasure">Toutes</string>
<string name="customMeasures">Défini</string>
<string name="cantGraphNoInput">Aucune mesure ou aucun sujet sélectionné.</string>
<string name="subjectNameDesc">Nom du sujet</string>
<string name="sinceWhenDialog">Depuis quelle date voulez vous voir les mesures ?</string>
<string name="measureCountDialogTitle">Selection des mesures</string>
<string name="measureCountDialogMessage">Combien de mesures en arrière faut-il observer ?</string>
<string name="notImplementedYet">Fonctionnalitée pas encore implémentée.</string>
<string name="subjectSelectTitle">Sélection des sujets</string>
<string name="prepareGraphTitle">Préparation du graphique</string>
</resources>

View File

@ -11,6 +11,10 @@
<style name="group_list_newgroup_item_text" parent="TextAppearance.AppCompat.Body1">
<item name="android:textStyle">italic</item>
</style>
<style name="preparegraph_subjects_list_item" parent="TextAppearance.AppCompat.Body1">
<item name="android:textStyle">italic</item>
<item name="sizePercent">60</item>
</style>
<style name="group_list_item_text_selected" parent="group_list_item_text">
<item name="android:textStyle">bold</item>