org.voidsink.anewjkuapp.fragment.CalendarFragment.java Source code

Java tutorial

Introduction

Here is the source code for org.voidsink.anewjkuapp.fragment.CalendarFragment.java

Source

/*
 *      ____.____  __.____ ___     _____
 *     |    |    |/ _|    |   \   /  _  \ ______ ______
 *     |    |      < |    |   /  /  /_\  \\____ \\____ \
 * /\__|    |    |  \|    |  /  /    |    \  |_> >  |_> >
 * \________|____|__ \______/   \____|__  /   __/|   __/
 *                  \/                  \/|__|   |__|
 *
 * Copyright (c) 2014-2015 Paul "Marunjar" Pretsch
 *
 * This program 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 program.  If not, see <http://www.gnu.org/licenses/>
 *
 */

package org.voidsink.anewjkuapp.fragment;

import android.accounts.Account;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.UriMatcher;
import android.database.Cursor;
import android.graphics.drawable.LayerDrawable;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.format.DateUtils;
import android.util.Log;
import android.util.SparseIntArray;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;

import org.voidsink.anewjkuapp.R;
import org.voidsink.anewjkuapp.analytics.Analytics;
import org.voidsink.anewjkuapp.base.BaseContentObserver;
import org.voidsink.anewjkuapp.base.BaseFragment;
import org.voidsink.anewjkuapp.base.ContentObserverListener;
import org.voidsink.anewjkuapp.calendar.CalendarContractWrapper;
import org.voidsink.anewjkuapp.calendar.CalendarEventAdapter;
import org.voidsink.anewjkuapp.calendar.CalendarListEvent;
import org.voidsink.anewjkuapp.calendar.CalendarListItem;
import org.voidsink.anewjkuapp.calendar.CalendarUtils;
import org.voidsink.anewjkuapp.update.UpdateService;
import org.voidsink.anewjkuapp.utils.AppUtils;
import org.voidsink.anewjkuapp.utils.Consts;
import org.voidsink.anewjkuapp.utils.UIUtils;
import org.voidsink.sectionedrecycleradapter.SectionedRecyclerViewAdapter;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

