Java tutorial
/** * RxDroid - A Medication Reminder * Copyright (C) 2011-2013 Joseph Lehner <joseph.c.lehner@gmail.com> * * * RxDroid 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. * * RxDroid 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 RxDroid. If not, see <http://www.gnu.org/licenses/>. * * */ package at.jclehner.rxdroid; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Locale; import android.annotation.TargetApi; import android.app.AlertDialog; import android.app.DatePickerDialog.OnDateSetListener; import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.os.Build; import android.os.Bundle; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.text.SpannableString; import android.text.TextUtils; import android.text.format.DateFormat; import android.text.style.RelativeSizeSpan; import android.text.style.UnderlineSpan; import android.util.DisplayMetrics; import android.util.Log; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.view.ViewStub; import android.widget.DatePicker; import android.widget.TextView; import android.widget.Toast; import at.jclehner.rxdroid.Fraction.MutableFraction; import at.jclehner.rxdroid.InfiniteViewPagerAdapter.ViewFactory; import at.jclehner.rxdroid.NotificationReceiver.OnDoseTimeChangeListener; import at.jclehner.rxdroid.Settings.Defaults; import at.jclehner.rxdroid.Settings.DoseTimeInfo; import at.jclehner.rxdroid.Settings.Keys; import at.jclehner.rxdroid.Settings.OnceIds; import at.jclehner.rxdroid.db.Database; import at.jclehner.rxdroid.db.DoseEvent; import at.jclehner.rxdroid.db.Drug; import at.jclehner.rxdroid.db.Entries; import at.jclehner.rxdroid.db.Entry; import at.jclehner.rxdroid.db.Patient; import at.jclehner.rxdroid.db.Schedule; import at.jclehner.rxdroid.ui.DrugOverviewAdapter; import at.jclehner.rxdroid.util.CollectionUtils; import at.jclehner.rxdroid.util.Components; import at.jclehner.rxdroid.util.DateTime; import at.jclehner.rxdroid.util.ShowcaseViews; import at.jclehner.rxdroid.util.Util; import at.jclehner.rxdroid.widget.AutoDragSortListView; import at.jclehner.rxdroid.widget.DrugSupplyMonitor; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuItem; import com.github.espiandev.showcaseview.ShowcaseView; import com.github.espiandev.showcaseview.ShowcaseView.OnShowcaseEventListener; import com.github.espiandev.showcaseview.ShowcaseViewBuilder2; import com.mobeta.android.dslv.DragSortListView; public class DrugListActivity extends SherlockFragmentActivity implements OnLongClickListener, OnDateSetListener, OnSharedPreferenceChangeListener, ViewFactory { private static final String TAG = DrugListActivity.class.getSimpleName(); private static final boolean LOGV = false; private static final boolean DEBUG_DATE_MISMATCH = true; private static final int CMENU_TAKE_DOSE = 1; private static final int CMENU_REMOVE_DOSE = 0; private static final int CMENU_EDIT_DRUG = 2; private static final int CMENU_IGNORE_DOSE = 4; private static final int CMENU_DUMP = 6; private static final int DIALOG_INFO = 0; public static final String EXTRA_DATE = "date"; public static final String EXTRA_STARTED_FROM_NOTIFICATION = "started_from_notification"; public static final int TAG_DRUG_ID = R.id.tag_drug_id; private ViewPager mPager; //private TextView mTextDate; private Date mOriginalDate; private Date mCurrentDate; private boolean mShowingAll = false; private int mCurrentPatientId = Patient.DEFAULT_PATIENT_ID; private int mSwipeDirection = 0; private int mLastPage = -1; private boolean mIsShowing = false; private final ShowcaseViews mShowcaseQueue = new ShowcaseViews(); @TargetApi(11) @Override protected void onCreate(Bundle savedInstanceState) { Components.onCreateActivity(this, 0); setContentView(R.layout.drug_list); mPager = (ViewPager) findViewById(R.id.drug_list_pager); /*mTextDate = (TextView) findViewById(R.id.text_date); mTextDate.setOnLongClickListener(mDateClickListener); mTextDate.setOnClickListener(mDateClickListener); mTextDate.setVisibility(View.GONE);*/ //mPager.setOnPageChangeListener(mPageListener); mPager.setOffscreenPageLimit(1); //startNotificationService(); NotificationReceiver.rescheduleAlarmsAndUpdateNotification(true); Database.registerEventListener(mDatabaseListener); Settings.registerOnChangeListener(this); super.onCreate(savedInstanceState); } @Override protected void onResume() { super.onResume(); Components.onResumeActivity(this, 0); mIsShowing = true; final Intent intent = getIntent(); Date date = null; if (intent != null) date = (Date) intent.getSerializableExtra(EXTRA_DATE); if (date == null) date = Settings.getActiveDate(); setDate(date, PAGER_INIT); NotificationReceiver.registerOnDoseTimeChangeListener(mDoseTimeListener); if (Version.BETA) showInfoDialog(OnceIds.BETA_VERSION, R.string._msg_beta_version, getString(R.string.app_name)); if (true) { final String isoLang = Locale.getDefault().getLanguage(); if (!TextUtils.isEmpty(isoLang) && !CollectionUtils.contains(Version.LANGUAGES, isoLang)) { final String language = Locale.getDefault().getDisplayLanguage(Locale.US); showInfoDialog("missing_translation_" + isoLang, R.string._msg_no_translation, language); } } mShowcaseQueue.show(); } @Override protected void onPause() { super.onPause(); mIsShowing = false; Components.onPauseActivity(this, 0); NotificationReceiver.unregisterOnDoseTimeChangeListener(mDoseTimeListener); } @Override protected void onStop() { super.onStop(); mPager.removeAllViews(); Database.unregisterEventListener(mDatabaseListener); } @Override public boolean onTrackballEvent(MotionEvent event) { // Using the trackball to navigate the ViewPager is very likely to cause a // problem with Activity date / DoseView date mismatch. Until this is fixed, // we eat all trackball events. return true; } @Override public boolean onCreateOptionsMenu(Menu menu) { final int menuResId; if (Settings.getBoolean(Keys.COMPACT_ACTION_BAR, Defaults.COMPACT_ACTION_BAR)) menuResId = R.menu.activity_drug_list_compact; else { if (!BuildConfig.DEBUG) menuResId = R.id.menu_default_drug_list_activity; else menuResId = R.menu.activity_drug_list_extended; } new MenuInflater(this).inflate(menuResId, menu); return true; } @Override public boolean onPrepareOptionsMenu(Menu menu) { final int titleResId = isShowingCurrentDate() ? R.string._title_go_to_date : R.string._title_today; menu.findItem(R.id.menuitem_date).setTitle(titleResId); menu.findItem(R.id.menuitem_toggle_filtering) .setTitle(mShowingAll ? R.string._title_filter : R.string._title_show_all); menu.findItem(R.id.menuitem_take_all_pending).setEnabled(isShowingCurrentDate()); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menuitem_date: { if (isShowingCurrentDate()) mDateClickListener.onLongClick(null); else mDateClickListener.onClick(null); return true; } case R.id.menuitem_patient: { } case R.id.menuitem_add: { Intent intent = new Intent(Intent.ACTION_INSERT); intent.setClass(this, DrugEditActivity.class); startActivity(intent); return true; } case R.id.menuitem_preferences: { Intent intent = new Intent(); intent.setClass(this, PreferencesActivity.class); startActivity(intent); return true; } case R.id.menuitem_toggle_filtering: { mShowingAll = !mShowingAll; invalidateViewPager(); return true; } case R.id.menuitem_take_all_pending: { final List<Drug> drugs = Entries.getAllDrugs(mCurrentPatientId); final DoseTimeInfo dtInfo = Settings.getDoseTimeInfo(); final int activeDoseTime = dtInfo.activeDoseTime(); final Date activeDate = dtInfo.activeDate(); int toastResId = R.string._toast_no_due_doses; int toastLength = Toast.LENGTH_SHORT; if (activeDoseTime != Schedule.TIME_INVALID) { int taken = 0, skipped = 0; for (Drug drug : drugs) { if (!drug.isActive()) continue; if (!Entries.findDoseEvents(drug, activeDate, activeDoseTime).isEmpty()) continue; final Fraction dose = drug.getDose(activeDoseTime, activeDate); if (!dose.isZero()) { final Fraction currentSupply = drug.getCurrentSupply(); if (!currentSupply.isZero()) { final Fraction newSupply = currentSupply.minus(dose); if (newSupply.isNegative()) { ++skipped; continue; } else { drug.setCurrentSupply(newSupply); Database.update(drug); } } Database.create(new DoseEvent(drug, activeDate, activeDoseTime, dose)); ++taken; } } if (skipped != 0) { toastResId = R.string._toast_some_due_doses_skipped; toastLength = Toast.LENGTH_LONG; } else if (taken != 0) toastResId = R.string._toast_all_due_doses_taken; } Toast.makeText(this, toastResId, toastLength).show(); } } return super.onOptionsItemSelected(item); } @Override public boolean onContextItemSelected(android.view.MenuItem item) { // TODO Auto-generated method stub return super.onContextItemSelected(item); } @Override public void onCreateContextMenu(ContextMenu menu, final View v, ContextMenuInfo menuInfo) { final DoseView doseView = (DoseView) v; if (toastIfPastMaxHistoryAge(doseView.getDate())) return; final Drug drug = doseView.getDrug(); final int doseTime = doseView.getDoseTime(); // menu.setHeaderIcon(android.R.drawable.ic_menu_agenda); menu.setHeaderTitle(drug.getName()); // //////////////////////////////////////////////// // //////////////////////////////////////////////// final boolean wasDoseTaken = doseView.wasDoseTaken(); if (wasDoseTaken) { menu.add(0, CMENU_REMOVE_DOSE, 0, R.string._title_mark_not_taken) .setOnMenuItemClickListener(new OnContextMenuItemClickListener() { @Override public boolean onMenuItemClick(android.view.MenuItem item) { MutableFraction dose = new MutableFraction(); for (DoseEvent intake : Entries.findDoseEvents(drug, mCurrentDate, doseTime)) { dose.add(intake.getDose()); Database.delete(intake); } drug.setCurrentSupply(drug.getCurrentSupply().plus(dose)); Database.update(drug); return true; } }); } else { menu.add(0, CMENU_IGNORE_DOSE, 0, R.string._title_ignore_dose) .setOnMenuItemClickListener(new OnContextMenuItemClickListener() { @Override public boolean onMenuItemClick(android.view.MenuItem item) { Database.create(new DoseEvent(drug, doseView.getDate(), doseTime)); return true; } }); } menu.add(0, CMENU_TAKE_DOSE, 0, R.string._title_mark_taken) .setOnMenuItemClickListener(new OnContextMenuItemClickListener() { @Override public boolean onMenuItemClick(android.view.MenuItem item) { showDoseDialog(drug, doseView.getDate(), doseTime, true); return true; } }); final Intent editIntent = new Intent(this, DrugEditActivity.class); editIntent.setAction(Intent.ACTION_EDIT); editIntent.putExtra(DrugEditActivity.EXTRA_DRUG_ID, drug.getId()); menu.add(0, CMENU_EDIT_DRUG, 0, R.string._title_edit_drug).setIntent(editIntent); if (BuildConfig.DEBUG) { menu.add(0, CMENU_DUMP, 0, "Dump").setOnMenuItemClickListener(new OnContextMenuItemClickListener() { @Override public boolean onMenuItemClick(android.view.MenuItem item) { Util.dumpObjectMembers(TAG, Log.VERBOSE, drug, drug.getName()); return true; } }); } } public void onDrugNameClick(View view) { Intent intent = new Intent(Intent.ACTION_EDIT); intent.setClass(this, DrugEditActivity.class); Drug drug = Drug.get((Integer) view.getTag(TAG_DRUG_ID)); intent.putExtra(DrugEditActivity.EXTRA_DRUG_ID, drug.getId()); intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); //startActivityForResult(intent, 0); startActivity(intent); } @Override public boolean onLongClick(View view) { if (view.getId() == R.id.text_date) { } return false; } @Override public void onDateSet(DatePicker view, int year, int month, int day) { setDate(DateTime.date(year, month, day), PAGER_INIT); } @Override public void onSharedPreferenceChanged(SharedPreferences preferences, String key) { if (Settings.Keys.THEME_IS_DARK.equals(key)) finish(); // TODO fix this naughty hack else if (mIsShowing) { // TODO also exclude all other non-important keys if (!Keys.LAST_MSG_HASH.equals(key)) invalidateViewPager(); } } @Override public View makeView(int offset) { if (offset <= -(InfiniteViewPagerAdapter.MAX / 2)) { if (LOGV) Log.d(TAG, "makeView: returning stub for offset=" + offset); return new ViewStub(this); } final View v = getLayoutInflater().inflate(R.layout.drug_list_fragment, null); final AutoDragSortListView listView = (AutoDragSortListView) v.findViewById(android.R.id.list); final TextView emptyView = (TextView) v.findViewById(android.R.id.empty); final Date date = DateTime.add(mOriginalDate, Calendar.DAY_OF_MONTH, offset); if (LOGV) Log.d(TAG, "makeView: date=" + DateTime.toDateString(date)); final List<Drug> drugs = Entries.getAllDrugs(mCurrentPatientId); Collections.sort(drugs, new DrugComparator()); updateListAdapter(listView, date, drugs); final String text; if (drugs.isEmpty()) { if (Settings.getBoolean(Keys.COMPACT_ACTION_BAR, Defaults.COMPACT_ACTION_BAR)) { Log.d(TAG, "COMPACT_ACTION_BAR"); final boolean hasHardwareMenuKey; if (Version.SDK_IS_PRE_HONEYCOMB) hasHardwareMenuKey = true; else { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) { // For Honeycomb, there appears to be no way to find out. As it // targets tablets only, we will assume that none of these have a // hardware menu key... hasHardwareMenuKey = false; } else hasHardwareMenuKey = ViewConfiguration.get(this).hasPermanentMenuKey(); } final StringBuilder sb = new StringBuilder( getString(R.string._msg_no_drugs_compact_ab, getString(R.string._title_add))); if (hasHardwareMenuKey) sb.append(" " + getString(R.string._help_msg_menu_hardware)); else sb.append(" " + getString(R.string._help_msg_menu_ab_overflow)); text = sb.toString(); } else { Log.d(TAG, "EXTENDED_ACTION_BAR"); text = getString(R.string._msg_no_drugs_extended_ab, getString(R.string._title_add)); } } else text = getString(R.string._msg_no_doses_on_this_day, getString(R.string._title_add)); emptyView.setText(text); listView.setEmptyView(emptyView); listView.setDragHandleId(R.id.drug_icon); return v; } public void onDoseViewClick(View view) { final DoseView doseView = (DoseView) view; showDoseDialog(doseView.getDrug(), doseView.getDate(), doseView.getDoseTime(), false); } public void onMissedIndicatorClicked(View view) { final Drug drug = (Drug) view.getTag(); final Calendar cal = DateTime.calendarFromDate(mCurrentDate); do { cal.add(Calendar.DAY_OF_MONTH, -1); } while (!drug.hasDoseOnDate(cal.getTime())); Toast.makeText(getApplicationContext(), R.string._toast_drug_notification_icon, Toast.LENGTH_SHORT).show(); setDate(cal.getTime(), PAGER_INIT | PAGER_SCROLL); } public void onSupplyMonitorClick(View view) { final Drug drug = ((DrugSupplyMonitor) view).getDrug(); if (drug == null) return; final Date today = DateTime.today(); final int daysLeft = Entries.getSupplyDaysLeftForDrug(drug, today); final String dateString = DateTime.toNativeDate(DateTime.add(today, Calendar.DAY_OF_MONTH, daysLeft)); Toast.makeText(this, getString(R.string._toast_low_supplies, dateString), Toast.LENGTH_LONG).show(); } public void onSupplyMonitorLongClick(View view) { final Drug drug = ((DrugSupplyMonitor) view).getDrug(); if (drug == null) return; final DrugSupplyEditFragment dialog = DrugSupplyEditFragment.newInstance(drug); dialog.show(getSupportFragmentManager(), "supply_edit_dialog"); } @SuppressWarnings("deprecation") @Override protected Dialog onCreateDialog(final int id, Bundle args) { if (id == R.id.dose_dialog) return new DoseDialog(this); else if (id == DIALOG_INFO) { final String msg = args.getString("msg"); final String onceId = args.getString("once_id"); final AlertDialog.Builder ab = new AlertDialog.Builder(this); ab.setIcon(android.R.drawable.ic_dialog_info); ab.setTitle(R.string._title_info); ab.setMessage(msg); ab.setCancelable(false); ab.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Log.d(TAG, "onClick: which = " + which); Settings.setDisplayedOnce(onceId); removeDialog(id); } }); return ab.create(); } return super.onCreateDialog(id, args); } @SuppressWarnings("deprecation") @Override protected void onPrepareDialog(int id, Dialog dialog, Bundle args) { if (id == R.id.dose_dialog) { if (!Database.exists(Drug.class, args.getInt(DoseDialog.ARG_DRUG_ID, -1))) { // If the drug currently associated with the dialog is deleted, // setArgs() throws when attempting to restore from the non-existent // drug id. return; } ((DoseDialog) dialog).setArgs(args); } else super.onPrepareDialog(id, dialog, args); } @Override protected void onNewIntent(Intent intent) { setIntent(intent); } private static final int PAGER_SCROLL = 1; private static final int PAGER_INIT = 1 << 1; private void invalidateViewPager() { setDate(mCurrentDate, PAGER_INIT); } @TargetApi(11) private void setDate(Date date, int flags) { if (DEBUG_DATE_MISMATCH) Log.d(TAG, "setDate(" + date + ", " + flags + ")"); if (!mIsShowing) { if (LOGV) Log.v(TAG, "setDate: activity is not showing; ignoring"); return; } if (toastIfPastMaxHistoryAge(date)) return; mCurrentDate = date; getIntent().putExtra(EXTRA_DATE, date); if ((flags & PAGER_INIT) != 0) { mOriginalDate = date; mSwipeDirection = 0; mPager.setOnPageChangeListener(null); mPager.removeAllViews(); final int drugCount = Database.countAll(Drug.class); if (drugCount != 0) { final boolean smoothScroll = (flags & PAGER_SCROLL) != 0; mPager.setAdapter(new InfiniteViewPagerAdapter(this)); mPager.setCurrentItem(InfiniteViewPagerAdapter.CENTER, smoothScroll); mLastPage = InfiniteViewPagerAdapter.CENTER; if (drugCount == 1 && !Settings.wasDisplayedOnce("date_swipe")) { ShowcaseViewBuilder2 svb = new ShowcaseViewBuilder2(this); svb.setText(R.string._help_title_swipe_date, R.string._help_msg_swipe_date); svb.setShotType(ShowcaseView.TYPE_ONE_SHOT); svb.setShowcaseId(0xdeadbeef + 0); svb.setShowcaseItem(ShowcaseView.ITEM_TITLE, 0, this); final DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); final float w = metrics.widthPixels; final float h = metrics.heightPixels; final float y = h * 0.6f; svb.setAnimatedGesture(-100, y, w, y); mShowcaseQueue.add(svb.build()); svb = new ShowcaseViewBuilder2(this); svb.setText(R.string._help_title_edit_drug, R.string._help_msg_edit_drug); svb.setShotType(ShowcaseView.TYPE_ONE_SHOT); svb.setShowcaseId(0xdeadbeef + 1); svb.setShowcaseView(R.id.drug_name, this); mShowcaseQueue.add(svb.build()); } else if (drugCount >= 2 && !Settings.wasDisplayedOnce(Settings.OnceIds.DRAG_DROP_SORTING)) { ShowcaseViewBuilder2 svb = new ShowcaseViewBuilder2(this); svb.setShowcaseView(R.id.drug_icon, this); svb.setText(R.string._help_title_drag_drop_sort, R.string._msg_drag_drop_sorting); svb.setShotType(ShowcaseView.TYPE_ONE_SHOT); svb.setShowcaseId(0xdeadbeef + 2); svb.setRelativeAnimatedGesture(0, 200); mShowcaseQueue.add(svb.build()); } } else { mPager.setAdapter(new PagerAdapter() { @Override public boolean isViewFromObject(View v, Object o) { return v == (View) o; } @Override public int getCount() { // TODO Auto-generated method stub return 1; } @Override public Object instantiateItem(ViewGroup container, int position) { final View v = makeView(0); Util.detachFromParent(v); container.addView(v); return v; } @Override public void destroyItem(ViewGroup container, int position, Object item) { container.removeView((View) item); } }); mPager.setCurrentItem(0); mLastPage = 0; } mPager.setOnPageChangeListener(mPageListener); } supportInvalidateOptionsMenu(); updateDateString(); } private boolean isShowingCurrentDate() { return DateTime.isToday(mCurrentDate); } private void updateListAdapter(DragSortListView listView, Date date, List<Drug> drugs) { if (listView == null) { Log.w(TAG, "updateListAdapter: listView==null"); return; } if (drugs == null) { drugs = Database.getAll(Drug.class); Collections.sort(drugs); } final DrugOverviewAdapter adapter = new DrugOverviewAdapter(this, drugs, date); adapter.setFilter(mShowingAll ? null : new DrugFilter(date)); listView.setAdapter(adapter); } // // private void startNotificationService() // { // NotificationReceiver.rescheduleAlarmsAndUpdateNotification(false); // Database.registerEventListener(mDatabaseWatcher); // } @TargetApi(11) private void updateDateString() { if (mCurrentDate == null) return; final SpannableString dateString = new SpannableString( DateFormat.getDateFormat(this).format(mCurrentDate.getTime())); if (isShowingCurrentDate()) Util.applyStyle(dateString, new UnderlineSpan()); Util.applyStyle(dateString, new RelativeSizeSpan(0.75f)); getSupportActionBar().setSubtitle(dateString); } private boolean toastIfPastMaxHistoryAge(Date date) { if (Settings.isPastMaxHistoryAge(DateTime.today(), date)) { Toast.makeText(this, R.string._toast_past_max_history_age, Toast.LENGTH_LONG).show(); //mPager.setCurrentItem(mLastPage); //setDate(mDate, PAGER_INIT | PAGER_SCROLL); return true; } return false; } @SuppressWarnings("deprecation") private void showInfoDialog(String onceId, int msgResId, Object... args) { if (Settings.wasDisplayedOnce(onceId)) return; Bundle bundle = new Bundle(); bundle.putString("once_id", onceId); bundle.putString("msg", getString(msgResId, args)); showDialog(DIALOG_INFO, bundle); } @SuppressWarnings("deprecation") private void showDoseDialog(Drug drug, Date date, int doseTime, boolean forceShow) { if (toastIfPastMaxHistoryAge(date)) return; else if (!date.equals(mCurrentDate)) { Log.i(TAG, "DoseView date " + DateTime.toDateString(date) + " differs from Activity date " + DateTime.toDateString(mCurrentDate) + " "); invalidateViewPager(); date = mCurrentDate; if (BuildConfig.DEBUG) Toast.makeText(this, "Invoked workaround!", Toast.LENGTH_SHORT).show(); } final Bundle args = new Bundle(); args.putInt(DoseDialog.ARG_DRUG_ID, drug.getId()); args.putInt(DoseDialog.ARG_DOSE_TIME, doseTime); args.putSerializable(DoseDialog.ARG_DATE, date); args.putBoolean(DoseDialog.ARG_FORCE_SHOW, forceShow); showDialog(R.id.dose_dialog, args); } static class DrugFilter implements CollectionUtils.Filter<Drug> { final boolean mShowSupplyMonitors = Settings.getBoolean(Settings.Keys.SHOW_SUPPLY_MONITORS, false); private Date mFilterDate; public DrugFilter(Date date) { mFilterDate = date; } @Override public boolean matches(Drug drug) { if (mFilterDate == null) return true; if (drug.hasAutoDoseEvents()) { if (Entries.hasLowSupplies(drug)) return true; return mShowSupplyMonitors; } if (!drug.isActive()) return false; if (Entries.countDoseEvents(drug, mFilterDate, null) != 0) return true; if (Entries.hasLowSupplies(drug)) return true; if (DateTime.isToday(mFilterDate) && Entries.hasMissingDosesBeforeDate(drug, mFilterDate)) return true; if (!drug.hasDoseOnDate(mFilterDate)) return false; return true; } } interface OnClickAndLongClickListener extends OnClickListener, OnLongClickListener { }; private final OnClickAndLongClickListener mDateClickListener = new OnClickAndLongClickListener() { @Override public boolean onLongClick(View v) { /*Calendar cal = DateTime.calendarFromDate(mDate); final int year = cal.get(Calendar.YEAR); final int month = cal.get(Calendar.MONTH); final int day = cal.get(Calendar.DAY_OF_MONTH); DatePickerDialog dialog = new DatePickerDialog(DrugListActivity.this, DrugListActivity.this, year, month, day); dialog.setCancelable(true); dialog.show(); return true;*/ DatePickerFragment datePicker = DatePickerFragment.newInstance(mCurrentDate, DrugListActivity.this); datePicker.show(getSupportFragmentManager(), "datePicker"); return true; } @Override public void onClick(View v) { final Date activeDate = Settings.getActiveDate(); setDate(activeDate, PAGER_INIT | PAGER_SCROLL); } }; private final OnPageChangeListener mPageListener = new OnPageChangeListener() { int mPage = InfiniteViewPagerAdapter.CENTER; @Override public void onPageSelected(int page) { if (DEBUG_DATE_MISMATCH) Log.d(TAG, "onPageSelected(" + page + ")"); mPage = page; //final int swipeDirection; if (mLastPage == -1) { mLastPage = InfiniteViewPagerAdapter.CENTER; mSwipeDirection = 0; } else mSwipeDirection = mPage - mLastPage; if (mSwipeDirection != 0) { final Date date = DateTime.add(mCurrentDate, Calendar.DAY_OF_MONTH, mSwipeDirection); setDate(date, 0); //if(LOGV) Log.d(TAG, "onPageSelected: swipe " + (mSwipeDirection < 0 ? "right" : "left")); } //else if(LOGV) Log.d(TAG, "onPageSelected: no swipe"); mLastPage = page; } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } @Override public void onPageScrollStateChanged(int state) { // if(LOGV) // { // final String[] states = { "IDLE", "DRAGGING", "SETTLING" }; // Log.v(TAG, "onPageScrollStateChanged: page=" + mPage); // Log.v(TAG, " state=" + states[state]); // } // // if(state == ViewPager.SCROLL_STATE_IDLE) // { // mSwipeDirection = mLastPage != -1 ? mPage - mLastPage : 0; // // if(LOGV) Log.v(TAG, "onPageScrollStateChanged: mPage=" + mPage + // ", mLastPage=" + mLastPage + ", mSwipeDirection=" + mSwipeDirection); // // if(mSwipeDirection != 0) // { // //final int shiftBy = mSwipeDirection < 0 ? -1 : 1; // //setDate(DateTime.add(mDate, Calendar.DAY_OF_MONTH, shiftBy), 0); // } // // //mLastPage = mPage; // } } }; private final Database.OnChangeListener mDatabaseListener = new Database.EmptyOnChangeListener() { @SuppressWarnings("deprecation") @Override public void onEntryDeleted(Entry entry, int flags) { try { DrugListActivity.this.removeDialog(R.id.dose_dialog); } catch (Exception e) { } if (entry instanceof Drug) invalidateViewPager(); } @Override public void onEntryCreated(Entry entry, int flags) { if (entry instanceof Drug) invalidateViewPager(); else if (entry instanceof DoseEvent) supportInvalidateOptionsMenu(); } }; private final OnDoseTimeChangeListener mDoseTimeListener = new OnDoseTimeChangeListener() { @Override public void onDoseTimeBegin(Date date, int doseTime) { if (!date.equals(mCurrentDate)) setDate(date, PAGER_INIT); } public void onDoseTimeEnd(Date date, int doseTime) { invalidateViewPager(); } }; static class DrugComparator implements Comparator<Drug> { private int mDoseTime; private Date mDate; private boolean mSmartSortEnabled; DrugComparator() { final DoseTimeInfo dtInfo = Settings.getDoseTimeInfo(); mDoseTime = dtInfo.activeDoseTime(); if (mDoseTime != Schedule.TIME_INVALID) mDate = dtInfo.activeDate(); else { mDoseTime = dtInfo.nextDoseTime(); mDate = dtInfo.nextDoseTimeDate(); } mSmartSortEnabled = Settings.getBoolean(Keys.USE_SMART_SORT, false); } @Override public int compare(Drug lhs, Drug rhs) { if (mSmartSortEnabled) { boolean lActive = lhs.isActive(); boolean rActive = rhs.isActive(); if (lActive != rActive) return lActive ? -1 : 1; boolean lHasDose = lhs.hasDoseOnDate(mDate); boolean rHasDose = rhs.hasDoseOnDate(mDate); if (lHasDose != rHasDose) return lHasDose ? -1 : 1; lHasDose = !lhs.getDose(mDoseTime, mDate).isZero(); rHasDose = !rhs.getDose(mDoseTime, mDate).isZero(); if (lHasDose != rHasDose) return lHasDose ? -1 : 1; } return lhs.compareTo(rhs); } } } interface OnContextMenuItemClickListener extends android.view.MenuItem.OnMenuItemClickListener { };