AOSP/Calendar - Add Kotlin copy of CalendarData.java and SimpleWeekView.java

Test: none, no functional change in this commit when merged with corresponding Kotlin conversion.
Change-Id: Ie7de49ede9e883c9f6cca688ba95cb90a1b594b2
diff --git a/src/com/android/calendar/CalendarData.kt b/src/com/android/calendar/CalendarData.kt
new file mode 100644
index 0000000..5c8456f
--- /dev/null
+++ b/src/com/android/calendar/CalendarData.kt
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2006 The Android Open Source Project
+ *
+ * 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.android.calendar;
+
+public final class CalendarData {
+    static final String[] s12HoursNoAmPm = { "12", "1", "2", "3", "4",
+        "5", "6", "7", "8", "9", "10", "11", "12",
+        "1", "2", "3", "4", "5", "6", "7", "8",
+        "9", "10", "11", "12" };
+
+    static final String[] s24Hours = { "00", "01", "02", "03", "04", "05",
+        "06", "07", "08", "09", "10", "11", "12", "13", "14", "15", "16",
+        "17", "18", "19", "20", "21", "22", "23", "00" };
+}
diff --git a/src/com/android/calendar/month/SimpleWeekView.kt b/src/com/android/calendar/month/SimpleWeekView.kt
new file mode 100644
index 0000000..4d0c09f
--- /dev/null
+++ b/src/com/android/calendar/month/SimpleWeekView.kt
@@ -0,0 +1,551 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * 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.android.calendar.month;
+
+import com.android.calendar.R;
+import com.android.calendar.Utils;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Align;
+import android.graphics.Paint.Style;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.text.format.DateUtils;
+import android.text.format.Time;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
+import android.view.accessibility.AccessibilityManager;
+
+import java.security.InvalidParameterException;
+import java.util.HashMap;
+
+/**
+ * <p>
+ * This is a dynamic view for drawing a single week. It can be configured to
+ * display the week number, start the week on a given day, or show a reduced
+ * number of days. It is intended for use as a single view within a ListView.
+ * See {@link SimpleWeeksAdapter} for usage.
+ * </p>
+ */
+public class SimpleWeekView extends View {
+    private static final String TAG = "MonthView";
+
+    /**
+     * These params can be passed into the view to control how it appears.
+     * {@link #VIEW_PARAMS_WEEK} is the only required field, though the default
+     * values are unlikely to fit most layouts correctly.
+     */
+    /**
+     * This sets the height of this week in pixels
+     */
+    public static final String VIEW_PARAMS_HEIGHT = "height";
+    /**
+     * This specifies the position (or weeks since the epoch) of this week,
+     * calculated using {@link Utils#getWeeksSinceEpochFromJulianDay}
+     */
+    public static final String VIEW_PARAMS_WEEK = "week";
+    /**
+     * This sets one of the days in this view as selected {@link Time#SUNDAY}
+     * through {@link Time#SATURDAY}.
+     */
+    public static final String VIEW_PARAMS_SELECTED_DAY = "selected_day";
+    /**
+     * Which day the week should start on. {@link Time#SUNDAY} through
+     * {@link Time#SATURDAY}.
+     */
+    public static final String VIEW_PARAMS_WEEK_START = "week_start";
+    /**
+     * How many days to display at a time. Days will be displayed starting with
+     * {@link #mWeekStart}.
+     */
+    public static final String VIEW_PARAMS_NUM_DAYS = "num_days";
+    /**
+     * Which month is currently in focus, as defined by {@link Time#month}
+     * [0-11].
+     */
+    public static final String VIEW_PARAMS_FOCUS_MONTH = "focus_month";
+    /**
+     * If this month should display week numbers. false if 0, true otherwise.
+     */
+    public static final String VIEW_PARAMS_SHOW_WK_NUM = "show_wk_num";
+
+    protected static int DEFAULT_HEIGHT = 32;
+    protected static int MIN_HEIGHT = 10;
+    protected static final int DEFAULT_SELECTED_DAY = -1;
+    protected static final int DEFAULT_WEEK_START = Time.SUNDAY;
+    protected static final int DEFAULT_NUM_DAYS = 7;
+    protected static final int DEFAULT_SHOW_WK_NUM = 0;
+    protected static final int DEFAULT_FOCUS_MONTH = -1;
+
+    protected static int DAY_SEPARATOR_WIDTH = 1;
+
+    protected static int MINI_DAY_NUMBER_TEXT_SIZE = 14;
+    protected static int MINI_WK_NUMBER_TEXT_SIZE = 12;
+    protected static int MINI_TODAY_NUMBER_TEXT_SIZE = 18;
+    protected static int MINI_TODAY_OUTLINE_WIDTH = 2;
+    protected static int WEEK_NUM_MARGIN_BOTTOM = 4;
+
+    // used for scaling to the device density
+    protected static float mScale = 0;
+
+    // affects the padding on the sides of this view
+    protected int mPadding = 0;
+
+    protected Rect r = new Rect();
+    protected Paint p = new Paint();
+    protected Paint mMonthNumPaint;
+    protected Drawable mSelectedDayLine;
+
+    // Cache the number strings so we don't have to recompute them each time
+    protected String[] mDayNumbers;
+    // Quick lookup for checking which days are in the focus month
+    protected boolean[] mFocusDay;
+    // Quick lookup for checking which days are in an odd month (to set a different background)
+    protected boolean[] mOddMonth;
+    // The Julian day of the first day displayed by this item
+    protected int mFirstJulianDay = -1;
+    // The month of the first day in this week
+    protected int mFirstMonth = -1;
+    // The month of the last day in this week
+    protected int mLastMonth = -1;
+    // The position of this week, equivalent to weeks since the week of Jan 1st,
+    // 1970
+    protected int mWeek = -1;
+    // Quick reference to the width of this view, matches parent
+    protected int mWidth;
+    // The height this view should draw at in pixels, set by height param
+    protected int mHeight = DEFAULT_HEIGHT;
+    // Whether the week number should be shown
+    protected boolean mShowWeekNum = false;
+    // If this view contains the selected day
+    protected boolean mHasSelectedDay = false;
+    // If this view contains the today
+    protected boolean mHasToday = false;
+    // Which day is selected [0-6] or -1 if no day is selected
+    protected int mSelectedDay = DEFAULT_SELECTED_DAY;
+    // Which day is today [0-6] or -1 if no day is today
+    protected int mToday = DEFAULT_SELECTED_DAY;
+    // Which day of the week to start on [0-6]
+    protected int mWeekStart = DEFAULT_WEEK_START;
+    // How many days to display
+    protected int mNumDays = DEFAULT_NUM_DAYS;
+    // The number of days + a spot for week number if it is displayed
+    protected int mNumCells = mNumDays;
+    // The left edge of the selected day
+    protected int mSelectedLeft = -1;
+    // The right edge of the selected day
+    protected int mSelectedRight = -1;
+    // The timezone to display times/dates in (used for determining when Today
+    // is)
+    protected String mTimeZone = Time.getCurrentTimezone();
+
+    protected int mBGColor;
+    protected int mSelectedWeekBGColor;
+    protected int mFocusMonthColor;
+    protected int mOtherMonthColor;
+    protected int mDaySeparatorColor;
+    protected int mTodayOutlineColor;
+    protected int mWeekNumColor;
+
+    public SimpleWeekView(Context context) {
+        super(context);
+
+        Resources res = context.getResources();
+
+        mBGColor = res.getColor(R.color.month_bgcolor);
+        mSelectedWeekBGColor = res.getColor(R.color.month_selected_week_bgcolor);
+        mFocusMonthColor = res.getColor(R.color.month_mini_day_number);
+        mOtherMonthColor = res.getColor(R.color.month_other_month_day_number);
+        mDaySeparatorColor = res.getColor(R.color.month_grid_lines);
+        mTodayOutlineColor = res.getColor(R.color.mini_month_today_outline_color);
+        mWeekNumColor = res.getColor(R.color.month_week_num_color);
+        mSelectedDayLine = res.getDrawable(R.drawable.dayline_minical_holo_light);
+
+        if (mScale == 0) {
+            mScale = context.getResources().getDisplayMetrics().density;
+            if (mScale != 1) {
+                DEFAULT_HEIGHT *= mScale;
+                MIN_HEIGHT *= mScale;
+                MINI_DAY_NUMBER_TEXT_SIZE *= mScale;
+                MINI_TODAY_NUMBER_TEXT_SIZE *= mScale;
+                MINI_TODAY_OUTLINE_WIDTH *= mScale;
+                WEEK_NUM_MARGIN_BOTTOM *= mScale;
+                DAY_SEPARATOR_WIDTH *= mScale;
+                MINI_WK_NUMBER_TEXT_SIZE *= mScale;
+            }
+        }
+
+        // Sets up any standard paints that will be used
+        initView();
+    }
+
+    /**
+     * Sets all the parameters for displaying this week. The only required
+     * parameter is the week number. Other parameters have a default value and
+     * will only update if a new value is included, except for focus month,
+     * which will always default to no focus month if no value is passed in. See
+     * {@link #VIEW_PARAMS_HEIGHT} for more info on parameters.
+     *
+     * @param params A map of the new parameters, see
+     *            {@link #VIEW_PARAMS_HEIGHT}
+     * @param tz The time zone this view should reference times in
+     */
+    public void setWeekParams(HashMap<String, Integer> params, String tz) {
+        if (!params.containsKey(VIEW_PARAMS_WEEK)) {
+            throw new InvalidParameterException("You must specify the week number for this view");
+        }
+        setTag(params);
+        mTimeZone = tz;
+        // We keep the current value for any params not present
+        if (params.containsKey(VIEW_PARAMS_HEIGHT)) {
+            mHeight = params.get(VIEW_PARAMS_HEIGHT);
+            if (mHeight < MIN_HEIGHT) {
+                mHeight = MIN_HEIGHT;
+            }
+        }
+        if (params.containsKey(VIEW_PARAMS_SELECTED_DAY)) {
+            mSelectedDay = params.get(VIEW_PARAMS_SELECTED_DAY);
+        }
+        mHasSelectedDay = mSelectedDay != -1;
+        if (params.containsKey(VIEW_PARAMS_NUM_DAYS)) {
+            mNumDays = params.get(VIEW_PARAMS_NUM_DAYS);
+        }
+        if (params.containsKey(VIEW_PARAMS_SHOW_WK_NUM)) {
+            if (params.get(VIEW_PARAMS_SHOW_WK_NUM) != 0) {
+                mShowWeekNum = true;
+            } else {
+                mShowWeekNum = false;
+            }
+        }
+        mNumCells = mShowWeekNum ? mNumDays + 1 : mNumDays;
+
+        // Allocate space for caching the day numbers and focus values
+        mDayNumbers = new String[mNumCells];
+        mFocusDay = new boolean[mNumCells];
+        mOddMonth = new boolean[mNumCells];
+        mWeek = params.get(VIEW_PARAMS_WEEK);
+        int julianMonday = Utils.getJulianMondayFromWeeksSinceEpoch(mWeek);
+        Time time = new Time(tz);
+        time.setJulianDay(julianMonday);
+
+        // If we're showing the week number calculate it based on Monday
+        int i = 0;
+        if (mShowWeekNum) {
+            mDayNumbers[0] = Integer.toString(time.getWeekNumber());
+            i++;
+        }
+
+        if (params.containsKey(VIEW_PARAMS_WEEK_START)) {
+            mWeekStart = params.get(VIEW_PARAMS_WEEK_START);
+        }
+
+        // Now adjust our starting day based on the start day of the week
+        // If the week is set to start on a Saturday the first week will be
+        // Dec 27th 1969 -Jan 2nd, 1970
+        if (time.weekDay != mWeekStart) {
+            int diff = time.weekDay - mWeekStart;
+            if (diff < 0) {
+                diff += 7;
+            }
+            time.monthDay -= diff;
+            time.normalize(true);
+        }
+
+        mFirstJulianDay = Time.getJulianDay(time.toMillis(true), time.gmtoff);
+        mFirstMonth = time.month;
+
+        // Figure out what day today is
+        Time today = new Time(tz);
+        today.setToNow();
+        mHasToday = false;
+        mToday = -1;
+
+        int focusMonth = params.containsKey(VIEW_PARAMS_FOCUS_MONTH) ? params.get(
+                VIEW_PARAMS_FOCUS_MONTH)
+                : DEFAULT_FOCUS_MONTH;
+
+        for (; i < mNumCells; i++) {
+            if (time.monthDay == 1) {
+                mFirstMonth = time.month;
+            }
+            mOddMonth [i] = (time.month %2) == 1;
+            if (time.month == focusMonth) {
+                mFocusDay[i] = true;
+            } else {
+                mFocusDay[i] = false;
+            }
+            if (time.year == today.year && time.yearDay == today.yearDay) {
+                mHasToday = true;
+                mToday = i;
+            }
+            mDayNumbers[i] = Integer.toString(time.monthDay++);
+            time.normalize(true);
+        }
+        // We do one extra add at the end of the loop, if that pushed us to a
+        // new month undo it
+        if (time.monthDay == 1) {
+            time.monthDay--;
+            time.normalize(true);
+        }
+        mLastMonth = time.month;
+
+        updateSelectionPositions();
+    }
+
+    /**
+     * Sets up the text and style properties for painting. Override this if you
+     * want to use a different paint.
+     */
+    protected void initView() {
+        p.setFakeBoldText(false);
+        p.setAntiAlias(true);
+        p.setTextSize(MINI_DAY_NUMBER_TEXT_SIZE);
+        p.setStyle(Style.FILL);
+
+        mMonthNumPaint = new Paint();
+        mMonthNumPaint.setFakeBoldText(true);
+        mMonthNumPaint.setAntiAlias(true);
+        mMonthNumPaint.setTextSize(MINI_DAY_NUMBER_TEXT_SIZE);
+        mMonthNumPaint.setColor(mFocusMonthColor);
+        mMonthNumPaint.setStyle(Style.FILL);
+        mMonthNumPaint.setTextAlign(Align.CENTER);
+    }
+
+    /**
+     * Returns the month of the first day in this week
+     *
+     * @return The month the first day of this view is in
+     */
+    public int getFirstMonth() {
+        return mFirstMonth;
+    }
+
+    /**
+     * Returns the month of the last day in this week
+     *
+     * @return The month the last day of this view is in
+     */
+    public int getLastMonth() {
+        return mLastMonth;
+    }
+
+    /**
+     * Returns the julian day of the first day in this view.
+     *
+     * @return The julian day of the first day in the view.
+     */
+    public int getFirstJulianDay() {
+        return mFirstJulianDay;
+    }
+
+    /**
+     * Calculates the day that the given x position is in, accounting for week
+     * number. Returns a Time referencing that day or null if
+     *
+     * @param x The x position of the touch event
+     * @return A time object for the tapped day or null if the position wasn't
+     *         in a day
+     */
+    public Time getDayFromLocation(float x) {
+        int dayStart = mShowWeekNum ? (mWidth - mPadding * 2) / mNumCells + mPadding : mPadding;
+        if (x < dayStart || x > mWidth - mPadding) {
+            return null;
+        }
+        // Selection is (x - start) / (pixels/day) == (x -s) * day / pixels
+        int dayPosition = (int) ((x - dayStart) * mNumDays / (mWidth - dayStart - mPadding));
+        int day = mFirstJulianDay + dayPosition;
+
+        Time time = new Time(mTimeZone);
+        if (mWeek == 0) {
+            // This week is weird...
+            if (day < Time.EPOCH_JULIAN_DAY) {
+                day++;
+            } else if (day == Time.EPOCH_JULIAN_DAY) {
+                time.set(1, 0, 1970);
+                time.normalize(true);
+                return time;
+            }
+        }
+
+        time.setJulianDay(day);
+        return time;
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        drawBackground(canvas);
+        drawWeekNums(canvas);
+        drawDaySeparators(canvas);
+    }
+
+    /**
+     * This draws the selection highlight if a day is selected in this week.
+     * Override this method if you wish to have a different background drawn.
+     *
+     * @param canvas The canvas to draw on
+     */
+    protected void drawBackground(Canvas canvas) {
+        if (mHasSelectedDay) {
+            p.setColor(mSelectedWeekBGColor);
+            p.setStyle(Style.FILL);
+        } else {
+            return;
+        }
+        r.top = 1;
+        r.bottom = mHeight - 1;
+        r.left = mPadding;
+        r.right = mSelectedLeft;
+        canvas.drawRect(r, p);
+        r.left = mSelectedRight;
+        r.right = mWidth - mPadding;
+        canvas.drawRect(r, p);
+    }
+
+    /**
+     * Draws the week and month day numbers for this week. Override this method
+     * if you need different placement.
+     *
+     * @param canvas The canvas to draw on
+     */
+    protected void drawWeekNums(Canvas canvas) {
+        int y = ((mHeight + MINI_DAY_NUMBER_TEXT_SIZE) / 2) - DAY_SEPARATOR_WIDTH;
+        int nDays = mNumCells;
+
+        int i = 0;
+        int divisor = 2 * nDays;
+        if (mShowWeekNum) {
+            p.setTextSize(MINI_WK_NUMBER_TEXT_SIZE);
+            p.setStyle(Style.FILL);
+            p.setTextAlign(Align.CENTER);
+            p.setAntiAlias(true);
+            p.setColor(mWeekNumColor);
+            int x = (mWidth - mPadding * 2) / divisor + mPadding;
+            canvas.drawText(mDayNumbers[0], x, y, p);
+            i++;
+        }
+
+        boolean isFocusMonth = mFocusDay[i];
+        mMonthNumPaint.setColor(isFocusMonth ? mFocusMonthColor : mOtherMonthColor);
+        mMonthNumPaint.setFakeBoldText(false);
+        for (; i < nDays; i++) {
+            if (mFocusDay[i] != isFocusMonth) {
+                isFocusMonth = mFocusDay[i];
+                mMonthNumPaint.setColor(isFocusMonth ? mFocusMonthColor : mOtherMonthColor);
+            }
+            if (mHasToday && mToday == i) {
+                mMonthNumPaint.setTextSize(MINI_TODAY_NUMBER_TEXT_SIZE);
+                mMonthNumPaint.setFakeBoldText(true);
+            }
+            int x = (2 * i + 1) * (mWidth - mPadding * 2) / (divisor) + mPadding;
+            canvas.drawText(mDayNumbers[i], x, y, mMonthNumPaint);
+            if (mHasToday && mToday == i) {
+                mMonthNumPaint.setTextSize(MINI_DAY_NUMBER_TEXT_SIZE);
+                mMonthNumPaint.setFakeBoldText(false);
+            }
+        }
+    }
+
+    /**
+     * Draws a horizontal line for separating the weeks. Override this method if
+     * you want custom separators.
+     *
+     * @param canvas The canvas to draw on
+     */
+    protected void drawDaySeparators(Canvas canvas) {
+        if (mHasSelectedDay) {
+            r.top = 1;
+            r.bottom = mHeight - 1;
+            r.left = mSelectedLeft + 1;
+            r.right = mSelectedRight - 1;
+            p.setStrokeWidth(MINI_TODAY_OUTLINE_WIDTH);
+            p.setStyle(Style.STROKE);
+            p.setColor(mTodayOutlineColor);
+            canvas.drawRect(r, p);
+        }
+        if (mShowWeekNum) {
+            p.setColor(mDaySeparatorColor);
+            p.setStrokeWidth(DAY_SEPARATOR_WIDTH);
+
+            int x = (mWidth - mPadding * 2) / mNumCells + mPadding;
+            canvas.drawLine(x, 0, x, mHeight, p);
+        }
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        mWidth = w;
+        updateSelectionPositions();
+    }
+
+    /**
+     * This calculates the positions for the selected day lines.
+     */
+    protected void updateSelectionPositions() {
+        if (mHasSelectedDay) {
+            int selectedPosition = mSelectedDay - mWeekStart;
+            if (selectedPosition < 0) {
+                selectedPosition += 7;
+            }
+            if (mShowWeekNum) {
+                selectedPosition++;
+            }
+            mSelectedLeft = selectedPosition * (mWidth - mPadding * 2) / mNumCells
+                    + mPadding;
+            mSelectedRight = (selectedPosition + 1) * (mWidth - mPadding * 2) / mNumCells
+                    + mPadding;
+        }
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), mHeight);
+    }
+
+    @Override
+    public boolean onHoverEvent(MotionEvent event) {
+        Context context = getContext();
+        // only send accessibility events if accessibility and exploration are
+        // on.
+        AccessibilityManager am = (AccessibilityManager) context
+                .getSystemService(Service.ACCESSIBILITY_SERVICE);
+        if (!am.isEnabled() || !am.isTouchExplorationEnabled()) {
+            return super.onHoverEvent(event);
+        }
+        if (event.getAction() != MotionEvent.ACTION_HOVER_EXIT) {
+            Time hover = getDayFromLocation(event.getX());
+            if (hover != null
+                    && (mLastHoverTime == null || Time.compare(hover, mLastHoverTime) != 0)) {
+                Long millis = hover.toMillis(true);
+                String date = Utils.formatDateRange(context, millis, millis,
+                        DateUtils.FORMAT_SHOW_DATE);
+                AccessibilityEvent accessEvent =
+                    AccessibilityEvent.obtain(AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED);
+                accessEvent.getText().add(date);
+                sendAccessibilityEventUnchecked(accessEvent);
+                mLastHoverTime = hover;
+            }
+        }
+        return true;
+    }
+
+    Time mLastHoverTime = null;
+}
\ No newline at end of file