public class CalendarFragment extends BaseFragment
        implements ContentObserverListener, LoaderManager.LoaderCallbacks<Cursor> {

    private static final String TAG = CalendarFragment.class.getSimpleName();
    private long now = 0, then = 0;

    private CalendarEventAdapter mAdapter;
    private BaseContentObserver mDataObserver;
    private RecyclerView mRecyclerView;
    private Button mLoadMoreButton;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_calendar, container, false);

        mRecyclerView = (RecyclerView) view.findViewById(R.id.calendar_card_events);

        mLoadMoreButton = (Button) view.findViewById(R.id.calendar_card_load);
        mLoadMoreButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loadMoreData();
            }
        });
        mLoadMoreButton.setClickable(true);

        setButtonLoadText();

        return view;
    }

    private void setButtonLoadText() {
        mLoadMoreButton.setText(getContext().getString(R.string.listview_footer_button,
                SimpleDateFormat.getDateInstance(SimpleDateFormat.MEDIUM).format(then)));
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        if (savedInstanceState != null) {
            now = savedInstanceState.getLong(Consts.ARG_CALENDAR_NOW, now);
            then = savedInstanceState.getLong(Consts.ARG_CALENDAR_THEN, then);

            setButtonLoadText();
        }

        mAdapter = new CalendarEventAdapter(getContext());

        //      mListView.addFooterView(loadMore);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        mRecyclerView.setAdapter(new SectionedRecyclerViewAdapter(mRecyclerView, mAdapter));

        mAdapter.setOnItemClickListener(new CalendarEventAdapter.OnItemClickListener() {

            @Override
            public void onItemClick(View view, int viewType, int position) {
                if (position != RecyclerView.NO_POSITION) {
                    CalendarListItem item = mAdapter.getItem(position);
                    if (item != null) {
                        ((CalendarListEvent) item).showOnMap(getContext());
                    }
                }
            }
        });

        getLoaderManager().initLoader(0, null, this);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // init range
        now = System.currentTimeMillis();
        then = now + 14 * DateUtils.DAY_IN_MILLIS;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        outState.putLong(Consts.ARG_CALENDAR_NOW, now);
        outState.putLong(Consts.ARG_CALENDAR_THEN, then);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);
        inflater.inflate(R.menu.calendar, menu);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            MenuItem menuItem = menu.findItem(R.id.action_cal_goto_today);
            // replace the default top layer drawable of the today icon with a
            // custom drawable that shows the day of the month of today
            LayerDrawable icon = (LayerDrawable) menuItem.getIcon();
            UIUtils.setTodayIcon(icon, getContext(), "");
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
        case R.id.action_refresh_calendar:
            Intent mUpdateService = new Intent(getActivity(), UpdateService.class);
            mUpdateService.putExtra(Consts.ARG_UPDATE_CAL, true);
            getActivity().startService(mUpdateService);

            return true;
        case R.id.action_cal_goto_today:
            mRecyclerView.smoothScrollToPosition(0);
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    private void loadMoreData() {
        if (this.isVisible() && !getLoaderManager().hasRunningLoaders()) {
            now = System.currentTimeMillis(); // if someone changed the time since last click

            // increase in month steps
            Calendar cal = Calendar.getInstance();
            cal.setTimeInMillis(then);

            then += cal.getActualMaximum(Calendar.DAY_OF_MONTH) * DateUtils.DAY_IN_MILLIS;

            // set button text
            setButtonLoadText();

            Analytics.eventLoadMoreEvents(getContext(), then - now);

            loadData();
        }
    }

    private void loadData() {
        if (this.isVisible() && !getLoaderManager().hasRunningLoaders()) {
            getLoaderManager().restartLoader(0, null, this);
        }
    }

    @Override
    public void onStart() {
        super.onStart();

        UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
        uriMatcher.addURI(CalendarContractWrapper.AUTHORITY(),
                CalendarContractWrapper.Events.CONTENT_URI().buildUpon().appendPath("#").build().toString(), 0);

        mDataObserver = new BaseContentObserver(uriMatcher, this);

        // listen to all changes
        getActivity().getContentResolver().registerContentObserver(
                CalendarContractWrapper.Events.CONTENT_URI().buildUpon().appendPath("#").build(), false,
                mDataObserver);
    }

    @Override
    public void onStop() {
        super.onStop();

        getActivity().getContentResolver().unregisterContentObserver(mDataObserver);
        mDataObserver = null;
    }

    @Override
    protected String getScreenName() {
        return Consts.SCREEN_CALENDAR;
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        showProgressIndeterminate();

        Account mAccount = AppUtils.getAccount(getContext());

        String calIDLva = CalendarUtils.getCalIDByName(getContext(), mAccount, CalendarUtils.ARG_CALENDAR_COURSE,
                true);
        String calIDExam = CalendarUtils.getCalIDByName(getContext(), mAccount, CalendarUtils.ARG_CALENDAR_EXAM,
                true);

        if (calIDLva == null || calIDExam == null) {
            Log.w(TAG, "no events loaded, calendars not found");
            return null;
        }

        return new CursorLoader(getContext(), CalendarContractWrapper.Events.CONTENT_URI(),
                CalendarUtils.EVENT_PROJECTION,
                "(" + CalendarContractWrapper.Events.CALENDAR_ID() + " = ? or "
                        + CalendarContractWrapper.Events.CALENDAR_ID() + " = ? ) and "
                        + CalendarContractWrapper.Events.DTEND() + " >= ? and "
                        + CalendarContractWrapper.Events.DTSTART() + " <= ? and "
                        + CalendarContractWrapper.Events.DELETED() + " != 1",
                new String[] { calIDExam, calIDLva, Long.toString(now), Long.toString(then) },
                CalendarContractWrapper.Events.DTSTART() + " ASC");
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
        mAdapter.clear();

        Account mAccount = AppUtils.getAccount(getContext());
        if (mAccount != null) {
            // fetch calendar colors
            final SparseIntArray mColors = new SparseIntArray();
            ContentResolver cr = getContext().getContentResolver();
            Cursor cursor = cr.query(CalendarContractWrapper.Calendars.CONTENT_URI(), new String[] {
                    CalendarContractWrapper.Calendars._ID(), CalendarContractWrapper.Calendars.CALENDAR_COLOR() },
                    null, null, null);
            if (cursor != null) {
                while (cursor.moveToNext()) {
                    mColors.put(cursor.getInt(0), cursor.getInt(1));
                }
                cursor.close();
            }

            List<CalendarListEvent> mEvents = new ArrayList<>();

            if (data != null) {
                data.moveToFirst();
                data.moveToPrevious();
                while (data.moveToNext()) {
                    mEvents.add(new CalendarListEvent(getContext(), data.getLong(CalendarUtils.COLUMN_EVENT_ID),
                            mColors.get(data.getInt(CalendarUtils.COLUMN_EVENT_CAL_ID)),
                            data.getString(CalendarUtils.COLUMN_EVENT_TITLE),
                            data.getString(CalendarUtils.COLUMN_EVENT_DESCRIPTION),
                            data.getString(CalendarUtils.COLUMN_EVENT_LOCATION),
                            data.getLong(CalendarUtils.COLUMN_EVENT_DTSTART),
                            data.getLong(CalendarUtils.COLUMN_EVENT_DTEND),
                            data.getInt(CalendarUtils.COLUMN_EVENT_ALL_DAY) == 1));
                }
            }

            mAdapter.addAll(mEvents);
        }

        mAdapter.notifyDataSetChanged();

        finishProgress();
    }

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {
        mAdapter.clear();
        mAdapter.notifyDataSetChanged();

        finishProgress();
    }

    @Override
    public void onContentChanged(boolean selfChange) {
        loadData();
    }
}