1a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson/*
2a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson * Copyright (C) 2012 The Android Open Source Project
3a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson *
4a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson * Licensed under the Apache License, Version 2.0 (the "License");
5a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson * you may not use this file except in compliance with the License.
6a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson * You may obtain a copy of the License at
7a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson *
8a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson *      http://www.apache.org/licenses/LICENSE-2.0
9a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson *
10a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson * Unless required by applicable law or agreed to in writing, software
11a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson * distributed under the License is distributed on an "AS IS" BASIS,
12a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson * See the License for the specific language governing permissions and
14a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson * limitations under the License.
15a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson */
16a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
17a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelsonpackage com.android.calendar.month;
18a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
19a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelsonimport android.content.Context;
20a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelsonimport android.graphics.Rect;
21a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelsonimport android.os.SystemClock;
22a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelsonimport android.text.format.Time;
23a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelsonimport android.util.AttributeSet;
24a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelsonimport android.view.MotionEvent;
25a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelsonimport android.view.VelocityTracker;
26a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelsonimport android.view.View;
27a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelsonimport android.widget.ListView;
28a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
29a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelsonimport com.android.calendar.Utils;
30a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
31a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelsonpublic class MonthListView extends ListView {
32a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
33a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    private static final String TAG = "MonthListView";
34a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    VelocityTracker mTracker;
35a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    private static float mScale = 0;
36a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
37a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    // These define the behavior of the fling. Below MIN_VELOCITY_FOR_FLING, do the system fling
38a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    // behavior. Between MIN_VELOCITY_FOR_FLING and MULTIPLE_MONTH_VELOCITY_THRESHOLD, do one month
39a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    // fling. Above MULTIPLE_MONTH_VELOCITY_THRESHOLD, do multiple month flings according to the
40a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    // fling strength. When doing multiple month fling, the velocity is reduced by this threshold
41a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    // to prevent moving from one month fling to 4 months and above flings.
42a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    private static int MIN_VELOCITY_FOR_FLING = 1500;
43a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    private static int MULTIPLE_MONTH_VELOCITY_THRESHOLD = 2000;
44a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    private static int FLING_VELOCITY_DIVIDER = 500;
45a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    private static int FLING_TIME = 1000;
46a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
47a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    // disposable variable used for time calculations
48a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    protected Time mTempTime;
49a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    private long mDownActionTime;
50a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    private final Rect mFirstViewRect = new Rect();
51a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
52a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    Context mListContext;
53a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
54a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    // Updates the time zone when it changes
55a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    private final Runnable mTimezoneUpdater = new Runnable() {
56a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        @Override
57a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        public void run() {
58a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            if (mTempTime != null && mListContext != null) {
59a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                mTempTime.timezone =
60a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                        Utils.getTimeZone(mListContext, mTimezoneUpdater);
61a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            }
62a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        }
63a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    };
64a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
65a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    public MonthListView(Context context) {
66a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        super(context);
67a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        init(context);
68a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    }
69a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
70a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    public MonthListView(Context context, AttributeSet attrs, int defStyle) {
71a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        super(context, attrs, defStyle);
72a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        init(context);
73a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    }
74a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
75a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    public MonthListView(Context context, AttributeSet attrs) {
76a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        super(context, attrs);
77a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        init(context);
78a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    }
79a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
80a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    private void init(Context c) {
81a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        mListContext = c;
82a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        mTracker  = VelocityTracker.obtain();
83a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        mTempTime = new Time(Utils.getTimeZone(c,mTimezoneUpdater));
84a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        if (mScale == 0) {
85a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            mScale = c.getResources().getDisplayMetrics().density;
86a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            if (mScale != 1) {
87a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                MIN_VELOCITY_FOR_FLING *= mScale;
88a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                MULTIPLE_MONTH_VELOCITY_THRESHOLD *= mScale;
89a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                FLING_VELOCITY_DIVIDER *= mScale;
90a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            }
91a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        }
92a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    }
93a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
94a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    @Override
95a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    public boolean onTouchEvent(MotionEvent ev) {
96a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        return processEvent(ev) || super.onTouchEvent(ev);
97a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    }
98a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
99a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    @Override
100a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    public boolean onInterceptTouchEvent(MotionEvent ev) {
101a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        return processEvent(ev) || super.onInterceptTouchEvent(ev);
102a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    }
103a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
104a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    private boolean processEvent (MotionEvent ev) {
105a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        switch (ev.getAction() & MotionEvent.ACTION_MASK) {
106a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            // Since doFling sends a cancel, make sure not to process it.
107a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            case MotionEvent.ACTION_CANCEL:
108a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                return false;
109a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            // Start tracking movement velocity
110a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            case MotionEvent.ACTION_DOWN:
111a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                mTracker.clear();
112a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                mDownActionTime = SystemClock.uptimeMillis();
113a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                break;
114a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            // Accumulate velocity and do a custom fling when above threshold
115a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            case MotionEvent.ACTION_UP:
116a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                mTracker.addMovement(ev);
117a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                mTracker.computeCurrentVelocity(1000);    // in pixels per second
118a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                float vel =  mTracker.getYVelocity ();
119a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                if (Math.abs(vel) > MIN_VELOCITY_FOR_FLING) {
120a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                    doFling(vel);
121a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                    return true;
122a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                }
123a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                break;
124a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            default:
125a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                 mTracker.addMovement(ev);
126a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                 break;
127a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        }
128a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        return false;
129a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    }
130a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
131a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    // Do a "snap to start of month" fling
132a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    private void doFling(float velocityY) {
133a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
134a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        // Stop the list-view movement and take over
135a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        MotionEvent cancelEvent = MotionEvent.obtain(mDownActionTime,  SystemClock.uptimeMillis(),
136a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                MotionEvent.ACTION_CANCEL, 0, 0, 0);
137a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        onTouchEvent(cancelEvent);
138a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
139a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        // Below the threshold, fling one month. Above the threshold , fling
140a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        // according to the speed of the fling.
141a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        int monthsToJump;
142a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        if (Math.abs(velocityY) < MULTIPLE_MONTH_VELOCITY_THRESHOLD) {
143a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            if (velocityY < 0) {
144a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                monthsToJump = 1;
145a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            } else {
146a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                // value here is zero and not -1 since by the time the fling is
147a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                // detected the list moved back one month.
148a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                monthsToJump = 0;
149a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            }
150a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        } else {
151a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            if (velocityY < 0) {
152a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                monthsToJump = 1 - (int) ((velocityY + MULTIPLE_MONTH_VELOCITY_THRESHOLD)
153a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                        / FLING_VELOCITY_DIVIDER);
154a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            } else {
155a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                monthsToJump = -(int) ((velocityY - MULTIPLE_MONTH_VELOCITY_THRESHOLD)
156a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                        / FLING_VELOCITY_DIVIDER);
157a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            }
158a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        }
159a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
160a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        // Get the day at the top right corner
161a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        int day = getUpperRightJulianDay();
162a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        // Get the day of the first day of the next/previous month
163a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        // (according to scroll direction)
164a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        mTempTime.setJulianDay(day);
165a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        mTempTime.monthDay = 1;
166a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        mTempTime.month += monthsToJump;
167a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        long timeInMillis = mTempTime.normalize(false);
168a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        // Since each view is 7 days, round the target day up to make sure the
169a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        // scroll will be  at least one view.
170a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        int scrollToDay = Time.getJulianDay(timeInMillis, mTempTime.gmtoff)
171a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                + ((monthsToJump > 0) ? 6 : 0);
172a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
173a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        // Since all views have the same height, scroll by pixels instead of
174a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        // "to position".
175a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        // Compensate for the top view offset from the top.
176a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        View firstView = getChildAt(0);
177a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        int firstViewHeight = firstView.getHeight();
178a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        // Get visible part length
179a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        firstView.getLocalVisibleRect(mFirstViewRect);
180a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        int topViewVisiblePart = mFirstViewRect.bottom - mFirstViewRect.top;
181a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        int viewsToFling = (scrollToDay - day) / 7 - ((monthsToJump <= 0) ? 1 : 0);
182a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        int offset = (viewsToFling > 0) ? -(firstViewHeight - topViewVisiblePart
183a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                + SimpleDayPickerFragment.LIST_TOP_OFFSET) : (topViewVisiblePart
184a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson                - SimpleDayPickerFragment.LIST_TOP_OFFSET);
185a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        // Fling
186a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        smoothScrollBy(viewsToFling * firstViewHeight + offset, FLING_TIME);
187a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    }
188a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson
189a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    // Returns the julian day of the day in the upper right corner
190a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    private int getUpperRightJulianDay() {
191a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        SimpleWeekView child = (SimpleWeekView) getChildAt(0);
192a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        if (child == null) {
193a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson            return -1;
194a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        }
195a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson        return child.getFirstJulianDay() + SimpleDayPickerFragment.DAYS_PER_WEEK - 1;
196a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson    }
197a8133aacf45345c83fc02e2a6ddc86e62153eca8Isaac Katzenelson}
198