Java tutorial
/* * Copyright 2013 Daniel Grech * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.dgsd.android.ShiftTracker.Adapter; import android.content.Context; import android.database.Cursor; import android.database.MatrixCursor; import android.graphics.Typeface; import android.support.v4.content.CursorLoader; import android.text.TextUtils; import android.text.format.DateFormat; import android.text.format.DateUtils; import android.text.format.Time; import android.util.SparseArray; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import com.dgsd.android.ShiftTracker.Data.DbField; import com.dgsd.android.ShiftTracker.Data.DbTable; import com.dgsd.android.ShiftTracker.Data.Provider; import com.dgsd.android.ShiftTracker.Model.Shift; import com.dgsd.android.ShiftTracker.R; import com.dgsd.android.ShiftTracker.Util.Prefs; import com.dgsd.android.ShiftTracker.Util.TimeUtils; import com.dgsd.android.ShiftTracker.Util.UIUtils; import com.emilsjolander.components.StickyListHeaders.StickyListHeadersCursorAdapter; import java.text.NumberFormat; import java.util.*; public class WeekAdapter extends StickyListHeadersCursorAdapter { public static final String NEW_ROW_KEY = WeekAdapter.class.getName() + "_NEW_ROW_KEY"; private LayoutInflater inflater; private int mStartingJulianDay; private Random mRand; private Time mTime; private SparseArray<String> mJdToTitleArray; private SparseArray<String> mIdToTimeArray; private SparseArray<String> mIdToPayArray; private boolean mIs24Hour; private boolean mShowIncomePref; private Formatter mFormatter; private StringBuilder mStringBuilder; private NumberFormat mCurrencyFormatter; private int mCurrentJulianDay; public WeekAdapter(Context context, Cursor c, int julianDay) { super(context, c, false); inflater = LayoutInflater.from(context); mStartingJulianDay = julianDay; mRand = new Random(); mTime = new Time(); mIs24Hour = DateFormat.is24HourFormat(context); mStringBuilder = new StringBuilder(); mFormatter = new Formatter((mStringBuilder)); mCurrencyFormatter = NumberFormat.getCurrencyInstance(); //Caching mJdToTitleArray = new SparseArray<String>(); mIdToTimeArray = new SparseArray<String>(); mIdToPayArray = new SparseArray<String>(); mCurrentJulianDay = TimeUtils.getCurrentJulianDay(); mShowIncomePref = Prefs.getInstance(context).get(context.getString(R.string.settings_key_show_income), true); } @Override protected View newHeaderView(Context context, Cursor cursor) { View v = inflater.inflate(R.layout.title_with_underline, null); new HeaderViewHolder(v); return v; } @Override protected void bindHeaderView(View view, Context context, Cursor cursor) { HeaderViewHolder holder = (HeaderViewHolder) view.getTag(); final int jd = cursor.getInt(cursor.getColumnIndex(DbField.JULIAN_DAY.name)); String title = mJdToTitleArray.get(jd, null); if (TextUtils.isEmpty(title)) { mTime.setJulianDay(jd); title = DateUtils.formatDateTime(getContext(), mTime.toMillis(true), DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY | DateUtils.FORMAT_ABBREV_MONTH | DateUtils.FORMAT_NO_YEAR); mJdToTitleArray.put(jd, title); } //Highlight the current day with a bold title if (jd == mCurrentJulianDay) holder.title.setTypeface(null, Typeface.BOLD); else holder.title.setTypeface(null, Typeface.NORMAL); holder.title.setText(title); } @Override protected long getHeaderId(Context context, Cursor cursor) { return cursor.getLong(cursor.getColumnIndex(DbField.JULIAN_DAY.name)); } @Override public void bindView(View view, Context context, Cursor cursor) { ViewHolder holder = (ViewHolder) view.getTag(); final Shift shift = Shift.fromCursor(cursor); if (TextUtils.equals(NEW_ROW_KEY, shift.name)) { holder.noShiftWrapper.setVisibility(View.VISIBLE); holder.shiftWrapper.setVisibility(View.GONE); holder.shift = null; holder.julianDay = shift.julianDay; return; } holder.noShiftWrapper.setVisibility(View.GONE); holder.shiftWrapper.setVisibility(View.VISIBLE); holder.name.setText(shift.name); holder.time.setText(getTimeText(shift)); String payText = getPayText(shift); if (mShowIncomePref && !TextUtils.isEmpty(payText)) { holder.pay.setText(payText); holder.pay.setVisibility(View.VISIBLE); } else { holder.pay.setText(null); holder.pay.setVisibility(View.GONE); } if (TextUtils.isEmpty(shift.note)) { holder.note.setVisibility(View.GONE); } else { holder.note.setText(shift.note); holder.note.setVisibility(View.VISIBLE); } holder.shift = shift; holder.julianDay = shift.julianDay; } @Override public View newView(Context context, Cursor cursor, ViewGroup parent) { View v = inflater.inflate(R.layout.list_item_shift_wrapper, null); new ViewHolder(v); return v; } @Override public Cursor swapCursor(Cursor cursor) { clearCaches(); if (cursor == null) return super.swapCursor(null); MatrixCursor mc = new MatrixCursor(DbTable.SHIFTS.getFieldNames(), cursor.getCount() + 7); int jd = mStartingJulianDay; final int colCount = cursor.getColumnCount(); SparseArray<List<Object[]>> jdToRowArray = new SparseArray<List<Object[]>>(); if (cursor.moveToFirst()) { final int jdIndex = cursor.getColumnIndex(DbField.JULIAN_DAY.name); do { Object[] row = new Object[colCount]; for (int i = 0; i < colCount; i++) row[i] = cursor.getString(i); final int shiftDay = cursor.getInt(jdIndex); List<Object[]> rowsOnSameJd = jdToRowArray.get(shiftDay, null); if (rowsOnSameJd == null) rowsOnSameJd = new ArrayList<Object[]>(); rowsOnSameJd.add(row); jdToRowArray.put(shiftDay, rowsOnSameJd); } while (cursor.moveToNext()); } for (int i = jd; i < jd + 7; i++) { List<Object[]> rows = jdToRowArray.get(i); if (rows != null) for (Object[] row : rows) mc.addRow(row); //Add a 'Add Shift' row Object[] row = new Object[colCount]; row[0] = mRand.nextInt(Integer.MAX_VALUE); // DbField.ID row[1] = i; // DbField.JULIAN_DAY row[2] = i; // DbField.END_JULIAN_DAY row[3] = -1; // DbField.START_TIME row[4] = -1; // DbField.END_TIME row[5] = -1; // DbField.PAY_RATE row[6] = NEW_ROW_KEY; // DbField.NAME row[7] = null; // DbField.NOTE row[8] = -1; // DbField.BREAK_DURATION row[9] = 0; // DbField.IS_TEMPLATE row[10] = -1; // DbField.REMINDER mc.addRow(row); } return super.swapCursor(mc); } private void clearCaches() { mJdToTitleArray.clear(); mIdToTimeArray.clear(); mIdToPayArray.clear(); } public CursorLoader getWeeklyLoader(Context context) { final String sel = "(" + DbField.JULIAN_DAY + " >= ? AND " + DbField.JULIAN_DAY + " < ?) OR (" + DbField.END_JULIAN_DAY + " >= ? AND " + DbField.END_JULIAN_DAY + " < ?)"; final String[] args = new String[] { String.valueOf(mStartingJulianDay), String.valueOf(mStartingJulianDay + 7), String.valueOf(mStartingJulianDay), String.valueOf(mStartingJulianDay + 7) }; final String sort = DbField.JULIAN_DAY + " ASC," + DbField.START_TIME + " ASC, " + DbField.NAME + " ASC"; return new CursorLoader(context, Provider.SHIFTS_URI, DbTable.SHIFTS.getFieldNames(), sel, args, sort); } private String getTimeText(Shift shift) { String time = mIdToTimeArray.get((int) shift.id); if (!TextUtils.isEmpty(time)) return time; int flags = DateUtils.FORMAT_SHOW_TIME; if (mIs24Hour) flags |= DateUtils.FORMAT_24HOUR; mStringBuilder.setLength(0); time = DateUtils.formatDateRange(getContext(), mFormatter, shift.getStartTime(), shift.getEndTime(), flags) .toString(); time += " (" + UIUtils.getDurationAsHours(shift.getDurationInMinutes()) + ")"; mIdToTimeArray.put((int) shift.id, time); return time; } private String getPayText(Shift shift) { if (shift.payRate <= 0.01) return null; String pay = mIdToPayArray.get((int) shift.id); if (!TextUtils.isEmpty(pay)) return pay; pay = mCurrencyFormatter.format(shift.getIncome()); mIdToPayArray.put((int) shift.id, pay); return pay; } private static class HeaderViewHolder { TextView title; public HeaderViewHolder(View view) { if (view == null) return; title = (TextView) view.findViewById(R.id.text); view.setTag(this); } } public static class ViewHolder { View noShiftWrapper; View shiftWrapper; TextView name; TextView time; TextView note; TextView pay; public Shift shift; public int julianDay; public ViewHolder(View view) { if (view == null) return; noShiftWrapper = view.findViewById(R.id.no_shift); shiftWrapper = view.findViewById(R.id.new_shift); name = (TextView) view.findViewById(R.id.name); time = (TextView) view.findViewById(R.id.time); note = (TextView) view.findViewById(R.id.note); pay = (TextView) view.findViewById(R.id.pay); julianDay = -1; view.setTag(this); } } }