Java tutorial
/* * Calendula - An assistant for personal medication management. * Copyright (C) 2016 CITIUS - USC * * Calendula is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software. If not, see <http://www.gnu.org/licenses/>. */ package es.usc.citius.servando.calendula.activities; import android.app.AlertDialog; import android.app.ProgressDialog; import android.content.DialogInterface; import android.graphics.Color; import android.graphics.Paint; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Bundle; import android.support.design.widget.AppBarLayout; import android.support.design.widget.CollapsingToolbarLayout; import android.support.v4.app.FragmentTransaction; import android.support.v4.util.Pair; import android.support.v4.widget.NestedScrollView; import android.text.Spannable; import android.text.SpannableString; import android.text.TextUtils; import android.text.style.ForegroundColorSpan; import android.text.style.ImageSpan; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; import com.mikepenz.community_material_typeface_library.CommunityMaterial; import com.mikepenz.iconics.IconicsDrawable; import com.roomorama.caldroid.CaldroidFragment; import com.roomorama.caldroid.CaldroidGridAdapter; import com.roomorama.caldroid.CaldroidListener; import org.joda.time.DateTime; import org.joda.time.LocalDate; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.List; import es.usc.citius.servando.calendula.CalendulaActivity; import es.usc.citius.servando.calendula.R; import es.usc.citius.servando.calendula.database.DB; import es.usc.citius.servando.calendula.persistence.Medicine; import es.usc.citius.servando.calendula.persistence.Patient; import es.usc.citius.servando.calendula.persistence.PickupInfo; import es.usc.citius.servando.calendula.scheduling.PickupReminderMgr; import es.usc.citius.servando.calendula.util.AvatarMgr; import es.usc.citius.servando.calendula.util.PickupUtils; public class CalendarActivity extends CalendulaActivity { public static final int ACTION_SHOW_REMINDERS = 1; private static DateFormat dtf2 = new SimpleDateFormat("dd/MMM"); private Pair<LocalDate, List<PickupInfo>> bestDay; static PickupUtils pickupUtils; DateTime from; DateTime to; String df; Patient patient; Patient selectedPatient; int selectedPatientIdx = 0; long selectedPatientId; List<Patient> pats; Date selectedDate = null; CharSequence bestDayText; View bottomSheet; TextView title; AppBarLayout appBarLayout; CollapsingToolbarLayout toolbarLayout; TextView subtitle; ImageView avatar; CaldroidFragment caldroidFragment; View topBg; NestedScrollView nestedScrollView; View titleCollapsedContainer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_calendar); pats = DB.patients().findAll(); patient = DB.patients().getActive(this); setupStatusBar(Color.TRANSPARENT); setupToolbar("", Color.TRANSPARENT, Color.WHITE); toolbar.setTitleTextColor(Color.WHITE); appBarLayout = (AppBarLayout) findViewById(R.id.appbar); toolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar); titleCollapsedContainer = findViewById(R.id.collapsed_title_container); topBg = findViewById(R.id.imageView5); subtitle = (TextView) findViewById(R.id.routine_name); title = (TextView) findViewById(R.id.routine_name_title); avatar = (ImageView) findViewById(R.id.patient_avatar_title); nestedScrollView = (NestedScrollView) findViewById(R.id.nestedScrollView); df = getString(R.string.pickup_date_format); from = DateTime.now().minusMonths(3); to = DateTime.now().plusMonths(3); bottomSheet = findViewById(R.id.pickup_list_container); bottomSheet.setVisibility(View.INVISIBLE); setupPatientSpinner(); onPatientUpdate(); findViewById(R.id.close_pickup_list).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { hideBottomSheet(); } }); checkIntent(); } private void setupPatientSpinner() { String[] names = new String[pats.size() + 1]; names[0] = "Todos"; for (int i = 0; i < pats.size(); i++) { names[i + 1] = pats.get(i).name(); } ArrayAdapter<String> adapter = new ArrayAdapter<>(this, R.layout.toolbar_spinner_item, names); adapter.setDropDownViewResource(R.layout.toolbar_spinner_item); Spinner spinner = (Spinner) findViewById(R.id.toolbar_spinner); spinner.setAdapter(adapter); spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { selectedPatientIdx = i; onPatientUpdate(); } @Override public void onNothingSelected(AdapterView<?> adapterView) { } }); } private void onPatientUpdate() { if (selectedPatientIdx == 0) { topBg.setBackgroundColor(getResources().getColor(R.color.dark_grey_home)); avatar.setImageDrawable(new IconicsDrawable(CalendarActivity.this) .icon(CommunityMaterial.Icon.cmd_account_multiple).color(Color.WHITE).paddingDp(6).sizeDp(48)); } else { int pIndex = selectedPatientIdx - 1; selectedPatient = pats.get(pIndex); topBg.setBackgroundColor(selectedPatient.color()); selectedPatientId = selectedPatient.id(); avatar.setImageResource(AvatarMgr.res(selectedPatient.avatar())); } new UpdatePickupsTask().execute(); } void setupNewCalendar() { caldroidFragment = new CaldroidSampleCustomFragment(); Bundle args = new Bundle(); DateTime now = DateTime.now(); args.putInt(CaldroidFragment.MONTH, now.getMonthOfYear()); args.putInt(CaldroidFragment.YEAR, now.getYear()); args.putBoolean(CaldroidFragment.SHOW_NAVIGATION_ARROWS, false); args.putBoolean(CaldroidFragment.SIX_WEEKS_IN_CALENDAR, false); args.putInt(CaldroidFragment.START_DAY_OF_WEEK, CaldroidFragment.MONDAY); args.putInt(CaldroidFragment.THEME_RESOURCE, R.style.CaldroidDefaultNoGrid); caldroidFragment.setArguments(args); FragmentTransaction t = getSupportFragmentManager().beginTransaction(); t.replace(R.id.calendar, caldroidFragment); t.commit(); final CaldroidListener listener = new CaldroidListener() { @Override public void onSelectDate(Date date, View view) { LocalDate d = LocalDate.fromDateFields(date); onDaySelected(d); if (bestDay != null && bestDay.first != null && bestDay.first.equals(d)) { //Toast.makeText(CalendarActivity.this, "Best day!", Toast.LENGTH_SHORT).show(); AlertDialog.Builder builder = new AlertDialog.Builder(CalendarActivity.this); builder.setTitle(R.string.best_date_recommendation_title).setPositiveButton( getString(R.string.driving_warning_gotit), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); AlertDialog alertDialog = builder.create(); alertDialog.setMessage(bestDayText); alertDialog.show(); } } @Override public void onChangeMonth(int month, int year) { DateTime date = DateTime.now().withYear(year).withMonthOfYear(month); subtitle.setText(date.toString("MMMM YYYY").toUpperCase()); } @Override public void onLongClickDate(Date date, View view) { } @Override public void onCaldroidViewCreated() { caldroidFragment.getView().findViewById(R.id.calendar_title_view).setVisibility(View.GONE); caldroidFragment.getMonthTitleTextView().setVisibility(View.GONE); } }; caldroidFragment.setCaldroidListener(listener); this.bestDay = pickupUtils.getBestDay(); this.bestDayText = getBestDayText(); if (this.bestDay != null && this.bestDay.first != null) { //Toast.makeText(CalendarActivity.this, "Best day: " + bestDay.first.toString("dd/MM/YY"), Toast.LENGTH_SHORT).show(); caldroidFragment.setBackgroundDrawableForDate( new ColorDrawable(getResources().getColor(R.color.android_green_light)), this.bestDay.first.toDate()); } caldroidFragment.refreshView(); } @Override protected void onDestroy() { selectedDate = null; super.onDestroy(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.calendar, menu); IconicsDrawable icon = new IconicsDrawable(this, CommunityMaterial.Icon.cmd_information_outline).sizeDp(48) .paddingDp(6).color(Color.WHITE); menu.getItem(0).setIcon(icon); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_best_day: //onBestDaySelected(); return true; default: return false; } } private void onActivateReminder(final LocalDate best) { AlertDialog alertDialog = new AlertDialog.Builder(this) .setNegativeButton(getString(R.string.cancel), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }).setTitle(R.string.best_date_reminder) .setSingleChoiceItems(getResources().getStringArray(R.array.calendar_pickup_reminder_values), -1, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { PickupReminderMgr.instance().setCheckPickupsAlarm(CalendarActivity.this, best.minusDays(which + 1)); Toast.makeText(CalendarActivity.this, "Recordatorio activado!", Toast.LENGTH_SHORT) .show(); dialog.dismiss(); } }) .create(); alertDialog.show(); } public CharSequence addPickupList(CharSequence msg, List<PickupInfo> pks) { Paint textPaint = new Paint(); //obviously, we have to set textSize into Paint object textPaint.setTextSize(getResources().getDimensionPixelOffset(R.dimen.medium_font_size)); Paint.FontMetricsInt fontMetrics = textPaint.getFontMetricsInt(); for (PickupInfo p : pks) { Patient patient = pickupUtils.getPatient(p); int color = patient.color(); String str = " " + p.medicine().name() + " (" + dtf2.format(p.from().toDate()) + " - " + dtf2.format(p.to().toDate()) + ")\n"; Spannable text = new SpannableString(str); text.setSpan(new ForegroundColorSpan(color), 0, str.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); Drawable d = getResources().getDrawable(AvatarMgr.res(patient.avatar())); d.setBounds(0, 0, fontMetrics.bottom, fontMetrics.bottom); ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE); text.setSpan(span, 0, 5, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); msg = TextUtils.concat(msg, text); } return msg; } private void checkIntent() { int action = getIntent().getIntExtra("action", -1); if (action == ACTION_SHOW_REMINDERS) { //onBestDaySelected(); } } private boolean onDaySelected(LocalDate date) { selectedDate = date.toDateTimeAtStartOfDay().toDate(); return showPickupsInfo(date); } private boolean showPickupsInfo(final LocalDate date) { final List<PickupInfo> from = DB.pickups().findByFrom(date, true); if (!from.isEmpty()) { TextView title = ((TextView) bottomSheet.findViewById(R.id.bottom_sheet_title)); LayoutInflater i = getLayoutInflater(); LinearLayout list = (LinearLayout) findViewById(R.id.pickup_list); list.removeAllViews(); for (final PickupInfo p : from) { Medicine m = DB.medicines().findById(p.medicine().getId()); Patient pat = DB.patients().findById(m.patient().id()); if (selectedPatientIdx == 0 || pat.id() == selectedPatientId) { View v = i.inflate(R.layout.calendar_pickup_list_item, null); TextView tv1 = ((TextView) v.findViewById(R.id.textView)); TextView tv2 = ((TextView) v.findViewById(R.id.textView2)); ImageView avatar = ((ImageView) v.findViewById(R.id.avatar)); String interval = getResources().getString(R.string.pickup_interval, p.to().toString(df)); if (p.taken()) { interval += " "; tv1.setAlpha(0.5f); } else { tv1.setAlpha(1f); tv2.setAlpha(1f); } tv1.setText(p.medicine().name()); tv2.setText(interval); avatar.setImageResource(AvatarMgr.res(pat.avatar())); tv1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { p.taken(!p.taken()); DB.pickups().save(p); showPickupsInfo(date); } }); list.addView(v); } } nestedScrollView.scrollBy(0, bottomSheet.getHeight()); showBottomSheet(); int total = list.getChildCount(); title.setText( total + " " + getResources().getString(R.string.title_pickups_bottom_sheet, date.toString(df))); appBarLayout.setExpanded(false, true); return true; } return false; } public void showBottomSheet() { bottomSheet.setVisibility(View.VISIBLE); } public void hideBottomSheet() { LinearLayout list = (LinearLayout) findViewById(R.id.pickup_list); list.removeAllViews(); appBarLayout.setExpanded(true, true); bottomSheet.setVisibility(View.INVISIBLE); } @Override public void onBackPressed() { if (bottomSheet.getVisibility() == View.VISIBLE) { hideBottomSheet(); } else { super.onBackPressed(); } } public CharSequence getBestDayText() { final List<PickupInfo> urgent = pickupUtils.urgentMeds(); Pair<LocalDate, List<PickupInfo>> best = pickupUtils.getBestDay(); final List<PickupInfo> next = (best == null || best.first == null) ? new ArrayList<PickupInfo>() : best.second; CharSequence msg = new SpannableString("No hai medicinas que recoger"); LocalDate today = LocalDate.now(); // there are not urgent meds, but there are others to pickup if (urgent.isEmpty() && best != null) { // Log.d("Calendar", "Urgent: " + urgent.size()); // Log.d("Calendar", "Next: " + next.size()); Log.d("Calendar", "there are not urgent meds, but there are others to pickup"); if (next.size() > 1) { msg = new SpannableString(getString(R.string.best_single_day_messge, best.first.toString(getString(R.string.best_date_format)), next.size()) + "\n\n"); } else { msg = new SpannableString(getString(R.string.best_single_day_messge_one_med, best.first.toString(getString(R.string.best_date_format))) + "\n\n"); } msg = addPickupList(msg, next); } // there are urgent meds Log.d("Calendar", "there are urgent meds"); if (!urgent.isEmpty()) { // and others Log.d("Calendar", "and others"); if (best != null) { String bestStr = best.equals(LocalDate.now().plusDays(1)) ? getString(R.string.calendar_date_tomorrow) : best.first.toString(getString(R.string.best_date_format)); // and the others date is near Log.d("Calendar", "and the others date is near"); if (today.plusDays(3).isAfter(best.first)) { List<PickupInfo> all = new ArrayList<>(); all.addAll(urgent); all.addAll(next); msg = new SpannableString( getString(R.string.best_single_day_messge, bestStr, all.size()) + "\n\n"); msg = addPickupList(msg, all); } // and the others date is not near else { Log.d("Calendar", "and the others date is not near"); msg = addPickupList(new SpannableString(getString(R.string.pending_meds_msg) + "\n\n"), urgent); msg = TextUtils.concat(msg, new SpannableString("\n")); if (next.size() > 1) { Log.d("Calendar", " size > 1"); msg = TextUtils.concat(msg, getString(R.string.best_single_day_messge_after_pending, bestStr, next.size()) + "\n\n"); } else { Log.d("Calendar", " size <= 1"); msg = TextUtils.concat(msg, getString(R.string.best_single_day_messge_after_pending_one_med, bestStr) + "\n\n"); } msg = addPickupList(msg, next); } } else { Log.d("Calendar", " there are only urgent meds"); // there are only urgent meds msg = addPickupList(getString(R.string.pending_meds_msg) + "\n\n", urgent); } } Log.d("BEST_DAY", msg.toString()); return msg; } public static class CaldroidSampleCustomFragment extends CaldroidFragment { @Override public CaldroidGridAdapter getNewDatesGridAdapter(int month, int year) { return new CaldroidSampleCustomAdapter(getActivity(), month, year, getCaldroidData(), extraData, pickupUtils); } } public class UpdatePickupsTask extends AsyncTask<Void, Void, Void> { ProgressDialog dialog; @Override protected Void doInBackground(Void... params) { pickupUtils = new PickupUtils( selectedPatientIdx == 0 ? DB.pickups().findAll() : DB.pickups().findByPatient(selectedPatient)); return null; } @Override protected void onPreExecute() { super.onPreExecute(); dialog = new ProgressDialog(CalendarActivity.this); dialog.setIndeterminate(true); dialog.setMessage("Actualizando calendario..."); dialog.show(); } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); if (dialog.isShowing()) { dialog.dismiss(); } setupNewCalendar(); } } }