CalendarViewAdapter.java revision 8135093480db642734fb40d9627325bf9e97a8c9
19a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson/*
29a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson * Copyright (C) 2011 The Android Open Source Project
39a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson *
49a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson * Licensed under the Apache License, Version 2.0 (the "License");
59a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson * you may not use this file except in compliance with the License.
69a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson * You may obtain a copy of the License at
79a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson *
89a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson *      http://www.apache.org/licenses/LICENSE-2.0
99a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson *
109a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson * Unless required by applicable law or agreed to in writing, software
119a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson * distributed under the License is distributed on an "AS IS" BASIS,
129a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson * See the License for the specific language governing permissions and
149a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson * limitations under the License.
159a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson */
169a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
179a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonpackage com.android.calendar;
189a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
199a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport com.android.calendar.CalendarController.ViewType;
209a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
219a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport android.content.Context;
229a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport android.database.DataSetObserver;
239a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport android.os.Handler;
249a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport android.text.TextUtils;
259a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport android.text.format.DateUtils;
269a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport android.text.format.Time;
279a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport android.util.Log;
289a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport android.view.LayoutInflater;
299a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport android.view.View;
309a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport android.view.ViewGroup;
319a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport android.widget.SpinnerAdapter;
329a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport android.widget.TextView;
339a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
349a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport java.util.ArrayList;
359a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport java.util.Arrays;
369a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport java.util.Formatter;
379a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport java.util.Iterator;
389a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonimport java.util.Locale;
399a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
409a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
419a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson/*
429a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson * The MenuSpinnerAdapter defines the look of the ActionBar's pull down menu
439a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson * for small screen layouts. The pull down menu replaces the tabs uses for big screen layouts
449a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson *
459a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson * The MenuSpinnerAdapter responsible for creating the views used for in the pull down menu.
469a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson */
479a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
489a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelsonpublic class CalendarViewAdapter implements SpinnerAdapter {
499a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
509a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private static final String TAG = "MenuSpinnerAdapter";
519a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
529a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private String mButtonNames [];           // Text on buttons
539a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private ArrayList<DataSetObserver> mObservers;
549a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
559a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Used to define the look of the menu button according to the current view:
569a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Day view: show day of the week + full date underneath
579a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Week view: show the month + year
589a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Month view: show the month + year
599a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Agenda view: show day of the week + full date underneath
609a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private int mCurrentMainView;
619a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
629a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private final LayoutInflater mInflater;
639a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
649a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Defines the types of view returned by this spinner
659a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private static final int BUTTON_VIEW_TYPE = 0;
669a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    static final int VIEW_TYPE_NUM = 1;  // Increase this if you add more view types
679a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
689a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public static final int DAY_BUTTON_INDEX = 0;
699a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public static final int WEEK_BUTTON_INDEX = 1;
709a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public static final int MONTH_BUTTON_INDEX = 2;
719a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public static final int AGENDA_BUTTON_INDEX = 3;
729a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
739a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // The current selected event's time, used to calculate the date and day of the week
749a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // for the buttons.
759a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    long mMilliTime;
769a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    String mTimeZone;
779a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private Time mTmpTime;
789a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    long mTodayJulianDay;
799a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
809a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    Context mContext;
819a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private Formatter mFormatter;
829a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private StringBuilder mStringBuilder;
839a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private Handler mMidnightHandler = null; // Used to run a time update every midnight
849a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
859a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Updates time specific variables (time-zone, today's Julian day).
869a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private Runnable mTimeUpdater = new Runnable() {
879a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        @Override
889a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        public void run() {
899a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            setTimeVars(mContext);
909a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        }
919a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    };
929a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
939a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public CalendarViewAdapter(Context context, int viewType) {
949a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        super();
959a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
969a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mCurrentMainView = viewType;
979a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mContext = context;
989a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
999a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        // Initialize
1009a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mButtonNames = context.getResources().getStringArray(R.array.buttons_list);
1019a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mObservers = new ArrayList<DataSetObserver>();
1029a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
1039a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mStringBuilder = new StringBuilder(50);
1049a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mFormatter = new Formatter(mStringBuilder, Locale.getDefault());
1059a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
1069a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        // Sets time specific variables and starts a thread for midnight updates
1079a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        setTimeVars(context);
1089a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
1099a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
1109a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
1119a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Sets the time zone and today's Julian day to be used by the adapter.
1129a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Also, notify listener on the change and resets the midnight update thread.
1139a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private void setTimeVars(Context context) {
1149a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mTimeZone = Utils.getTimeZone(context, mTimeUpdater);
1159a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mTmpTime = new Time(mTimeZone);
1169a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        Time time = new Time(mTimeZone);
1179a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        long now = System.currentTimeMillis();
1189a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        time.set(now);
1199a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mTodayJulianDay = Time.getJulianDay(now, time.gmtoff);
1209a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        notifyDataChange();
1219a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        setMidnightHandler();
1229a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
1239a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
1249a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Sets a thread to run 1 second after midnight and update the current date
1259a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // This is used to display correctly the date of yesterday/today/tomorrow
1269a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public void setMidnightHandler() {
1279a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        if (mMidnightHandler == null) {
1289a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            mMidnightHandler = new Handler();
1299a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        } else {
1309a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            mMidnightHandler.removeCallbacks(mTimeUpdater);
1319a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        }
1329a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        // Set the time updater to run at 1 second after midnight
1339a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        long now = System.currentTimeMillis();
1349a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        Time time = new Time(mTimeZone);
1359a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        time.set(now);
1369a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        long runInMillis = (24 * 3600 - time.hour * 3600 - time.minute * 60 -
1379a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                time.second + 1) * 1000;
1389a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mMidnightHandler.postDelayed(mTimeUpdater, runInMillis);
1399a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
1409a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
1419a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Stops the midnight update thread, called by the activity when it is paused.
1429a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public void resetMidnightHandler() {
1439a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        if (mMidnightHandler != null) {
1449a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            mMidnightHandler.removeCallbacks(mTimeUpdater);
1459a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        }
1469a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
1479a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
1489a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Add a data observer that will be called if there is a change in the data set (buttons list)
1499a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public void registerDataSetObserver(DataSetObserver observer) {
1509a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        if (observer != null) {
1519a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            synchronized(mObservers) {
1529a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                mObservers.add(observer);
1539a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            }
1549a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        }
1559a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
1569a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
1579a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Remove an existing data observer
1589a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public void unregisterDataSetObserver(DataSetObserver observer) {
1599a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        if (observer != null) {
1609a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            synchronized(mObservers) {
1619a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                mObservers.remove(observer);
1629a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            }
1639a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        }
1649a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
1659a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
1669a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Returns the amount of buttons in the menu
1679a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public int getCount() {
1689a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        return mButtonNames.length;
1699a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
1709a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
1719a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
1729a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public Object getItem(int position) {
1739a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        if (position < mButtonNames.length) {
1749a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            return mButtonNames[position];
1759a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        }
1769a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        return null;
1779a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
1789a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
1799a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public long getItemId(int position) {
1809a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        // Item ID is its location in the list
1819a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        return position;
1829a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
1839a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
1849a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public boolean hasStableIds() {
1859a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        return false;
1869a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
1879a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
1889a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public View getView(int position, View convertView, ViewGroup parent) {
1899a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
1909a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        View v;
1919a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        // Check if can recycle the view
1929a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        if (convertView == null ||
1939a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                ((Integer)convertView.getTag()).intValue() !=
1949a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                    R.layout.actionbar_pulldown_menu_top_button) {
1959a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            v = mInflater.inflate(R.layout.actionbar_pulldown_menu_top_button, parent, false);
1969a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            // Set the tag to make sure you can recycle it when you get it as a convert view
1979a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            v.setTag(new Integer(R.layout.actionbar_pulldown_menu_top_button));
1989a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        } else {
1999a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            v = convertView;
2009a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        }
2019a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        TextView weekDay = (TextView)v.findViewById(R.id.top_button_weekday);
2029a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        TextView date = (TextView)v.findViewById(R.id.top_button_date);
2039a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
2049a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        switch (mCurrentMainView) {
2059a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            case ViewType.DAY:
2069a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                weekDay.setVisibility(View.VISIBLE);
2079a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                weekDay.setText(buildDayOfWeek());
2089a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                date.setText(buildFullDate());
2099a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                break;
2109a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            case ViewType.WEEK:
21114e82b453a95456277fa5c40189c9b253a8e487fRoboErik                weekDay.setVisibility(View.VISIBLE);
21214e82b453a95456277fa5c40189c9b253a8e487fRoboErik                weekDay.setText(buildWeekNum());
2139a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                date.setText(buildMonthYearDate());
2149a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                break;
2159a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            case ViewType.MONTH:
2169a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                weekDay.setVisibility(View.GONE);
2179a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                date.setText(buildMonthYearDate());
2189a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                break;
2199a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            case ViewType.AGENDA:
2209a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                weekDay.setVisibility(View.VISIBLE);
2219a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                weekDay.setText(buildDayOfWeek());
2229a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                date.setText(buildFullDate());
2239a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                break;
2249a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            default:
2259a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                v = null;
2269a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                break;
2279a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        }
2289a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        return v;
2299a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
2309a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
2319a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public int getItemViewType(int position) {
2329a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        // Only one kind of view is used
2339a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        return BUTTON_VIEW_TYPE;
2349a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
2359a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
2369a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public int getViewTypeCount() {
2379a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        return VIEW_TYPE_NUM;
2389a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
2399a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
2409a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public boolean isEmpty() {
2419a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        return (mButtonNames.length == 0);
2429a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
2439a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
2449a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public View getDropDownView(int position, View convertView, ViewGroup parent) {
2459a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        View v = mInflater.inflate(R.layout.actionbar_pulldown_menu_button, parent, false);
2469a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        TextView viewType = (TextView)v.findViewById(R.id.button_view);
2479a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        TextView date = (TextView)v.findViewById(R.id.button_date);
2489a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        switch (position) {
2499a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            case DAY_BUTTON_INDEX:
2509a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                viewType.setText(mButtonNames [DAY_BUTTON_INDEX]);
2519a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                date.setText(buildMonthDayDate());
2529a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                break;
2539a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            case WEEK_BUTTON_INDEX:
2549a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                viewType.setText(mButtonNames [WEEK_BUTTON_INDEX]);
2559a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                date.setText(buildWeekDate());
2569a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                break;
2579a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            case MONTH_BUTTON_INDEX:
2589a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                viewType.setText(mButtonNames [MONTH_BUTTON_INDEX]);
2599a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                date.setText(buildMonthDate());
2609a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                break;
2619a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            case AGENDA_BUTTON_INDEX:
2629a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                viewType.setText(mButtonNames [AGENDA_BUTTON_INDEX]);
2639a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                date.setText(buildMonthDayDate());
2649a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                break;
2659a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            default:
2669a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                v = convertView;
2679a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                break;
2689a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        }
2699a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        return v;
2709a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
2719a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
2729a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Updates the current viewType
2739a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Used to match the label on the menu button with the calendar view
2749a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public void setMainView(int viewType) {
2759a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mCurrentMainView = viewType;
2769a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        notifyDataChange();
2779a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
2789a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
2799a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Update the date that is displayed on buttons
2809a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Used when the user selects a new day/week/month to watch
2819a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    public void setTime(long time) {
2829a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mMilliTime = time;
2839a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        notifyDataChange();
2849a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
2859a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
2869a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private void notifyDataChange() {
2879a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        synchronized(mObservers) {
2889a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            if (!mObservers.isEmpty()) {
2899a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                Iterator<DataSetObserver> i = mObservers.iterator();
2909a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                while (i.hasNext()) {
2919a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                    i.next().onChanged();
2929a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                }
2939a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            }
2949a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        }
2959a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
2969a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
2979a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Builds a string with the day of the week and the word yesterday/today/tomorrow
2989a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // before it if applicable.
2999a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private String buildDayOfWeek() {
3009a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
3019a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        Time t = new Time(mTimeZone);
3029a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        t.set(mMilliTime);
3039a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        long julianDay = Time.getJulianDay(mMilliTime,t.gmtoff);
3049a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        String dayOfWeek = null;
3059a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mStringBuilder.setLength(0);
3069a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
3079a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        if (julianDay == mTodayJulianDay) {
3089a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            dayOfWeek = mContext.getString(R.string.agenda_today,
3099a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                    DateUtils.formatDateRange(mContext, mFormatter, mMilliTime, mMilliTime,
3109a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                            DateUtils.FORMAT_SHOW_WEEKDAY, mTimeZone).toString());
3119a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        } else if (julianDay == mTodayJulianDay - 1) {
3129a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            dayOfWeek = mContext.getString(R.string.agenda_yesterday,
3139a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                    DateUtils.formatDateRange(mContext, mFormatter, mMilliTime, mMilliTime,
3149a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                            DateUtils.FORMAT_SHOW_WEEKDAY, mTimeZone).toString());
3159a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        } else if (julianDay == mTodayJulianDay + 1) {
3169a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            dayOfWeek = mContext.getString(R.string.agenda_tomorrow,
3179a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                    DateUtils.formatDateRange(mContext, mFormatter, mMilliTime, mMilliTime,
3189a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                            DateUtils.FORMAT_SHOW_WEEKDAY, mTimeZone).toString());
3199a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        } else {
3209a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            dayOfWeek = DateUtils.formatDateRange(mContext, mFormatter, mMilliTime, mMilliTime,
3219a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                    DateUtils.FORMAT_SHOW_WEEKDAY, mTimeZone).toString();
3229a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        }
3239a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        return dayOfWeek.toUpperCase();
3249a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
3259a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
3269a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Builds strings with different formats:
3279a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Full date: Month,day Year
3289a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Month year
3299a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Month day
3309a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Month
3319a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    // Week:  month day-day or month day - month day
3329a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private String buildFullDate() {
3339a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mStringBuilder.setLength(0);
3349a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        String date = DateUtils.formatDateRange(mContext, mFormatter, mMilliTime, mMilliTime,
3359a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_YEAR, mTimeZone).toString();
3369a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson         return date;
3379a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
3389a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private String buildMonthYearDate() {
3399a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mStringBuilder.setLength(0);
3409a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        String date = DateUtils.formatDateRange(mContext, mFormatter, mMilliTime, mMilliTime,
3419a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_MONTH_DAY |
3429a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                DateUtils.FORMAT_SHOW_YEAR, mTimeZone).toString();
3439a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson         return date;
3449a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
3459a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private String buildMonthDayDate() {
3469a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mStringBuilder.setLength(0);
3479a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        String date = DateUtils.formatDateRange(mContext, mFormatter, mMilliTime, mMilliTime,
3489a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_YEAR, mTimeZone).toString();
3499a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson         return date;
3509a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
3519a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private String buildMonthDate() {
3529a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mStringBuilder.setLength(0);
3539a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        String date = DateUtils.formatDateRange(mContext, mFormatter, mMilliTime, mMilliTime,
3549a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_YEAR |
3559a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                DateUtils.FORMAT_NO_MONTH_DAY, mTimeZone).toString();
3569a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson         return date;
3579a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
3589a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    private String buildWeekDate() {
3599a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
3609a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
3619a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        // Calculate the start of the week, taking into account the "first day of the week"
3629a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        // setting.
3639a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
3649a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        Time t = new Time(mTimeZone);
3659a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        t.set(mMilliTime);
3669a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        int firstDayOfWeek = Utils.getFirstDayOfWeek(mContext);
3679a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        int dayOfWeek = t.weekDay;
3689a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        int diff = dayOfWeek - firstDayOfWeek;
3699a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        if (diff != 0) {
3709a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            if (diff < 0) {
3719a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                diff += 7;
3729a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            }
3739a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            t.monthDay -= diff;
3749a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            t.normalize(true /* ignore isDst */);
3759a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        }
3769a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
3779a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        long weekStartTime = t.toMillis(true);
3788135093480db642734fb40d9627325bf9e97a8c9RoboErik        // The end of the week is 6 days after the start of the week
3798135093480db642734fb40d9627325bf9e97a8c9RoboErik        long weekEndTime = weekStartTime + DateUtils.WEEK_IN_MILLIS - DateUtils.DAY_IN_MILLIS;
3809a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
3819a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        // If week start and end is in 2 different months, use short months names
3829a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        Time t1 = new Time(mTimeZone);
3839a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        t.set(weekEndTime);
3849a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_NO_YEAR;
3859a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        if (t.month != t1.month) {
3869a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson            flags |= DateUtils.FORMAT_ABBREV_MONTH;
3879a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        }
3889a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
3899a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        mStringBuilder.setLength(0);
3909a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson        String date = DateUtils.formatDateRange(mContext, mFormatter, weekStartTime,
3919a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson                weekEndTime, flags, mTimeZone).toString();
3929a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson         return date;
3939a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson    }
3949a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
39514e82b453a95456277fa5c40189c9b253a8e487fRoboErik    private String buildWeekNum() {
39614e82b453a95456277fa5c40189c9b253a8e487fRoboErik        int week = Utils.getWeekNumberFromTime(mMilliTime, mContext);
39714e82b453a95456277fa5c40189c9b253a8e487fRoboErik        return mContext.getResources().getQuantityString(R.plurals.weekN, week, week);
39814e82b453a95456277fa5c40189c9b253a8e487fRoboErik    }
39914e82b453a95456277fa5c40189c9b253a8e487fRoboErik
4009a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson}
4019a39bddb8e519b710a06d1c77257de6962ae5f72Isaac Katzenelson
402