19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.util;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Calendar;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Helps answer common questions that come up when displaying a month in a
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6 row calendar grid format.
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Not thread safe.
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class MonthDisplayHelper {
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // display pref
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final int mWeekStartDay;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // holds current month, year, helps compute display
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private Calendar mCalendar;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // cached computed stuff that helps with display
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNumDaysInMonth;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNumDaysInPrevMonth;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mOffset;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param year The year.
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param month The month.
449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param weekStartDay What day of the week the week should start.
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MonthDisplayHelper(int year, int month, int weekStartDay) {
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (weekStartDay < Calendar.SUNDAY || weekStartDay > Calendar.SATURDAY) {
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException();
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWeekStartDay = weekStartDay;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCalendar = Calendar.getInstance();
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCalendar.set(Calendar.YEAR, year);
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCalendar.set(Calendar.MONTH, month);
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCalendar.set(Calendar.DAY_OF_MONTH, 1);
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCalendar.set(Calendar.HOUR_OF_DAY, 0);
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCalendar.set(Calendar.MINUTE, 0);
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCalendar.set(Calendar.SECOND, 0);
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCalendar.getTimeInMillis();
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        recalculate();
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public MonthDisplayHelper(int year, int month) {
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        this(year, month, Calendar.SUNDAY);
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getYear() {
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCalendar.get(Calendar.YEAR);
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getMonth() {
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCalendar.get(Calendar.MONTH);
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getWeekStartDay() {
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mWeekStartDay;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The first day of the month using a constants such as
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   {@link java.util.Calendar#SUNDAY}.
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getFirstDayOfMonth() {
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mCalendar.get(Calendar.DAY_OF_WEEK);
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The number of days in the month.
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getNumberOfDaysInMonth() {
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mNumDaysInMonth;
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The offset from displaying everything starting on the very first
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   box.  For example, if the calendar is set to display the first day of
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *   the week as Sunday, and the month starts on a Wednesday, the offset is 3.
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getOffset() {
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mOffset;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param row Which row (0-5).
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return the digits of the month to display in one
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * of the 6 rows of a calendar month display.
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int[] getDigitsForRow(int row) {
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (row < 0 || row > 5) {
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("row " + row
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " out of range (0-5)");
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int [] result = new int[7];
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int column = 0; column < 7; column++) {
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            result[column] = getDayAt(row, column);
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return result;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param row The row, 0-5, starting from the top.
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param column The column, 0-6, starting from the left.
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return The day at a particular row, column
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getDayAt(int row, int column) {
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (row == 0 && column < mOffset) {
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mNumDaysInPrevMonth + column - mOffset + 1;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int day = 7 * row + column - mOffset + 1;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (day > mNumDaysInMonth) ?
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                day - mNumDaysInMonth : day;
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Which row day is in.
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getRowOf(int day) {
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (day + mOffset - 1) / 7;
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Which column day is in.
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int getColumnOf(int day) {
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return (day + mOffset - 1) % 7;
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Decrement the month.
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void previousMonth() {
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCalendar.add(Calendar.MONTH, -1);
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        recalculate();
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Increment the month.
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void nextMonth() {
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCalendar.add(Calendar.MONTH, 1);
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        recalculate();
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Whether the row and column fall within the month.
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean isWithinCurrentMonth(int row, int column) {
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (row < 0 || column < 0 || row > 5 || column > 6) {
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (row == 0 && column < mOffset) {
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int day = 7 * row + column - mOffset + 1;
1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (day > mNumDaysInMonth) {
1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return true;
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // helper method that recalculates cached values based on current month / year
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private void recalculate() {
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumDaysInMonth = mCalendar.getActualMaximum(Calendar.DAY_OF_MONTH);
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCalendar.add(Calendar.MONTH, -1);
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mNumDaysInPrevMonth = mCalendar.getActualMaximum(Calendar.DAY_OF_MONTH);
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCalendar.add(Calendar.MONTH, 1);
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int firstDayOfMonth = getFirstDayOfMonth();
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int offset = firstDayOfMonth - mWeekStartDay;
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (offset < 0) {
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            offset += 7;
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mOffset = offset;
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
214