MonthWeekEventsView.java revision e21674aefc9755ba519dfc5b3ff4348be4814903
182b318634af1b6594e60cfd1f2df4d3845f80587Erik/*
282b318634af1b6594e60cfd1f2df4d3845f80587Erik * Copyright (C) 2010 The Android Open Source Project
382b318634af1b6594e60cfd1f2df4d3845f80587Erik *
482b318634af1b6594e60cfd1f2df4d3845f80587Erik * Licensed under the Apache License, Version 2.0 (the "License");
582b318634af1b6594e60cfd1f2df4d3845f80587Erik * you may not use this file except in compliance with the License.
682b318634af1b6594e60cfd1f2df4d3845f80587Erik * You may obtain a copy of the License at
782b318634af1b6594e60cfd1f2df4d3845f80587Erik *
882b318634af1b6594e60cfd1f2df4d3845f80587Erik *      http://www.apache.org/licenses/LICENSE-2.0
982b318634af1b6594e60cfd1f2df4d3845f80587Erik *
1082b318634af1b6594e60cfd1f2df4d3845f80587Erik * Unless required by applicable law or agreed to in writing, software
1182b318634af1b6594e60cfd1f2df4d3845f80587Erik * distributed under the License is distributed on an "AS IS" BASIS,
1282b318634af1b6594e60cfd1f2df4d3845f80587Erik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1382b318634af1b6594e60cfd1f2df4d3845f80587Erik * See the License for the specific language governing permissions and
1482b318634af1b6594e60cfd1f2df4d3845f80587Erik * limitations under the License.
1582b318634af1b6594e60cfd1f2df4d3845f80587Erik */
1682b318634af1b6594e60cfd1f2df4d3845f80587Erik
1782b318634af1b6594e60cfd1f2df4d3845f80587Erikpackage com.android.calendar.month;
1882b318634af1b6594e60cfd1f2df4d3845f80587Erik
193553621c824afe1f3eacbe8555678005ca1264a1Erikimport com.android.calendar.Event;
203553621c824afe1f3eacbe8555678005ca1264a1Erikimport com.android.calendar.R;
2140bcd101b212c9863c3110c05a487a7ae6ebc3caErikimport com.android.calendar.Utils;
223553621c824afe1f3eacbe8555678005ca1264a1Erik
2382b318634af1b6594e60cfd1f2df4d3845f80587Erikimport android.content.Context;
243553621c824afe1f3eacbe8555678005ca1264a1Erikimport android.content.res.Configuration;
253553621c824afe1f3eacbe8555678005ca1264a1Erikimport android.content.res.Resources;
263553621c824afe1f3eacbe8555678005ca1264a1Erikimport android.graphics.Canvas;
273553621c824afe1f3eacbe8555678005ca1264a1Erikimport android.graphics.Paint;
283553621c824afe1f3eacbe8555678005ca1264a1Erikimport android.graphics.Paint.Align;
293553621c824afe1f3eacbe8555678005ca1264a1Erikimport android.graphics.Paint.Style;
3040bcd101b212c9863c3110c05a487a7ae6ebc3caErikimport android.graphics.Typeface;
3140bcd101b212c9863c3110c05a487a7ae6ebc3caErikimport android.graphics.drawable.Drawable;
3240bcd101b212c9863c3110c05a487a7ae6ebc3caErikimport android.text.TextPaint;
3340bcd101b212c9863c3110c05a487a7ae6ebc3caErikimport android.text.TextUtils;
3440bcd101b212c9863c3110c05a487a7ae6ebc3caErikimport android.text.format.DateUtils;
353553621c824afe1f3eacbe8555678005ca1264a1Erikimport android.text.format.Time;
363553621c824afe1f3eacbe8555678005ca1264a1Erikimport android.util.Log;
373553621c824afe1f3eacbe8555678005ca1264a1Erik
383553621c824afe1f3eacbe8555678005ca1264a1Erikimport java.util.ArrayList;
3940bcd101b212c9863c3110c05a487a7ae6ebc3caErikimport java.util.Formatter;
403553621c824afe1f3eacbe8555678005ca1264a1Erikimport java.util.HashMap;
4140bcd101b212c9863c3110c05a487a7ae6ebc3caErikimport java.util.Iterator;
4240bcd101b212c9863c3110c05a487a7ae6ebc3caErikimport java.util.List;
4340bcd101b212c9863c3110c05a487a7ae6ebc3caErikimport java.util.Locale;
4482b318634af1b6594e60cfd1f2df4d3845f80587Erik
45e21674aefc9755ba519dfc5b3ff4348be4814903Erikpublic class MonthWeekEventsView extends SimpleWeekView {
463553621c824afe1f3eacbe8555678005ca1264a1Erik    private static final String TAG = "MonthView";
473553621c824afe1f3eacbe8555678005ca1264a1Erik
483553621c824afe1f3eacbe8555678005ca1264a1Erik    public static final String VIEW_PARAMS_ORIENTATION = "orientation";
493553621c824afe1f3eacbe8555678005ca1264a1Erik
503553621c824afe1f3eacbe8555678005ca1264a1Erik    private static int TEXT_SIZE_MONTH_NUMBER = 32;
513553621c824afe1f3eacbe8555678005ca1264a1Erik    private static int TEXT_SIZE_EVENT = 14;
523553621c824afe1f3eacbe8555678005ca1264a1Erik    private static int TEXT_SIZE_MORE_EVENTS = 12;
533553621c824afe1f3eacbe8555678005ca1264a1Erik    private static int TEXT_SIZE_MONTH_NAME = 14;
543553621c824afe1f3eacbe8555678005ca1264a1Erik    private static int TEXT_SIZE_WEEK_NUM = 12;
553553621c824afe1f3eacbe8555678005ca1264a1Erik
563553621c824afe1f3eacbe8555678005ca1264a1Erik    private static final int DEFAULT_EDGE_SPACING = 4;
573553621c824afe1f3eacbe8555678005ca1264a1Erik    private static int PADDING_MONTH_NUMBER = 4;
583553621c824afe1f3eacbe8555678005ca1264a1Erik    private static int PADDING_WEEK_NUMBER = 16;
5940bcd101b212c9863c3110c05a487a7ae6ebc3caErik    private static int DAY_SEPARATOR_OUTER_WIDTH = 5;
6040bcd101b212c9863c3110c05a487a7ae6ebc3caErik    private static int DAY_SEPARATOR_INNER_WIDTH = 1;
6140bcd101b212c9863c3110c05a487a7ae6ebc3caErik    private static int DAY_SEPARATOR_VERTICAL_LENGTH = 53;
6240bcd101b212c9863c3110c05a487a7ae6ebc3caErik    private static int DAY_SEPARATOR_VERTICAL_LENGHT_PORTRAIT = 64;
6340bcd101b212c9863c3110c05a487a7ae6ebc3caErik
6440bcd101b212c9863c3110c05a487a7ae6ebc3caErik    private static int EVENT_X_OFFSET_LANDSCAPE = 44;
6540bcd101b212c9863c3110c05a487a7ae6ebc3caErik    private static int EVENT_Y_OFFSET_LANDSCAPE = 11;
6640bcd101b212c9863c3110c05a487a7ae6ebc3caErik    private static int EVENT_Y_OFFSET_PORTRAIT = 18;
6740bcd101b212c9863c3110c05a487a7ae6ebc3caErik    private static int EVENT_SQUARE_WIDTH = 10;
6840bcd101b212c9863c3110c05a487a7ae6ebc3caErik    private static int EVENT_SQUARE_BORDER = 1;
6940bcd101b212c9863c3110c05a487a7ae6ebc3caErik    private static int EVENT_LINE_PADDING = 4;
7040bcd101b212c9863c3110c05a487a7ae6ebc3caErik    private static int EVENT_RIGHT_PADDING = 4;
7140bcd101b212c9863c3110c05a487a7ae6ebc3caErik    private static int EVENT_BOTTOM_PADDING = 15;
723553621c824afe1f3eacbe8555678005ca1264a1Erik
733553621c824afe1f3eacbe8555678005ca1264a1Erik    private static int SPACING_WEEK_NUMBER = 19;
7440bcd101b212c9863c3110c05a487a7ae6ebc3caErik    private static boolean mScaled = false;
753553621c824afe1f3eacbe8555678005ca1264a1Erik
763553621c824afe1f3eacbe8555678005ca1264a1Erik    protected Time mToday = new Time();
773553621c824afe1f3eacbe8555678005ca1264a1Erik    protected boolean mHasToday = false;
783553621c824afe1f3eacbe8555678005ca1264a1Erik    protected int mTodayIndex = -1;
793553621c824afe1f3eacbe8555678005ca1264a1Erik    protected int mOrientation = Configuration.ORIENTATION_LANDSCAPE;
8040bcd101b212c9863c3110c05a487a7ae6ebc3caErik    protected List<ArrayList<Event>> mEvents = null;
8140bcd101b212c9863c3110c05a487a7ae6ebc3caErik    // This is for drawing the outlines around event chips and supports up to 5
8240bcd101b212c9863c3110c05a487a7ae6ebc3caErik    // events being drawn on each day
8340bcd101b212c9863c3110c05a487a7ae6ebc3caErik    protected float[] mEventOutlines = new float[5 * 4 * 4 * 7];
8440bcd101b212c9863c3110c05a487a7ae6ebc3caErik
8540bcd101b212c9863c3110c05a487a7ae6ebc3caErik    protected static StringBuilder mStringBuilder = new StringBuilder(50);
8640bcd101b212c9863c3110c05a487a7ae6ebc3caErik    // TODO recreate formatter when locale changes
8740bcd101b212c9863c3110c05a487a7ae6ebc3caErik    protected static Formatter mFormatter = new Formatter(mStringBuilder, Locale.getDefault());
883553621c824afe1f3eacbe8555678005ca1264a1Erik
893553621c824afe1f3eacbe8555678005ca1264a1Erik    protected Paint mMonthNamePaint;
9040bcd101b212c9863c3110c05a487a7ae6ebc3caErik    protected TextPaint mEventPaint;
9140bcd101b212c9863c3110c05a487a7ae6ebc3caErik    protected TextPaint mEventExtrasPaint;
923553621c824afe1f3eacbe8555678005ca1264a1Erik    protected Paint mWeekNumPaint;
933553621c824afe1f3eacbe8555678005ca1264a1Erik
9440bcd101b212c9863c3110c05a487a7ae6ebc3caErik    protected Drawable mTodayDrawable;
9540bcd101b212c9863c3110c05a487a7ae6ebc3caErik
963553621c824afe1f3eacbe8555678005ca1264a1Erik    protected int mMonthNumHeight;
973553621c824afe1f3eacbe8555678005ca1264a1Erik    protected int mEventHeight;
983553621c824afe1f3eacbe8555678005ca1264a1Erik    protected int mExtrasHeight;
993553621c824afe1f3eacbe8555678005ca1264a1Erik    protected int mWeekNumHeight;
1003553621c824afe1f3eacbe8555678005ca1264a1Erik
1013553621c824afe1f3eacbe8555678005ca1264a1Erik    protected int mMonthNumColor;
1023553621c824afe1f3eacbe8555678005ca1264a1Erik    protected int mMonthNumOtherColor;
1033553621c824afe1f3eacbe8555678005ca1264a1Erik    protected int mMonthNumTodayColor;
1043553621c824afe1f3eacbe8555678005ca1264a1Erik    protected int mMonthNameColor;
1053553621c824afe1f3eacbe8555678005ca1264a1Erik    protected int mMonthNameOtherColor;
1063553621c824afe1f3eacbe8555678005ca1264a1Erik    protected int mMonthEventColor;
1073553621c824afe1f3eacbe8555678005ca1264a1Erik    protected int mMonthEventExtraColor;
1083553621c824afe1f3eacbe8555678005ca1264a1Erik    protected int mMonthEventOtherColor;
1093553621c824afe1f3eacbe8555678005ca1264a1Erik    protected int mMonthEventExtraOtherColor;
1103553621c824afe1f3eacbe8555678005ca1264a1Erik    protected int mMonthWeekNumColor;
11182b318634af1b6594e60cfd1f2df4d3845f80587Erik
11240bcd101b212c9863c3110c05a487a7ae6ebc3caErik    protected int mEventChipOutlineColor = 0xFFFFFFFF;
11340bcd101b212c9863c3110c05a487a7ae6ebc3caErik    protected int mDaySeparatorOuterColor = 0x33FFFFFF;
11440bcd101b212c9863c3110c05a487a7ae6ebc3caErik    protected int mDaySeparatorInnerColor = 0x1A000000;
11540bcd101b212c9863c3110c05a487a7ae6ebc3caErik
11682b318634af1b6594e60cfd1f2df4d3845f80587Erik    /**
11782b318634af1b6594e60cfd1f2df4d3845f80587Erik     * @param context
11882b318634af1b6594e60cfd1f2df4d3845f80587Erik     */
11982b318634af1b6594e60cfd1f2df4d3845f80587Erik    public MonthWeekEventsView(Context context) {
12082b318634af1b6594e60cfd1f2df4d3845f80587Erik        super(context);
1213553621c824afe1f3eacbe8555678005ca1264a1Erik
1223553621c824afe1f3eacbe8555678005ca1264a1Erik        mPadding = DEFAULT_EDGE_SPACING;
12340bcd101b212c9863c3110c05a487a7ae6ebc3caErik        if (mScale != 1 && !mScaled) {
1243553621c824afe1f3eacbe8555678005ca1264a1Erik            PADDING_MONTH_NUMBER *= mScale;
1253553621c824afe1f3eacbe8555678005ca1264a1Erik            PADDING_WEEK_NUMBER *= mScale;
1263553621c824afe1f3eacbe8555678005ca1264a1Erik            SPACING_WEEK_NUMBER *= mScale;
1273553621c824afe1f3eacbe8555678005ca1264a1Erik            TEXT_SIZE_MONTH_NUMBER *= mScale;
1283553621c824afe1f3eacbe8555678005ca1264a1Erik            TEXT_SIZE_EVENT *= mScale;
1293553621c824afe1f3eacbe8555678005ca1264a1Erik            TEXT_SIZE_MORE_EVENTS *= mScale;
1303553621c824afe1f3eacbe8555678005ca1264a1Erik            TEXT_SIZE_MONTH_NAME *= mScale;
1313553621c824afe1f3eacbe8555678005ca1264a1Erik            TEXT_SIZE_WEEK_NUM *= mScale;
13240bcd101b212c9863c3110c05a487a7ae6ebc3caErik            DAY_SEPARATOR_OUTER_WIDTH *= mScale;
13340bcd101b212c9863c3110c05a487a7ae6ebc3caErik            DAY_SEPARATOR_INNER_WIDTH *= mScale;
13440bcd101b212c9863c3110c05a487a7ae6ebc3caErik            DAY_SEPARATOR_VERTICAL_LENGTH *= mScale;
13540bcd101b212c9863c3110c05a487a7ae6ebc3caErik            DAY_SEPARATOR_VERTICAL_LENGHT_PORTRAIT *= mScale;
13640bcd101b212c9863c3110c05a487a7ae6ebc3caErik            EVENT_X_OFFSET_LANDSCAPE *= mScale;
13740bcd101b212c9863c3110c05a487a7ae6ebc3caErik            EVENT_Y_OFFSET_LANDSCAPE *= mScale;
13840bcd101b212c9863c3110c05a487a7ae6ebc3caErik            EVENT_Y_OFFSET_PORTRAIT *= mScale;
13940bcd101b212c9863c3110c05a487a7ae6ebc3caErik            EVENT_SQUARE_WIDTH *= mScale;
14040bcd101b212c9863c3110c05a487a7ae6ebc3caErik            EVENT_LINE_PADDING *= mScale;
14140bcd101b212c9863c3110c05a487a7ae6ebc3caErik            EVENT_BOTTOM_PADDING *= mScale;
14240bcd101b212c9863c3110c05a487a7ae6ebc3caErik            EVENT_RIGHT_PADDING *= mScale;
1433553621c824afe1f3eacbe8555678005ca1264a1Erik            mPadding = (int) (DEFAULT_EDGE_SPACING * mScale);
14440bcd101b212c9863c3110c05a487a7ae6ebc3caErik            mScaled = true;
1453553621c824afe1f3eacbe8555678005ca1264a1Erik        }
1463553621c824afe1f3eacbe8555678005ca1264a1Erik    }
1473553621c824afe1f3eacbe8555678005ca1264a1Erik
14840bcd101b212c9863c3110c05a487a7ae6ebc3caErik    public void setEvents(List<ArrayList<Event>> sortedEvents) {
1493553621c824afe1f3eacbe8555678005ca1264a1Erik        mEvents = sortedEvents;
1503553621c824afe1f3eacbe8555678005ca1264a1Erik        if (sortedEvents == null) {
1513553621c824afe1f3eacbe8555678005ca1264a1Erik            return;
1523553621c824afe1f3eacbe8555678005ca1264a1Erik        }
1533553621c824afe1f3eacbe8555678005ca1264a1Erik        if (sortedEvents.size() != mNumDays) {
1543553621c824afe1f3eacbe8555678005ca1264a1Erik            if (Log.isLoggable(TAG, Log.ERROR)) {
1553553621c824afe1f3eacbe8555678005ca1264a1Erik                Log.wtf(TAG, "Events size must be same as days displayed: size="
1563553621c824afe1f3eacbe8555678005ca1264a1Erik                        + sortedEvents.size() + " days=" + mNumDays);
1573553621c824afe1f3eacbe8555678005ca1264a1Erik            }
1583553621c824afe1f3eacbe8555678005ca1264a1Erik            mEvents = null;
1593553621c824afe1f3eacbe8555678005ca1264a1Erik            return;
1603553621c824afe1f3eacbe8555678005ca1264a1Erik        }
1613553621c824afe1f3eacbe8555678005ca1264a1Erik    }
1623553621c824afe1f3eacbe8555678005ca1264a1Erik
1633553621c824afe1f3eacbe8555678005ca1264a1Erik    protected void loadColors(Context context) {
1643553621c824afe1f3eacbe8555678005ca1264a1Erik        Resources res = context.getResources();
1653553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthWeekNumColor = res.getColor(R.color.month_week_num_color);
1663553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthNumColor = res.getColor(R.color.month_day_number);
1673553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthNumOtherColor = res.getColor(R.color.month_day_number_other);
1683553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthNumTodayColor = res.getColor(R.color.month_today_number);
1693553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthNameColor = mMonthNumColor;
1703553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthNameOtherColor = mMonthNumOtherColor;
1713553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthEventColor = res.getColor(R.color.month_event_color);
1723553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthEventExtraColor = res.getColor(R.color.month_event_extra_color);
1733553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthEventOtherColor = res.getColor(R.color.month_event_other_color);
1743553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthEventExtraOtherColor = res.getColor(R.color.month_event_extra_other_color);
17540bcd101b212c9863c3110c05a487a7ae6ebc3caErik
17640bcd101b212c9863c3110c05a487a7ae6ebc3caErik        mTodayDrawable = res.getDrawable(R.drawable.today_blue_week_holo_light);
1773553621c824afe1f3eacbe8555678005ca1264a1Erik    }
1783553621c824afe1f3eacbe8555678005ca1264a1Erik
1793553621c824afe1f3eacbe8555678005ca1264a1Erik    /**
1803553621c824afe1f3eacbe8555678005ca1264a1Erik     * Sets up the text and style properties for painting. Override this if you
1813553621c824afe1f3eacbe8555678005ca1264a1Erik     * want to use a different paint.
1823553621c824afe1f3eacbe8555678005ca1264a1Erik     */
1833553621c824afe1f3eacbe8555678005ca1264a1Erik    @Override
1843553621c824afe1f3eacbe8555678005ca1264a1Erik    protected void setPaintProperties() {
1853553621c824afe1f3eacbe8555678005ca1264a1Erik        loadColors(mContext);
1863553621c824afe1f3eacbe8555678005ca1264a1Erik        // TODO modify paint properties depending on isMini
1873553621c824afe1f3eacbe8555678005ca1264a1Erik        p.setStyle(Style.FILL);
1883553621c824afe1f3eacbe8555678005ca1264a1Erik
1893553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthNumPaint = new Paint();
19040bcd101b212c9863c3110c05a487a7ae6ebc3caErik        mMonthNumPaint.setFakeBoldText(false);
1913553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthNumPaint.setAntiAlias(true);
1923553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthNumPaint.setTextSize(TEXT_SIZE_MONTH_NUMBER);
1933553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthNumPaint.setColor(mMonthNumColor);
1943553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthNumPaint.setStyle(Style.FILL);
1953553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthNumPaint.setTextAlign(Align.LEFT);
19640bcd101b212c9863c3110c05a487a7ae6ebc3caErik        mMonthNumPaint.setTypeface(Typeface.DEFAULT_BOLD);
1973553621c824afe1f3eacbe8555678005ca1264a1Erik
1983553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthNumHeight = (int) (-mMonthNumPaint.ascent());
1993553621c824afe1f3eacbe8555678005ca1264a1Erik
20040bcd101b212c9863c3110c05a487a7ae6ebc3caErik        mEventPaint = new TextPaint();
2013553621c824afe1f3eacbe8555678005ca1264a1Erik        mEventPaint.setFakeBoldText(false);
2023553621c824afe1f3eacbe8555678005ca1264a1Erik        mEventPaint.setAntiAlias(true);
2033553621c824afe1f3eacbe8555678005ca1264a1Erik        mEventPaint.setTextSize(TEXT_SIZE_EVENT);
2043553621c824afe1f3eacbe8555678005ca1264a1Erik        mEventPaint.setColor(mMonthEventColor);
2053553621c824afe1f3eacbe8555678005ca1264a1Erik
2063553621c824afe1f3eacbe8555678005ca1264a1Erik        mEventHeight = (int) (-mEventPaint.ascent());
2073553621c824afe1f3eacbe8555678005ca1264a1Erik
20840bcd101b212c9863c3110c05a487a7ae6ebc3caErik        mEventExtrasPaint = new TextPaint();
2093553621c824afe1f3eacbe8555678005ca1264a1Erik        mEventExtrasPaint.setFakeBoldText(false);
2103553621c824afe1f3eacbe8555678005ca1264a1Erik        mEventExtrasPaint.setAntiAlias(true);
21140bcd101b212c9863c3110c05a487a7ae6ebc3caErik        mEventExtrasPaint.setStrokeWidth(EVENT_SQUARE_BORDER);
2123553621c824afe1f3eacbe8555678005ca1264a1Erik        mEventExtrasPaint.setTextSize(TEXT_SIZE_EVENT);
2133553621c824afe1f3eacbe8555678005ca1264a1Erik        mEventExtrasPaint.setColor(mMonthEventExtraColor);
2143553621c824afe1f3eacbe8555678005ca1264a1Erik        mEventExtrasPaint.setStyle(Style.FILL);
2153553621c824afe1f3eacbe8555678005ca1264a1Erik        mEventExtrasPaint.setTextAlign(Align.LEFT);
2163553621c824afe1f3eacbe8555678005ca1264a1Erik
2173553621c824afe1f3eacbe8555678005ca1264a1Erik        mWeekNumPaint = new Paint();
2183553621c824afe1f3eacbe8555678005ca1264a1Erik        mWeekNumPaint.setFakeBoldText(false);
2193553621c824afe1f3eacbe8555678005ca1264a1Erik        mWeekNumPaint.setAntiAlias(true);
2203553621c824afe1f3eacbe8555678005ca1264a1Erik        mWeekNumPaint.setTextSize(TEXT_SIZE_WEEK_NUM);
2213553621c824afe1f3eacbe8555678005ca1264a1Erik        mWeekNumPaint.setColor(mWeekNumColor);
2223553621c824afe1f3eacbe8555678005ca1264a1Erik        mWeekNumPaint.setStyle(Style.FILL);
2233553621c824afe1f3eacbe8555678005ca1264a1Erik        mWeekNumPaint.setTextAlign(Align.RIGHT);
2243553621c824afe1f3eacbe8555678005ca1264a1Erik
2253553621c824afe1f3eacbe8555678005ca1264a1Erik        mWeekNumHeight = (int) (-mWeekNumPaint.ascent());
2263553621c824afe1f3eacbe8555678005ca1264a1Erik    }
2273553621c824afe1f3eacbe8555678005ca1264a1Erik
2283553621c824afe1f3eacbe8555678005ca1264a1Erik    @Override
2293553621c824afe1f3eacbe8555678005ca1264a1Erik    public void setWeekParams(HashMap<String, Integer> params, String tz) {
2303553621c824afe1f3eacbe8555678005ca1264a1Erik        super.setWeekParams(params, tz);
2313553621c824afe1f3eacbe8555678005ca1264a1Erik
23240bcd101b212c9863c3110c05a487a7ae6ebc3caErik        if (params.containsKey(VIEW_PARAMS_ORIENTATION)) {
23340bcd101b212c9863c3110c05a487a7ae6ebc3caErik            mOrientation = params.get(VIEW_PARAMS_ORIENTATION);
23440bcd101b212c9863c3110c05a487a7ae6ebc3caErik        }
23540bcd101b212c9863c3110c05a487a7ae6ebc3caErik
2363553621c824afe1f3eacbe8555678005ca1264a1Erik        mToday.timezone = tz;
2373553621c824afe1f3eacbe8555678005ca1264a1Erik        mToday.setToNow();
2383553621c824afe1f3eacbe8555678005ca1264a1Erik        mToday.normalize(true);
2393553621c824afe1f3eacbe8555678005ca1264a1Erik        int julianToday = Time.getJulianDay(mToday.toMillis(false), mToday.gmtoff);
2403553621c824afe1f3eacbe8555678005ca1264a1Erik        if (julianToday >= mFirstJulianDay && julianToday < mFirstJulianDay + mNumDays) {
2413553621c824afe1f3eacbe8555678005ca1264a1Erik            mHasToday = true;
2423553621c824afe1f3eacbe8555678005ca1264a1Erik            mTodayIndex = julianToday - mFirstJulianDay;
2433553621c824afe1f3eacbe8555678005ca1264a1Erik        } else {
2443553621c824afe1f3eacbe8555678005ca1264a1Erik            mHasToday = false;
2453553621c824afe1f3eacbe8555678005ca1264a1Erik            mTodayIndex = -1;
2463553621c824afe1f3eacbe8555678005ca1264a1Erik        }
2473553621c824afe1f3eacbe8555678005ca1264a1Erik    }
2483553621c824afe1f3eacbe8555678005ca1264a1Erik
2493553621c824afe1f3eacbe8555678005ca1264a1Erik    @Override
25040bcd101b212c9863c3110c05a487a7ae6ebc3caErik    protected void onDraw(Canvas canvas) {
25140bcd101b212c9863c3110c05a487a7ae6ebc3caErik        drawBackground(canvas);
25240bcd101b212c9863c3110c05a487a7ae6ebc3caErik        drawWeekNums(canvas);
25340bcd101b212c9863c3110c05a487a7ae6ebc3caErik        drawDaySeparators(canvas);
25440bcd101b212c9863c3110c05a487a7ae6ebc3caErik        drawEvents(canvas);
25540bcd101b212c9863c3110c05a487a7ae6ebc3caErik    }
25640bcd101b212c9863c3110c05a487a7ae6ebc3caErik
25740bcd101b212c9863c3110c05a487a7ae6ebc3caErik    @Override
25840bcd101b212c9863c3110c05a487a7ae6ebc3caErik    protected void drawDaySeparators(Canvas canvas) {
25940bcd101b212c9863c3110c05a487a7ae6ebc3caErik        // mDaySeparatorOuterColor
26040bcd101b212c9863c3110c05a487a7ae6ebc3caErik        float lines[] = new float[8 * 4];
26140bcd101b212c9863c3110c05a487a7ae6ebc3caErik        int count = 7 * 4;
26240bcd101b212c9863c3110c05a487a7ae6ebc3caErik        int wkNumOffset = 0;
26340bcd101b212c9863c3110c05a487a7ae6ebc3caErik        int effectiveWidth = mWidth - mPadding * 2;
26440bcd101b212c9863c3110c05a487a7ae6ebc3caErik        if (mShowWeekNum) {
26540bcd101b212c9863c3110c05a487a7ae6ebc3caErik            count += 4;
26640bcd101b212c9863c3110c05a487a7ae6ebc3caErik            wkNumOffset = 1;
26740bcd101b212c9863c3110c05a487a7ae6ebc3caErik            effectiveWidth -= SPACING_WEEK_NUMBER;
26840bcd101b212c9863c3110c05a487a7ae6ebc3caErik        }
26940bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[0] = mPadding;
27040bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[1] = DAY_SEPARATOR_OUTER_WIDTH / 2 + 1;
27140bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[2] = mWidth - mPadding;
27240bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[3] = lines[1];
27340bcd101b212c9863c3110c05a487a7ae6ebc3caErik        int y0 = DAY_SEPARATOR_OUTER_WIDTH / 2 + DAY_SEPARATOR_INNER_WIDTH;
27440bcd101b212c9863c3110c05a487a7ae6ebc3caErik        int y1;
27540bcd101b212c9863c3110c05a487a7ae6ebc3caErik        if (mOrientation == Configuration.ORIENTATION_PORTRAIT) {
27640bcd101b212c9863c3110c05a487a7ae6ebc3caErik            y1 = y0 + DAY_SEPARATOR_VERTICAL_LENGHT_PORTRAIT;
27740bcd101b212c9863c3110c05a487a7ae6ebc3caErik        } else {
27840bcd101b212c9863c3110c05a487a7ae6ebc3caErik            y1 = y0 + DAY_SEPARATOR_VERTICAL_LENGTH;
27940bcd101b212c9863c3110c05a487a7ae6ebc3caErik        }
28040bcd101b212c9863c3110c05a487a7ae6ebc3caErik
28140bcd101b212c9863c3110c05a487a7ae6ebc3caErik        for (int i = 4; i < count;) {
28240bcd101b212c9863c3110c05a487a7ae6ebc3caErik            int x = (i / 4 - wkNumOffset) * effectiveWidth / (mNumDays) + mPadding
28340bcd101b212c9863c3110c05a487a7ae6ebc3caErik                    + (SPACING_WEEK_NUMBER * wkNumOffset);
28440bcd101b212c9863c3110c05a487a7ae6ebc3caErik            lines[i++] = x;
28540bcd101b212c9863c3110c05a487a7ae6ebc3caErik            lines[i++] = y0;
28640bcd101b212c9863c3110c05a487a7ae6ebc3caErik            lines[i++] = x;
28740bcd101b212c9863c3110c05a487a7ae6ebc3caErik            lines[i++] = y1;
28840bcd101b212c9863c3110c05a487a7ae6ebc3caErik        }
28940bcd101b212c9863c3110c05a487a7ae6ebc3caErik        p.setColor(mDaySeparatorOuterColor);
29040bcd101b212c9863c3110c05a487a7ae6ebc3caErik        p.setStrokeWidth(DAY_SEPARATOR_OUTER_WIDTH);
29140bcd101b212c9863c3110c05a487a7ae6ebc3caErik        canvas.drawLines(lines, 0, count, p);
29240bcd101b212c9863c3110c05a487a7ae6ebc3caErik        p.setColor(mDaySeparatorInnerColor);
29340bcd101b212c9863c3110c05a487a7ae6ebc3caErik        p.setStrokeWidth(DAY_SEPARATOR_INNER_WIDTH);
29440bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[1]--;
29540bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[3]--;
29640bcd101b212c9863c3110c05a487a7ae6ebc3caErik        canvas.drawLines(lines, 0, count, p);
29740bcd101b212c9863c3110c05a487a7ae6ebc3caErik    }
29840bcd101b212c9863c3110c05a487a7ae6ebc3caErik
29940bcd101b212c9863c3110c05a487a7ae6ebc3caErik    @Override
3003553621c824afe1f3eacbe8555678005ca1264a1Erik    protected void drawBackground(Canvas canvas) {
30140bcd101b212c9863c3110c05a487a7ae6ebc3caErik        if (mHasToday) {
3023553621c824afe1f3eacbe8555678005ca1264a1Erik            p.setColor(mSelectedWeekBGColor);
3033553621c824afe1f3eacbe8555678005ca1264a1Erik        } else {
3043553621c824afe1f3eacbe8555678005ca1264a1Erik            return;
3053553621c824afe1f3eacbe8555678005ca1264a1Erik        }
30640bcd101b212c9863c3110c05a487a7ae6ebc3caErik        int wkNumOffset = 0;
30740bcd101b212c9863c3110c05a487a7ae6ebc3caErik        int effectiveWidth = mWidth - mPadding * 2;
30840bcd101b212c9863c3110c05a487a7ae6ebc3caErik        if (mShowWeekNum) {
30940bcd101b212c9863c3110c05a487a7ae6ebc3caErik            wkNumOffset = 1;
31040bcd101b212c9863c3110c05a487a7ae6ebc3caErik            effectiveWidth -= SPACING_WEEK_NUMBER;
31140bcd101b212c9863c3110c05a487a7ae6ebc3caErik        }
31240bcd101b212c9863c3110c05a487a7ae6ebc3caErik        r.top = DAY_SEPARATOR_OUTER_WIDTH;
3133553621c824afe1f3eacbe8555678005ca1264a1Erik        r.bottom = mHeight;
31440bcd101b212c9863c3110c05a487a7ae6ebc3caErik        r.left = (mTodayIndex) * effectiveWidth / (mNumDays) + mPadding
31540bcd101b212c9863c3110c05a487a7ae6ebc3caErik                + (SPACING_WEEK_NUMBER * wkNumOffset) + DAY_SEPARATOR_OUTER_WIDTH / 2;
31640bcd101b212c9863c3110c05a487a7ae6ebc3caErik        r.right = (mTodayIndex + 1) * effectiveWidth / (mNumDays) + mPadding
31740bcd101b212c9863c3110c05a487a7ae6ebc3caErik                + (SPACING_WEEK_NUMBER * wkNumOffset) - DAY_SEPARATOR_OUTER_WIDTH / 2 - 1;
31840bcd101b212c9863c3110c05a487a7ae6ebc3caErik        mTodayDrawable.setBounds(r);
31940bcd101b212c9863c3110c05a487a7ae6ebc3caErik        mTodayDrawable.draw(canvas);
3203553621c824afe1f3eacbe8555678005ca1264a1Erik    }
3213553621c824afe1f3eacbe8555678005ca1264a1Erik
3223553621c824afe1f3eacbe8555678005ca1264a1Erik    @Override
3233553621c824afe1f3eacbe8555678005ca1264a1Erik    protected void drawWeekNums(Canvas canvas) {
3243553621c824afe1f3eacbe8555678005ca1264a1Erik        int y;// = (int) ((mHeight + textHeight) / 2);
3253553621c824afe1f3eacbe8555678005ca1264a1Erik
3263553621c824afe1f3eacbe8555678005ca1264a1Erik        int i = 0;
3273553621c824afe1f3eacbe8555678005ca1264a1Erik        int wkNumOffset = 0;
3283553621c824afe1f3eacbe8555678005ca1264a1Erik        int effectiveWidth = mWidth - mPadding * 2;
3293553621c824afe1f3eacbe8555678005ca1264a1Erik        int todayIndex = mTodayIndex;
3303553621c824afe1f3eacbe8555678005ca1264a1Erik        if (mShowWeekNum) {
3313553621c824afe1f3eacbe8555678005ca1264a1Erik            int x = PADDING_WEEK_NUMBER + mPadding;
3323553621c824afe1f3eacbe8555678005ca1264a1Erik            y = mWeekNumHeight + PADDING_MONTH_NUMBER;
3333553621c824afe1f3eacbe8555678005ca1264a1Erik            canvas.drawText(mDayNumbers[0], x, y, mWeekNumPaint);
3343553621c824afe1f3eacbe8555678005ca1264a1Erik            i++;
3353553621c824afe1f3eacbe8555678005ca1264a1Erik            wkNumOffset = 1;
3363553621c824afe1f3eacbe8555678005ca1264a1Erik            effectiveWidth -= SPACING_WEEK_NUMBER;
3373553621c824afe1f3eacbe8555678005ca1264a1Erik            todayIndex++;
3383553621c824afe1f3eacbe8555678005ca1264a1Erik        }
3393553621c824afe1f3eacbe8555678005ca1264a1Erik
3403553621c824afe1f3eacbe8555678005ca1264a1Erik        y = (mMonthNumHeight + PADDING_MONTH_NUMBER);
3413553621c824afe1f3eacbe8555678005ca1264a1Erik
3423553621c824afe1f3eacbe8555678005ca1264a1Erik        boolean isFocusMonth = mFocusDay[i];
3433553621c824afe1f3eacbe8555678005ca1264a1Erik        mMonthNumPaint.setColor(isFocusMonth ? mMonthNumColor : mMonthNumOtherColor);
3443553621c824afe1f3eacbe8555678005ca1264a1Erik        for (; i < mNumCells; i++) {
3453553621c824afe1f3eacbe8555678005ca1264a1Erik            if (mHasToday && todayIndex == i) {
3463553621c824afe1f3eacbe8555678005ca1264a1Erik                mMonthNumPaint.setColor(mMonthNumTodayColor);
3473553621c824afe1f3eacbe8555678005ca1264a1Erik                if (i + 1 < mNumCells) {
3483553621c824afe1f3eacbe8555678005ca1264a1Erik                    // Make sure the color will be set back on the next
3493553621c824afe1f3eacbe8555678005ca1264a1Erik                    // iteration
3503553621c824afe1f3eacbe8555678005ca1264a1Erik                    isFocusMonth = !mFocusDay[i + 1];
3513553621c824afe1f3eacbe8555678005ca1264a1Erik                }
3523553621c824afe1f3eacbe8555678005ca1264a1Erik            } else if (mFocusDay[i] != isFocusMonth) {
3533553621c824afe1f3eacbe8555678005ca1264a1Erik                isFocusMonth = mFocusDay[i];
3543553621c824afe1f3eacbe8555678005ca1264a1Erik                mMonthNumPaint.setColor(isFocusMonth ? mMonthNumColor : mMonthNumOtherColor);
3553553621c824afe1f3eacbe8555678005ca1264a1Erik            }
3563553621c824afe1f3eacbe8555678005ca1264a1Erik            int x = (i - wkNumOffset) * effectiveWidth / (mNumDays) + mPadding
3573553621c824afe1f3eacbe8555678005ca1264a1Erik                    + PADDING_MONTH_NUMBER + (SPACING_WEEK_NUMBER * wkNumOffset);
3583553621c824afe1f3eacbe8555678005ca1264a1Erik            canvas.drawText(mDayNumbers[i], x, y, mMonthNumPaint);
3593553621c824afe1f3eacbe8555678005ca1264a1Erik
3603553621c824afe1f3eacbe8555678005ca1264a1Erik        }
3613553621c824afe1f3eacbe8555678005ca1264a1Erik    }
3623553621c824afe1f3eacbe8555678005ca1264a1Erik
36340bcd101b212c9863c3110c05a487a7ae6ebc3caErik    protected void drawEvents(Canvas canvas) {
36440bcd101b212c9863c3110c05a487a7ae6ebc3caErik        if (mEvents == null) {
36540bcd101b212c9863c3110c05a487a7ae6ebc3caErik            return;
36640bcd101b212c9863c3110c05a487a7ae6ebc3caErik        }
36740bcd101b212c9863c3110c05a487a7ae6ebc3caErik        int wkNumOffset = 0;
36840bcd101b212c9863c3110c05a487a7ae6ebc3caErik        int effectiveWidth = mWidth - mPadding * 2;
36940bcd101b212c9863c3110c05a487a7ae6ebc3caErik        if (mShowWeekNum) {
37040bcd101b212c9863c3110c05a487a7ae6ebc3caErik            wkNumOffset = 1;
37140bcd101b212c9863c3110c05a487a7ae6ebc3caErik            effectiveWidth -= SPACING_WEEK_NUMBER;
37240bcd101b212c9863c3110c05a487a7ae6ebc3caErik        }
37340bcd101b212c9863c3110c05a487a7ae6ebc3caErik
37440bcd101b212c9863c3110c05a487a7ae6ebc3caErik        int day = -1;
37540bcd101b212c9863c3110c05a487a7ae6ebc3caErik        int outlineCount = 0;
37640bcd101b212c9863c3110c05a487a7ae6ebc3caErik        for (ArrayList<Event> eventDay : mEvents) {
37740bcd101b212c9863c3110c05a487a7ae6ebc3caErik            day++;
37840bcd101b212c9863c3110c05a487a7ae6ebc3caErik            if (eventDay == null || eventDay.size() == 0) {
37940bcd101b212c9863c3110c05a487a7ae6ebc3caErik                continue;
38040bcd101b212c9863c3110c05a487a7ae6ebc3caErik            }
38140bcd101b212c9863c3110c05a487a7ae6ebc3caErik            int ySquare;
38240bcd101b212c9863c3110c05a487a7ae6ebc3caErik            int xSquare = day * effectiveWidth / (mNumDays) + mPadding
38340bcd101b212c9863c3110c05a487a7ae6ebc3caErik                    + (SPACING_WEEK_NUMBER * wkNumOffset);
38440bcd101b212c9863c3110c05a487a7ae6ebc3caErik            if (mOrientation == Configuration.ORIENTATION_PORTRAIT) {
38540bcd101b212c9863c3110c05a487a7ae6ebc3caErik                ySquare = EVENT_Y_OFFSET_PORTRAIT + mMonthNumHeight + PADDING_MONTH_NUMBER;
38640bcd101b212c9863c3110c05a487a7ae6ebc3caErik                xSquare += PADDING_MONTH_NUMBER + 1;
38740bcd101b212c9863c3110c05a487a7ae6ebc3caErik            } else {
38840bcd101b212c9863c3110c05a487a7ae6ebc3caErik                ySquare = EVENT_Y_OFFSET_LANDSCAPE;
38940bcd101b212c9863c3110c05a487a7ae6ebc3caErik                xSquare += EVENT_X_OFFSET_LANDSCAPE;
39040bcd101b212c9863c3110c05a487a7ae6ebc3caErik            }
39140bcd101b212c9863c3110c05a487a7ae6ebc3caErik            int rightEdge = (day + 1) * effectiveWidth / (mNumDays) + mPadding
39240bcd101b212c9863c3110c05a487a7ae6ebc3caErik                    + (SPACING_WEEK_NUMBER * wkNumOffset) - EVENT_RIGHT_PADDING;
39340bcd101b212c9863c3110c05a487a7ae6ebc3caErik            int eventCount = 0;
39440bcd101b212c9863c3110c05a487a7ae6ebc3caErik            Iterator<Event> iter = eventDay.iterator();
39540bcd101b212c9863c3110c05a487a7ae6ebc3caErik            while (iter.hasNext()) {
39640bcd101b212c9863c3110c05a487a7ae6ebc3caErik                Event event = iter.next();
39740bcd101b212c9863c3110c05a487a7ae6ebc3caErik                int newY = drawEvent(canvas, event, xSquare, ySquare, rightEdge, iter.hasNext());
39840bcd101b212c9863c3110c05a487a7ae6ebc3caErik                if (newY == ySquare) {
39940bcd101b212c9863c3110c05a487a7ae6ebc3caErik                    break;
40040bcd101b212c9863c3110c05a487a7ae6ebc3caErik                }
40140bcd101b212c9863c3110c05a487a7ae6ebc3caErik                outlineCount = addChipOutline(mEventOutlines, outlineCount, xSquare, ySquare);
40240bcd101b212c9863c3110c05a487a7ae6ebc3caErik                eventCount++;
40340bcd101b212c9863c3110c05a487a7ae6ebc3caErik                ySquare = newY;
40440bcd101b212c9863c3110c05a487a7ae6ebc3caErik            }
40540bcd101b212c9863c3110c05a487a7ae6ebc3caErik
40640bcd101b212c9863c3110c05a487a7ae6ebc3caErik            int remaining = eventDay.size() - eventCount;
40740bcd101b212c9863c3110c05a487a7ae6ebc3caErik            if (remaining > 0) {
40840bcd101b212c9863c3110c05a487a7ae6ebc3caErik                drawMoreEvents(canvas, remaining, xSquare);
40940bcd101b212c9863c3110c05a487a7ae6ebc3caErik            }
41040bcd101b212c9863c3110c05a487a7ae6ebc3caErik        }
41140bcd101b212c9863c3110c05a487a7ae6ebc3caErik        if (outlineCount > 0) {
41240bcd101b212c9863c3110c05a487a7ae6ebc3caErik            p.setColor(mEventChipOutlineColor);
41340bcd101b212c9863c3110c05a487a7ae6ebc3caErik            p.setStrokeWidth(EVENT_SQUARE_BORDER);
41440bcd101b212c9863c3110c05a487a7ae6ebc3caErik            canvas.drawLines(mEventOutlines, 0, outlineCount, p);
41540bcd101b212c9863c3110c05a487a7ae6ebc3caErik        }
41640bcd101b212c9863c3110c05a487a7ae6ebc3caErik    }
41740bcd101b212c9863c3110c05a487a7ae6ebc3caErik
41840bcd101b212c9863c3110c05a487a7ae6ebc3caErik    protected int addChipOutline(float[] lines, int count, int x, int y) {
41940bcd101b212c9863c3110c05a487a7ae6ebc3caErik        // top of box
42040bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[count++] = x;
42140bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[count++] = y;
42240bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[count++] = x + EVENT_SQUARE_WIDTH;
42340bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[count++] = y;
42440bcd101b212c9863c3110c05a487a7ae6ebc3caErik        // right side of box
42540bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[count++] = x + EVENT_SQUARE_WIDTH;
42640bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[count++] = y;
42740bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[count++] = x + EVENT_SQUARE_WIDTH;
42840bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[count++] = y + EVENT_SQUARE_WIDTH;
42940bcd101b212c9863c3110c05a487a7ae6ebc3caErik        // left side of box
43040bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[count++] = x;
43140bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[count++] = y;
43240bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[count++] = x;
43340bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[count++] = y + EVENT_SQUARE_WIDTH + 1;
43440bcd101b212c9863c3110c05a487a7ae6ebc3caErik        // bottom of box
43540bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[count++] = x;
43640bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[count++] = y + EVENT_SQUARE_WIDTH;
43740bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[count++] = x + EVENT_SQUARE_WIDTH;
43840bcd101b212c9863c3110c05a487a7ae6ebc3caErik        lines[count++] = y + EVENT_SQUARE_WIDTH;
43940bcd101b212c9863c3110c05a487a7ae6ebc3caErik
44040bcd101b212c9863c3110c05a487a7ae6ebc3caErik        return count;
44140bcd101b212c9863c3110c05a487a7ae6ebc3caErik    }
44240bcd101b212c9863c3110c05a487a7ae6ebc3caErik
44340bcd101b212c9863c3110c05a487a7ae6ebc3caErik    /**
44440bcd101b212c9863c3110c05a487a7ae6ebc3caErik     * Attempts to draw the given event. Returns the y for the next event or the
44540bcd101b212c9863c3110c05a487a7ae6ebc3caErik     * original y if the event will not fit. An event is considered to not fit
44640bcd101b212c9863c3110c05a487a7ae6ebc3caErik     * if the event and its extras won't fit or if there are more events and the
44740bcd101b212c9863c3110c05a487a7ae6ebc3caErik     * more events line would not fit after drawing this event.
44840bcd101b212c9863c3110c05a487a7ae6ebc3caErik     *
44940bcd101b212c9863c3110c05a487a7ae6ebc3caErik     * @param event the event to draw
45040bcd101b212c9863c3110c05a487a7ae6ebc3caErik     * @param x the top left corner for this event's color chip
45140bcd101b212c9863c3110c05a487a7ae6ebc3caErik     * @param y the top left corner for this event's color chip
45240bcd101b212c9863c3110c05a487a7ae6ebc3caErik     * @return the y for the next event or the original y if it won't fit
45340bcd101b212c9863c3110c05a487a7ae6ebc3caErik     */
45440bcd101b212c9863c3110c05a487a7ae6ebc3caErik    protected int drawEvent(
45540bcd101b212c9863c3110c05a487a7ae6ebc3caErik            Canvas canvas, Event event, int x, int y, int rightEdge, boolean moreEvents) {
45640bcd101b212c9863c3110c05a487a7ae6ebc3caErik        int requiredSpace = EVENT_LINE_PADDING + mEventHeight;
45740bcd101b212c9863c3110c05a487a7ae6ebc3caErik        int multiplier = 1;
45840bcd101b212c9863c3110c05a487a7ae6ebc3caErik        if (moreEvents) {
45940bcd101b212c9863c3110c05a487a7ae6ebc3caErik            multiplier++;
46040bcd101b212c9863c3110c05a487a7ae6ebc3caErik        }
46140bcd101b212c9863c3110c05a487a7ae6ebc3caErik        if (!event.allDay) {
46240bcd101b212c9863c3110c05a487a7ae6ebc3caErik            multiplier++;
46340bcd101b212c9863c3110c05a487a7ae6ebc3caErik        }
46440bcd101b212c9863c3110c05a487a7ae6ebc3caErik        requiredSpace *= multiplier;
46540bcd101b212c9863c3110c05a487a7ae6ebc3caErik        if (requiredSpace + y >= mHeight - EVENT_BOTTOM_PADDING) {
46640bcd101b212c9863c3110c05a487a7ae6ebc3caErik            // Not enough space, return
46740bcd101b212c9863c3110c05a487a7ae6ebc3caErik            return y;
46840bcd101b212c9863c3110c05a487a7ae6ebc3caErik        }
46940bcd101b212c9863c3110c05a487a7ae6ebc3caErik        r.left = x;
47040bcd101b212c9863c3110c05a487a7ae6ebc3caErik        r.right = x + EVENT_SQUARE_WIDTH;
47140bcd101b212c9863c3110c05a487a7ae6ebc3caErik        r.top = y;
47240bcd101b212c9863c3110c05a487a7ae6ebc3caErik        r.bottom = y + EVENT_SQUARE_WIDTH;
47340bcd101b212c9863c3110c05a487a7ae6ebc3caErik        p.setColor(event.color);
47440bcd101b212c9863c3110c05a487a7ae6ebc3caErik        canvas.drawRect(r, p);
47540bcd101b212c9863c3110c05a487a7ae6ebc3caErik
47640bcd101b212c9863c3110c05a487a7ae6ebc3caErik        int textX = x + EVENT_SQUARE_WIDTH + EVENT_LINE_PADDING;
47740bcd101b212c9863c3110c05a487a7ae6ebc3caErik        int textY = y + mEventHeight - EVENT_LINE_PADDING / 2;
47840bcd101b212c9863c3110c05a487a7ae6ebc3caErik        float avail = rightEdge - textX;
47940bcd101b212c9863c3110c05a487a7ae6ebc3caErik        CharSequence text = TextUtils.ellipsize(
48040bcd101b212c9863c3110c05a487a7ae6ebc3caErik                event.title, mEventPaint, avail, TextUtils.TruncateAt.END);
48140bcd101b212c9863c3110c05a487a7ae6ebc3caErik        canvas.drawText(text.toString(), textX, textY, mEventPaint);
48240bcd101b212c9863c3110c05a487a7ae6ebc3caErik        if (!event.allDay) {
48340bcd101b212c9863c3110c05a487a7ae6ebc3caErik            textY += mEventHeight + EVENT_LINE_PADDING;
48440bcd101b212c9863c3110c05a487a7ae6ebc3caErik            mStringBuilder.setLength(0);
48540bcd101b212c9863c3110c05a487a7ae6ebc3caErik            text = DateUtils.formatDateRange(mContext, mFormatter, event.startMillis,
48640bcd101b212c9863c3110c05a487a7ae6ebc3caErik                    event.endMillis, DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_ABBREV_ALL,
48740bcd101b212c9863c3110c05a487a7ae6ebc3caErik                    Utils.getTimeZone(mContext, null)).toString();
48840bcd101b212c9863c3110c05a487a7ae6ebc3caErik            text = TextUtils.ellipsize(text, mEventExtrasPaint, avail, TextUtils.TruncateAt.END);
48940bcd101b212c9863c3110c05a487a7ae6ebc3caErik            canvas.drawText(text.toString(), textX, textY, mEventExtrasPaint);
49040bcd101b212c9863c3110c05a487a7ae6ebc3caErik        }
49140bcd101b212c9863c3110c05a487a7ae6ebc3caErik
49240bcd101b212c9863c3110c05a487a7ae6ebc3caErik        return textY + EVENT_LINE_PADDING;
49340bcd101b212c9863c3110c05a487a7ae6ebc3caErik    }
49440bcd101b212c9863c3110c05a487a7ae6ebc3caErik
49540bcd101b212c9863c3110c05a487a7ae6ebc3caErik    protected void drawMoreEvents(Canvas canvas, int remainingEvents, int x) {
49640bcd101b212c9863c3110c05a487a7ae6ebc3caErik        float[] lines = new float[4 * 4];
49740bcd101b212c9863c3110c05a487a7ae6ebc3caErik        int y = mHeight - EVENT_BOTTOM_PADDING + EVENT_LINE_PADDING / 2 - mEventHeight;
49840bcd101b212c9863c3110c05a487a7ae6ebc3caErik        addChipOutline(lines, 0, x, y);
49940bcd101b212c9863c3110c05a487a7ae6ebc3caErik        canvas.drawLines(lines, mEventExtrasPaint);
50040bcd101b212c9863c3110c05a487a7ae6ebc3caErik        String text = mContext.getResources().getQuantityString(
50140bcd101b212c9863c3110c05a487a7ae6ebc3caErik                R.plurals.month_more_events, remainingEvents);
50240bcd101b212c9863c3110c05a487a7ae6ebc3caErik        y = mHeight - EVENT_BOTTOM_PADDING;
50340bcd101b212c9863c3110c05a487a7ae6ebc3caErik        x += EVENT_SQUARE_WIDTH + EVENT_LINE_PADDING;
50440bcd101b212c9863c3110c05a487a7ae6ebc3caErik        mEventExtrasPaint.setFakeBoldText(true);
50540bcd101b212c9863c3110c05a487a7ae6ebc3caErik        canvas.drawText(String.format(text, remainingEvents), x, y, mEventExtrasPaint);
50640bcd101b212c9863c3110c05a487a7ae6ebc3caErik        mEventExtrasPaint.setFakeBoldText(false);
50740bcd101b212c9863c3110c05a487a7ae6ebc3caErik    }
50840bcd101b212c9863c3110c05a487a7ae6ebc3caErik
5093553621c824afe1f3eacbe8555678005ca1264a1Erik    @Override
5103553621c824afe1f3eacbe8555678005ca1264a1Erik    protected void updateSelectionPositions() {
5113553621c824afe1f3eacbe8555678005ca1264a1Erik        if (mHasSelectedDay) {
5123553621c824afe1f3eacbe8555678005ca1264a1Erik            int selectedPosition = mSelectedDay - mWeekStart;
5133553621c824afe1f3eacbe8555678005ca1264a1Erik            if (selectedPosition < 0) {
5143553621c824afe1f3eacbe8555678005ca1264a1Erik                selectedPosition += 7;
5153553621c824afe1f3eacbe8555678005ca1264a1Erik            }
5163553621c824afe1f3eacbe8555678005ca1264a1Erik            int effectiveWidth = mWidth - mPadding * 2;
5173553621c824afe1f3eacbe8555678005ca1264a1Erik            if (mShowWeekNum) {
5183553621c824afe1f3eacbe8555678005ca1264a1Erik                effectiveWidth -= SPACING_WEEK_NUMBER;
5193553621c824afe1f3eacbe8555678005ca1264a1Erik            }
5203553621c824afe1f3eacbe8555678005ca1264a1Erik            mSelectedLeft = selectedPosition * effectiveWidth / mNumDays + mPadding;
5213553621c824afe1f3eacbe8555678005ca1264a1Erik            mSelectedRight = (selectedPosition + 1) * effectiveWidth / mNumDays + mPadding;
5223553621c824afe1f3eacbe8555678005ca1264a1Erik            if (mShowWeekNum) {
5233553621c824afe1f3eacbe8555678005ca1264a1Erik                mSelectedLeft += SPACING_WEEK_NUMBER;
5243553621c824afe1f3eacbe8555678005ca1264a1Erik                mSelectedRight += SPACING_WEEK_NUMBER;
5253553621c824afe1f3eacbe8555678005ca1264a1Erik            }
5263553621c824afe1f3eacbe8555678005ca1264a1Erik        }
5273553621c824afe1f3eacbe8555678005ca1264a1Erik    }
5283553621c824afe1f3eacbe8555678005ca1264a1Erik
5293553621c824afe1f3eacbe8555678005ca1264a1Erik    @Override
5303553621c824afe1f3eacbe8555678005ca1264a1Erik    public Time getDayFromLocation(float x) {
5313553621c824afe1f3eacbe8555678005ca1264a1Erik        int dayStart = mShowWeekNum ? SPACING_WEEK_NUMBER + mPadding : mPadding;
5323553621c824afe1f3eacbe8555678005ca1264a1Erik        if (x < dayStart || x > mWidth - mPadding) {
5333553621c824afe1f3eacbe8555678005ca1264a1Erik            return null;
5343553621c824afe1f3eacbe8555678005ca1264a1Erik        }
5353553621c824afe1f3eacbe8555678005ca1264a1Erik        // Selection is (x - start) / (pixels/day) == (x -s) * day / pixels
5363553621c824afe1f3eacbe8555678005ca1264a1Erik        int dayPosition = (int) ((x - dayStart) * mNumDays / (mWidth - dayStart - mPadding));
5373553621c824afe1f3eacbe8555678005ca1264a1Erik        int day = mFirstJulianDay + dayPosition;
5383553621c824afe1f3eacbe8555678005ca1264a1Erik
5393553621c824afe1f3eacbe8555678005ca1264a1Erik        Time time = new Time(mTimeZone);
5403553621c824afe1f3eacbe8555678005ca1264a1Erik        if (mWeek == 0) {
5413553621c824afe1f3eacbe8555678005ca1264a1Erik            // This week is weird...
5423553621c824afe1f3eacbe8555678005ca1264a1Erik            if (day < Time.EPOCH_JULIAN_DAY) {
5433553621c824afe1f3eacbe8555678005ca1264a1Erik                day++;
5443553621c824afe1f3eacbe8555678005ca1264a1Erik            } else if (day == Time.EPOCH_JULIAN_DAY) {
5453553621c824afe1f3eacbe8555678005ca1264a1Erik                time.set(1, 0, 1970);
5463553621c824afe1f3eacbe8555678005ca1264a1Erik                time.normalize(true);
5473553621c824afe1f3eacbe8555678005ca1264a1Erik                return time;
5483553621c824afe1f3eacbe8555678005ca1264a1Erik            }
5493553621c824afe1f3eacbe8555678005ca1264a1Erik        }
5503553621c824afe1f3eacbe8555678005ca1264a1Erik
5513553621c824afe1f3eacbe8555678005ca1264a1Erik        time.setJulianDay(day);
5523553621c824afe1f3eacbe8555678005ca1264a1Erik        return time;
55382b318634af1b6594e60cfd1f2df4d3845f80587Erik    }
55482b318634af1b6594e60cfd1f2df4d3845f80587Erik
55582b318634af1b6594e60cfd1f2df4d3845f80587Erik}
556