Java tutorial
/* Copyright (C) 2013, Martin Stoyanov * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero 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 Affero General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.mstoyanov.music_lessons; import java.util.ArrayList; import java.util.List; import com.mstoyanov.music_lessons.data.SchoolContract; import com.mstoyanov.music_lessons.data.SchoolContract.Schedule; import com.mstoyanov.music_lessons.data.SchoolContract.Students; import com.mstoyanov.music_lessons.model.Actions; import com.mstoyanov.music_lessons.model.ActionsAdapter; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; import android.support.v4.widget.SimpleCursorAdapter; 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.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import android.widget.TextView; /* Six ScheduleFragments are available under the Schedule tab, one for each weekday. * The ScheduleFragment is started by the MainActivity, with weekday passed in. * In single pane mode, only "add lesson" menu is available, it starts the AddLessonActivity. * Students, already in the database, can be assigned lesson day and time. * The LessonDetailsActivity starts on lesson item click, with lesson Id passed in, it reveals * student contact data and it allows call, SMS or email. From the LessonDetailsActivity, * the lesson can be deleted, or the EditLessonActivity can be called, again with * lesson Id passed in. * * In dual pane mode, the LessonDetailsActivity logic and layout is incorporated into the * ScheduleFragment, so the "edit" and "delete" menus appear in the ScheduleFragment in dual * pane mode only.*/ public class ScheduleFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor>, OnItemClickListener { private View view; private String weekday; private int lessonId; private boolean dualPane; // the current layout // lessons are assigned to this day: private boolean lessonsBooked; private int selectedLesson; // index private List<Actions> actions; // call, SMS, email private ListView lessonsList; private ListView actionsList; private TextView firstNameTextView; private TextView lastNameTextView; private TextView firstNameLabel; private TextView lastNameLabel; private SimpleCursorAdapter lessonsAdapter; private ActionsAdapter actionsAdapter; private static final int LESSONS_LOADER = 0; private static final int ACTIONS_LOADER = 1; // lessons query: private static final String[] projection_lessons = { Schedule.COLUMN_NAME_LESSON_ID + " as _id", Schedule.COLUMN_NAME_TIME_FROM, Schedule.COLUMN_NAME_TIME_TO, "schedule." + Schedule.COLUMN_NAME_STUDENT_ID, Students.COLUMN_NAME_FIRST_NAME, Students.COLUMN_NAME_LAST_NAME }; private static final String selection_lessons = "weekday = ?"; private String[] selectionArgs_lessons = new String[1]; private static final String sortOrder = Schedule.COLUMN_NAME_TIME_FROM + ", " + Schedule.COLUMN_NAME_TIME_TO; // actions query: private static final String[] projection_actions = { Students.COLUMN_NAME_STUDENT_ID + " as _id", Students.COLUMN_NAME_HOME_PHONE, Students.COLUMN_NAME_CELL_PHONE, Students.COLUMN_NAME_WORK_PHONE, Students.COLUMN_NAME_EMAIL }; private static final String selection_actions = "studentID = ?"; private String[] selectionArgs_actions = new String[1]; // delete lesson query: private static final String selection_delete = "lessonId = ?"; private String[] selectionArgs_delete = new String[1]; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); view = inflater.inflate(R.layout.schedule_fragment, container, false); return view; } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); setHasOptionsMenu(true); // get the weekday from the MainActivity: weekday = getArguments().getString("WEEKDAY"); ((TextView) view.findViewById(R.id.weekday)).setText(weekday); selectionArgs_lessons[0] = weekday; // determine the current layout: View actionsView = getActivity().findViewById(R.id.lesson_details_pane); dualPane = actionsView != null && actionsView.getVisibility() == View.VISIBLE; String[] fromColumns = new String[] { "timeFrom", "timeTo", "firstName", "lastName" }; int[] toViews = new int[] { R.id.timeFrom, R.id.timeTo, R.id.firstName, R.id.lastName }; lessonsAdapter = new SimpleCursorAdapter(getActivity(), R.layout.lesson_list_item, // layout null, // no cursor is created yet fromColumns, // columns toViews, // UI controls 0 // flags ); lessonsList = (ListView) view.findViewById(R.id.lessons_list); lessonsList.setOnItemClickListener(this); lessonsList.setAdapter(lessonsAdapter); // in dual pane mode, the controls from the LessonDetailsActivity // appear in the right column of the ScheduleFragment: if (dualPane) { if (savedInstanceState != null) { selectedLesson = savedInstanceState.getInt("SELECTED_LESSON", 0); } firstNameLabel = ((TextView) view.findViewById(R.id.label_fname_schedule)); firstNameTextView = ((TextView) view.findViewById(R.id.fname_schedule)); lastNameLabel = ((TextView) view.findViewById(R.id.label_lname_schedule)); lastNameTextView = ((TextView) view.findViewById(R.id.lname_schedule)); actionsList = (ListView) view.findViewById(R.id.actions_list); actionsList.setOnItemClickListener(this); actions = new ArrayList<Actions>(); actionsAdapter = new ActionsAdapter(getActivity(), actions); actionsList.setAdapter(actionsAdapter); } } @Override public void onResume() { super.onResume(); getLoaderManager().restartLoader(LESSONS_LOADER, null, this); } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (dualPane) { outState.putInt("SELECTED_LESSON", selectedLesson); } } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { getActivity().getMenuInflater().inflate(R.menu.schedule_menu, menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_add_lesson: Intent intent = new Intent(getActivity(), AddLessonActivity.class); intent.putExtra("WEEKDAY", weekday); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); return true; case R.id.menu_edit_lesson: if (lessonsBooked) { intent = new Intent(getActivity(), EditLessonActivity.class); intent.putExtra("LESSON_ID", lessonId); intent.putExtra("DUAL_PANE", dualPane); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); return true; } return true; case R.id.menu_delete_lesson: if (lessonsBooked) { // Create AlertDialog: AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity()); alertDialogBuilder.setMessage("Delete lesson?") .setPositiveButton("Delete", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // Call the "delete" method of the // DataProvider: getActivity().getContentResolver().delete(SchoolContract.SCHEDULE_TABLE_CONTENTURI, // uri selection_delete, // selection selectionArgs_delete // selectionArgs ); Intent intent = new Intent(getActivity(), // context MainActivity.class // class to // navigate // to ); // after "delete" return to the day the // lesson was on: intent.putExtra("WEEKDAY", weekday); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); } }).setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); AlertDialog alertDialog = alertDialogBuilder.create(); alertDialog.show(); return true; } return true; case R.id.menu_export_schedule: intent = new Intent(getActivity(), ExportScheduleActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); return true; case R.id.menu_settings: intent = new Intent(getActivity(), SettingsActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); return true; default: throw new IllegalArgumentException("Invalid ItemId: " + item.getItemId()); } } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { switch (parent.getId()) { case R.id.lessons_list: Cursor cursor = (Cursor) parent.getItemAtPosition(position); int studentId = cursor.getInt(cursor.getColumnIndex("studentID")); lessonId = cursor.getInt(cursor.getColumnIndex("_id")); String firstName = cursor.getString(cursor.getColumnIndex("firstName")); String lastName = cursor.getString(cursor.getColumnIndex("lastName")); if (dualPane) { selectionArgs_delete[0] = String.valueOf(lessonId); lessonsList.setItemChecked(position, true); selectedLesson = position; selectionArgs_actions[0] = String.valueOf(studentId); firstNameLabel.setText("First Name"); firstNameTextView.setText(firstName); lastNameLabel.setText("Last Name"); lastNameTextView.setText(lastName); getLoaderManager().restartLoader(ACTIONS_LOADER, null, this); } else { Intent intent = new Intent(getActivity(), LessonDetailsActivity.class); intent.putExtra("LESSON_ID", lessonId); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); } break; case R.id.actions_list: Actions action = actions.get(position); switch (action.getType()) { case Actions.ACTION_CALL: Uri callUri = Uri.parse("tel:" + action.getData()); Intent intent = new Intent(Intent.ACTION_CALL, callUri); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); break; case Actions.ACTION_EMAIL: intent = new Intent(Intent.ACTION_SEND); intent.setType("plain/text"); intent.putExtra(Intent.EXTRA_EMAIL, new String[] { action.getData() }); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); break; case Actions.ACTION_SMS: Uri smsUri = Uri.parse("sms:" + action.getData()); intent = new Intent(Intent.ACTION_VIEW, smsUri); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); startActivity(intent); break; default: throw new IllegalArgumentException("Invalid action type: " + action.getType()); } break; default: throw new IllegalArgumentException("Invalid parentId: " + parent.getId()); } } @Override public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle) { switch (loaderID) { case LESSONS_LOADER: String innerJoin = " INNER JOIN " + Students.TABLE_NAME + " ON " + "schedule." + Schedule.COLUMN_NAME_STUDENT_ID + " = " + "students." + Students.COLUMN_NAME_STUDENT_ID; Uri uri = Uri.withAppendedPath(SchoolContract.SCHEDULE_TABLE_CONTENTURI, innerJoin); return new CursorLoader(getActivity(), // context uri, // uri projection_lessons, // projection selection_lessons, // selection selectionArgs_lessons, // selectionArgs sortOrder // timeFrom, timeTo ); case ACTIONS_LOADER: return new CursorLoader(getActivity(), // context SchoolContract.STUDENTS_TABLE_CONTENTURI, // table projection_actions, // projection selection_actions, // selection selectionArgs_actions, // selectionArgs null // sortOrder ); default: throw new IllegalArgumentException("Invalid loaderID: " + loaderID); } } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { switch (loader.getId()) { case LESSONS_LOADER: lessonsAdapter.swapCursor(cursor); if (dualPane && cursor.getCount() > 0) { lessonsBooked = true; // there are lessons assigned to this day onItemClick(lessonsList, lessonsList.getChildAt(selectedLesson), selectedLesson, -1); } break; case ACTIONS_LOADER: if (cursor != null) { cursor.moveToFirst(); actions.clear(); firstNameLabel.setText(getString(R.string.first_name)); lastNameLabel.setText(getString(R.string.last_name)); String homePhone = cursor.getString(cursor.getColumnIndex("homePhone")); if (homePhone.length() > 0) { actions.add(new Actions("Home", homePhone, Actions.ACTION_CALL)); } String cellPhone = cursor.getString(cursor.getColumnIndex("cellPhone")); if (cellPhone.length() > 0) { actions.add(new Actions("Mobile", cellPhone, Actions.ACTION_CALL)); actions.add(new Actions("SMS", cellPhone, Actions.ACTION_SMS)); } String workPhone = cursor.getString(cursor.getColumnIndex("workPhone")); if (workPhone.length() > 0) { actions.add(new Actions("Office", workPhone, Actions.ACTION_CALL)); } String email = cursor.getString(cursor.getColumnIndex("email")); if (email.length() > 0) { actions.add(new Actions("Email", email, Actions.ACTION_EMAIL)); } actionsAdapter.notifyDataSetChanged(); } break; default: throw new IllegalArgumentException("Unknown loaderId: " + loader.getId()); } } @Override public void onLoaderReset(Loader<Cursor> loader) { switch (loader.getId()) { case LESSONS_LOADER: lessonsAdapter.swapCursor(null); break; case ACTIONS_LOADER: actionsAdapter.clear(); break; default: throw new IllegalArgumentException("Unknown loaderId: " + loader.getId()); } } }