1
/***************************************************************
3
* Purpose: Chart fragment for OpenMoneyBox Application
4
* Author: Igor Calì (igor.cali0@gmail.com)
6
* Copyright: Igor Calì (igor.cali0@gmail.com)
8
**************************************************************/
10
package com.igisw.openmoneybox;
12
import android.content.Context;
13
import android.graphics.Bitmap;
14
import android.graphics.Color;
15
import android.net.Uri;
16
import android.os.Bundle;
17
import android.support.v4.app.Fragment;
18
import android.view.LayoutInflater;
19
import android.view.View;
20
import android.view.ViewGroup;
22
import com.github.mikephil.charting.charts.LineChart;
23
import com.github.mikephil.charting.charts.PieChart;
24
import com.github.mikephil.charting.components.YAxis;
25
import com.github.mikephil.charting.data.Entry;
26
import com.github.mikephil.charting.data.LineData;
27
import com.github.mikephil.charting.data.LineDataSet;
28
import com.github.mikephil.charting.data.PieData;
29
import com.github.mikephil.charting.data.PieDataSet;
30
import com.github.mikephil.charting.data.PieEntry;
31
import com.github.mikephil.charting.highlight.Highlight;
32
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
35
import java.io.FileNotFoundException;
36
import java.io.FileOutputStream;
37
import java.io.IOException;
38
import java.io.OutputStream;
39
import java.text.NumberFormat;
40
import java.text.ParseException;
41
import java.util.ArrayList;
42
import java.util.Calendar;
43
import java.util.GregorianCalendar;
44
import java.util.List;
45
import java.util.Locale;
49
* A simple {@link Fragment} subclass.
50
* Activities that contain this fragment must implement the
51
* {@link ChartFragment.OnFragmentInteractionListener} interface
52
* to handle interaction events.
53
* Use the {@link ChartFragment#newInstance} factory method to
54
* create an instance of this fragment.
56
public class ChartFragment extends Fragment {
57
// TODO: Rename parameter arguments, choose names that match
58
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
59
private static final String ARG_PARAM1 = "param1";
60
private static final String ARG_PARAM2 = "param2";
63
private OnFragmentInteractionListener mListener;
65
private mainactivity activity;
68
public ChartFragment() {
69
// Required empty public constructor
73
* Use this factory method to create a new instance of
74
* this fragment using the provided parameters.
76
* @param param1 Parameter 1.
77
* @param param2 Parameter 2.
78
* @return A new instance of fragment ChartFragment.
80
// TODO: Rename and change types and number of parameters
81
public static ChartFragment newInstance(String param1, String param2) {
82
ChartFragment fragment = new ChartFragment();
83
Bundle args = new Bundle();
84
args.putString(ARG_PARAM1, param1);
85
args.putString(ARG_PARAM2, param2);
86
fragment.setArguments(args);
91
public void onCreate(Bundle savedInstanceState) {
92
super.onCreate(savedInstanceState);
93
if (getArguments() != null) {
94
String mParam1 = getArguments().getString(ARG_PARAM1);
95
String mParam2 = getArguments().getString(ARG_PARAM2);
100
public View onCreateView(LayoutInflater inflater, ViewGroup container,
101
Bundle savedInstanceState) {
102
activity = (mainactivity) getActivity();
104
// Inflate the layout for this fragment
105
view = inflater.inflate(R.layout.fragment_chart, container, false);
113
// TODO: Rename method, update argument and hook method into UI event
114
public void onButtonPressed(Uri uri) {
115
if (mListener != null) {
116
mListener.onFragmentInteraction(uri);
122
public void onAttach(Context context) {
123
super.onAttach(context);
124
if (context instanceof OnFragmentInteractionListener) {
125
mListener = (OnFragmentInteractionListener) context;
127
throw new RuntimeException(context.toString()
128
+ " must implement OnFragmentInteractionListener");
133
public void onDetach() {
139
* This interface must be implemented by activities that contain this
140
* fragment to allow an interaction in this fragment to be communicated
141
* to the activity and potentially other fragments contained in that
144
* See the Android Training lesson <a href=
145
* "http://developer.android.com/training/basics/fragments/communicating.html"
146
* >Communicating with Other Fragments</a> for more information.
148
public interface OnFragmentInteractionListener {
149
// TODO: Update argument type and name
150
void onFragmentInteraction(Uri uri);
153
private void paintChart(){
155
boolean default_is_small = false;
157
double percent, sum_small_funds = 0;
160
// Fund Chart construction
161
List<PieEntry> pie_entries = new ArrayList<>();
162
PieChart FundPlot = view.findViewById(R.id.fund_graph);
164
//FundPlot.removeSlices();
165
int inserted_entries = 0;
166
int default_entry = -1;
168
for(i = 0; i < activity.Data.NFun; i++){
169
percent = activity.Data.Funds.get(i).Value / activity.Data.GetTot(omb31core.TTypeVal.tvFou) * 100;
171
pie_entries.add(new PieEntry((float) activity.Data.Funds.get(i).Value, activity.Data.Funds.get(i).Name));
173
if(activity.Data.Funds.get(i).Name.compareToIgnoreCase(activity.Data.FileData.DefFund) == 0)
174
default_entry = inserted_entries - 1;
177
sum_small_funds += activity.Data.Funds.get(i).Value;
178
if(activity.Data.Funds.get(i).Name.compareToIgnoreCase(activity.Data.FileData.DefFund) == 0) default_is_small = true;
181
if(sum_small_funds > 0){
182
pie_entries.add(new PieEntry((float) sum_small_funds, getResources().getString(R.string.fund_others)));
184
if(default_is_small)default_entry = inserted_entries - 1;
186
PieDataSet set = new PieDataSet(pie_entries, getResources().getString(R.string.fund_chart));
188
set.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);
189
set.setValueLinePart1OffsetPercentage(100.f);
190
set.setValueLinePart1Length(0.8f);
191
set.setValueLinePart2Length(0.8f);
193
for(i = 1; i < 7; i++){
213
if(i == 1) set.setColor(Color.parseColor(color));
214
else set.addColor(Color.parseColor(color));
217
PieData data = new PieData(set);
218
FundPlot.setData(data);
219
FundPlot.getDescription().setEnabled(false);
220
FundPlot.setEntryLabelColor(Color.parseColor("#000000"));
221
FundPlot.setEntryLabelTextSize(7f);
223
// Highlight default fund
224
Highlight h = new Highlight((float) default_entry, 0, 0); // dataset index for piechart is always 0
225
FundPlot.highlightValues(new Highlight[] { h });
226
FundPlot.setDrawHoleEnabled(false);
227
FundPlot.invalidate(); // refresh
229
// Trend chart construction
230
GregorianCalendar month = activity.Data.Day;
231
GregorianCalendar lastday = month;
232
month.set(Calendar.MONTH, (int) activity.Data.FileData.Month);
233
int number_of_days = month.getActualMaximum(Calendar.DAY_OF_MONTH);
234
List<Entry> trendvalues = new ArrayList<>();
235
double LastValue = 0 /*, MinValue = 0, MaxValue = 0 */;
238
NumberFormat nf = NumberFormat.getInstance(Locale.getDefault());
241
for(i = 0; i < activity.Data.NLin; i++){
242
if(activity.Data.isDate(i)){
243
lastday = activity.Data.Lines.get(i).Date;
245
// Robustness code to handle localized or unlocalized strings
246
value = activity.Data.Lines.get(i).Value;
247
if(value.contains(".")) LastValue = Double.parseDouble(value);
250
LastValue = nf.parse(value).doubleValue();
251
} catch (ParseException e) {
252
// TODO Auto-generated catch block
256
Entry day_entry = new Entry((float) lastday.getTimeInMillis(), (float) LastValue);
257
trendvalues.add(day_entry);
260
LineChart TrendPlot = view.findViewById(R.id.trend_graph);
261
LineDataSet setComp1 = new LineDataSet(trendvalues, getResources().getString(R.string.trend_chart));
262
setComp1.setAxisDependency(YAxis.AxisDependency.LEFT);
263
setComp1.setColor(Color.parseColor("#000000"));
264
// use the interface ILineDataSet
265
List<ILineDataSet> dataSets = new ArrayList<>();
266
dataSets.add(setComp1);
268
if(! activity.Data.FileData.ReadOnly){
270
double currenttotal = activity.Data.GetTot(omb31core.TTypeVal.tvFou);
271
month.set(Calendar.DAY_OF_MONTH, number_of_days);
272
List<Entry> trendtrendvalues = new ArrayList<>();
273
trendtrendvalues.add(new Entry((float) lastday.getTimeInMillis(), (float) LastValue));
274
trendtrendvalues.add(new Entry((float) month.getTimeInMillis(), (float) currenttotal));
275
LineDataSet setComp2 = new LineDataSet(trendtrendvalues, getResources().getString(R.string.trend_last));
276
setComp2.setAxisDependency(YAxis.AxisDependency.LEFT);
277
dataSets.add(setComp2);
279
if(LastValue == currenttotal) color = "#FFFF00";
280
else if(LastValue < currenttotal) color = "#006400";
281
else color = "#FF0000";
282
setComp2.setColor(Color.parseColor(color));
285
LineData trenddata = new LineData(dataSets);
287
TrendPlot.getXAxis().setValueFormatter(new DateAxisValueFormatter(null));
289
TrendPlot.setData(trenddata);
290
TrendPlot.getDescription().setEnabled(false);
291
TrendPlot.invalidate(); // refresh
295
public void saveChart(int id, File filename){
296
View plot = view.findViewById(id);
297
plot.setDrawingCacheEnabled (true);
298
plot.buildDrawingCache(true);
299
Bitmap b = Bitmap.createBitmap(plot.getDrawingCache());
300
OutputStream os = null;
302
os = new FileOutputStream(filename);
303
} catch (FileNotFoundException e) {
304
// TODO Auto-generated catch block
307
b.compress(Bitmap.CompressFormat.PNG, 100, os);
308
plot.destroyDrawingCache();
311
} catch (IOException e) {
312
// TODO Auto-generated catch block