public AgendaByDayAdapter(Context context) { mContext = context; mAgendaAdapter = new AgendaAdapter(context, R.layout.agenda_item); mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); mStringBuilder = new StringBuilder(50); mFormatter = new Formatter(mStringBuilder, Locale.getDefault()); mTimeZone = Utils.getTimeZone(context, mTZUpdater); mTmpTime = new Time(mTimeZone); }
private void init(Context c) { mListContext = c; mTracker = VelocityTracker.obtain(); mTempTime = new Time(Utils.getTimeZone(c, mTimezoneUpdater)); if (mScale == 0) { mScale = c.getResources().getDisplayMetrics().density; if (mScale != 1) { MIN_VELOCITY_FOR_FLING *= mScale; MULTIPLE_MONTH_VELOCITY_THRESHOLD *= mScale; FLING_VELOCITY_DIVIDER *= mScale; } } }
@Override public void run() { mTimeZone = Utils.getTimeZone(mContext, this); mTmpTime = new Time(mTimeZone); notifyDataSetChanged(); }
public void calculateDays(DayAdapterInfo dayAdapterInfo) { Cursor cursor = dayAdapterInfo.cursor; ArrayList<RowInfo> rowInfo = new ArrayList<RowInfo>(); int prevStartDay = -1; Time tempTime = new Time(mTimeZone); long now = System.currentTimeMillis(); tempTime.set(now); mTodayJulianDay = Time.getJulianDay(now, tempTime.gmtoff); LinkedList<MultipleDayInfo> multipleDayList = new LinkedList<MultipleDayInfo>(); for (int position = 0; cursor.moveToNext(); position++) { int startDay = cursor.getInt(AgendaWindowAdapter.INDEX_START_DAY); long id = cursor.getLong(AgendaWindowAdapter.INDEX_EVENT_ID); long startTime = cursor.getLong(AgendaWindowAdapter.INDEX_BEGIN); long endTime = cursor.getLong(AgendaWindowAdapter.INDEX_END); long instanceId = cursor.getLong(AgendaWindowAdapter.INDEX_INSTANCE_ID); boolean allDay = cursor.getInt(AgendaWindowAdapter.INDEX_ALL_DAY) != 0; if (allDay) { startTime = Utils.convertAlldayUtcToLocal(tempTime, startTime, mTimeZone); endTime = Utils.convertAlldayUtcToLocal(tempTime, endTime, mTimeZone); } // Skip over the days outside of the adapter's range startDay = Math.max(startDay, dayAdapterInfo.start); // Make sure event's start time is not before the start of the day // (setJulianDay sets the time to 12:00am) long adapterStartTime = tempTime.setJulianDay(startDay); startTime = Math.max(startTime, adapterStartTime); if (startDay != prevStartDay) { // Check if we skipped over any empty days if (prevStartDay == -1) { rowInfo.add(new RowInfo(TYPE_DAY, startDay)); } else { // If there are any multiple-day events that span the empty // range of days, then create day headers and events for // those multiple-day events. boolean dayHeaderAdded = false; for (int currentDay = prevStartDay + 1; currentDay <= startDay; currentDay++) { dayHeaderAdded = false; Iterator<MultipleDayInfo> iter = multipleDayList.iterator(); while (iter.hasNext()) { MultipleDayInfo info = iter.next(); // If this event has ended then remove it from the // list. if (info.mEndDay < currentDay) { iter.remove(); continue; } // If this is the first event for the day, then // insert a day header. if (!dayHeaderAdded) { rowInfo.add(new RowInfo(TYPE_DAY, currentDay)); dayHeaderAdded = true; } long nextMidnight = Utils.getNextMidnight(tempTime, info.mEventStartTimeMilli, mTimeZone); long infoEndTime = (info.mEndDay == currentDay) ? info.mEventEndTimeMilli : nextMidnight; rowInfo.add( new RowInfo( TYPE_MEETING, currentDay, info.mPosition, info.mEventId, info.mEventStartTimeMilli, infoEndTime, info.mInstanceId, info.mAllDay)); info.mEventStartTimeMilli = nextMidnight; } } // If the day header was not added for the start day, then // add it now. if (!dayHeaderAdded) { rowInfo.add(new RowInfo(TYPE_DAY, startDay)); } } prevStartDay = startDay; } // If this event spans multiple days, then add it to the multipleDay // list. int endDay = cursor.getInt(AgendaWindowAdapter.INDEX_END_DAY); // Skip over the days outside of the adapter's range endDay = Math.min(endDay, dayAdapterInfo.end); if (endDay > startDay) { long nextMidnight = Utils.getNextMidnight(tempTime, startTime, mTimeZone); multipleDayList.add( new MultipleDayInfo(position, endDay, id, nextMidnight, endTime, instanceId, allDay)); // Add in the event for this cursor position - since it is the start of a multi-day // event, the end time is midnight rowInfo.add( new RowInfo( TYPE_MEETING, startDay, position, id, startTime, nextMidnight, instanceId, allDay)); } else { // Add in the event for this cursor position rowInfo.add( new RowInfo( TYPE_MEETING, startDay, position, id, startTime, endTime, instanceId, allDay)); } } // There are no more cursor events but we might still have multiple-day // events left. So create day headers and events for those. if (prevStartDay > 0) { for (int currentDay = prevStartDay + 1; currentDay <= dayAdapterInfo.end; currentDay++) { boolean dayHeaderAdded = false; Iterator<MultipleDayInfo> iter = multipleDayList.iterator(); while (iter.hasNext()) { MultipleDayInfo info = iter.next(); // If this event has ended then remove it from the // list. if (info.mEndDay < currentDay) { iter.remove(); continue; } // If this is the first event for the day, then // insert a day header. if (!dayHeaderAdded) { rowInfo.add(new RowInfo(TYPE_DAY, currentDay)); dayHeaderAdded = true; } long nextMidnight = Utils.getNextMidnight(tempTime, info.mEventStartTimeMilli, mTimeZone); long infoEndTime = (info.mEndDay == currentDay) ? info.mEventEndTimeMilli : nextMidnight; rowInfo.add( new RowInfo( TYPE_MEETING, currentDay, info.mPosition, info.mEventId, info.mEventStartTimeMilli, infoEndTime, info.mInstanceId, info.mAllDay)); info.mEventStartTimeMilli = nextMidnight; } } } mRowInfo = rowInfo; }
@Override public View getView(int position, View convertView, ViewGroup parent) { if ((mRowInfo == null) || (position > mRowInfo.size())) { // If we have no row info, mAgendaAdapter returns the view. return mAgendaAdapter.getView(position, convertView, parent); } RowInfo row = mRowInfo.get(position); if (row.mType == TYPE_DAY) { ViewHolder holder = null; View agendaDayView = null; if ((convertView != null) && (convertView.getTag() != null)) { // Listview may get confused and pass in a different type of // view since we keep shifting data around. Not a big problem. Object tag = convertView.getTag(); if (tag instanceof ViewHolder) { agendaDayView = convertView; holder = (ViewHolder) tag; holder.julianDay = row.mDay; } } if (holder == null) { // Create a new AgendaView with a ViewHolder for fast access to // views w/o calling findViewById() holder = new ViewHolder(); agendaDayView = mInflater.inflate(R.layout.agenda_day, parent, false); holder.dayView = (TextView) agendaDayView.findViewById(R.id.day); holder.dateView = (TextView) agendaDayView.findViewById(R.id.date); holder.julianDay = row.mDay; holder.grayed = false; agendaDayView.setTag(holder); } // Re-use the member variable "mTime" which is set to the local // time zone. // It's difficult to find and update all these adapters when the // home tz changes so check it here and update if needed. String tz = Utils.getTimeZone(mContext, mTZUpdater); if (!TextUtils.equals(tz, mTmpTime.timezone)) { mTimeZone = tz; mTmpTime = new Time(tz); } // Build the text for the day of the week. // Should be yesterday/today/tomorrow (if applicable) + day of the week Time date = mTmpTime; long millis = date.setJulianDay(row.mDay); int flags = DateUtils.FORMAT_SHOW_WEEKDAY; mStringBuilder.setLength(0); String dayViewText = Utils.getDayOfWeekString(row.mDay, mTodayJulianDay, millis, mContext); // Build text for the date // Format should be month day mStringBuilder.setLength(0); flags = DateUtils.FORMAT_SHOW_DATE; String dateViewText = DateUtils.formatDateRange(mContext, mFormatter, millis, millis, flags, mTimeZone) .toString(); if (AgendaWindowAdapter.BASICLOG) { dayViewText += " P:" + position; dateViewText += " P:" + position; } holder.dayView.setText(dayViewText); holder.dateView.setText(dateViewText); // Set the background of the view, it is grayed for day that are in the past and today if (row.mDay > mTodayJulianDay) { agendaDayView.setBackgroundResource(R.drawable.agenda_item_bg_primary); holder.grayed = false; } else { agendaDayView.setBackgroundResource(R.drawable.agenda_item_bg_secondary); holder.grayed = true; } return agendaDayView; } else if (row.mType == TYPE_MEETING) { View itemView = mAgendaAdapter.getView(row.mPosition, convertView, parent); AgendaAdapter.ViewHolder holder = ((AgendaAdapter.ViewHolder) itemView.getTag()); TextView title = holder.title; // The holder in the view stores information from the cursor, but the cursor has no // notion of multi-day event and the start time of each instance of a multi-day event // is the same. RowInfo has the correct info , so take it from there. holder.startTimeMilli = row.mEventStartTimeMilli; boolean allDay = holder.allDay; if (AgendaWindowAdapter.BASICLOG) { title.setText(title.getText() + " P:" + position); } else { title.setText(title.getText()); } // if event in the past or started already, un-bold the title and set the background if ((!allDay && row.mEventStartTimeMilli <= System.currentTimeMillis()) || (allDay && row.mDay <= mTodayJulianDay)) { itemView.setBackgroundResource(R.drawable.agenda_item_bg_secondary); title.setTypeface(Typeface.DEFAULT); holder.grayed = true; } else { itemView.setBackgroundResource(R.drawable.agenda_item_bg_primary); title.setTypeface(Typeface.DEFAULT_BOLD); holder.grayed = false; } holder.julianDay = row.mDay; return itemView; } else { // Error throw new IllegalStateException("Unknown event type:" + row.mType); } }
@Override public void run() { if (mTempTime != null && mListContext != null) { mTempTime.timezone = Utils.getTimeZone(mListContext, mTimezoneUpdater); } }