AgendaListView.java revision a9507932dbc49ecb9f5c71fda6af3a47b0b2a39a
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.calendar.agenda; 18 19import com.android.calendar.CalendarController; 20import com.android.calendar.CalendarController.EventType; 21import com.android.calendar.DeleteEventHelper; 22import com.android.calendar.R; 23import com.android.calendar.Utils; 24import com.android.calendar.agenda.AgendaAdapter.ViewHolder; 25import com.android.calendar.agenda.AgendaWindowAdapter.EventInfo; 26 27import android.content.Context; 28import android.graphics.Color; 29import android.graphics.Rect; 30import android.text.format.Time; 31import android.util.Log; 32import android.view.View; 33import android.widget.AdapterView; 34import android.widget.AdapterView.OnItemClickListener; 35import android.widget.ListView; 36import android.widget.TextView; 37 38public class AgendaListView extends ListView implements OnItemClickListener { 39 40 private static final String TAG = "AgendaListView"; 41 private static final boolean DEBUG = false; 42 43 private AgendaWindowAdapter mWindowAdapter; 44 private DeleteEventHelper mDeleteEventHelper; 45 private Context mContext; 46 private String mTimeZone; 47 48 private Runnable mTZUpdater = new Runnable() { 49 @Override 50 public void run() { 51 mTimeZone = Utils.getTimeZone(mContext, this); 52 } 53 }; 54 55 public AgendaListView(Context context) { 56 super(context, null); 57 mContext = context; 58 mTimeZone = Utils.getTimeZone(context, mTZUpdater); 59 setOnItemClickListener(this); 60 setChoiceMode(ListView.CHOICE_MODE_SINGLE); 61 setVerticalScrollBarEnabled(false); 62 mWindowAdapter = new AgendaWindowAdapter(context, this); 63 setAdapter(mWindowAdapter); 64 setCacheColorHint(context.getResources().getColor(R.color.agenda_item_not_selected)); 65 mDeleteEventHelper = 66 new DeleteEventHelper(context, null, false /* don't exit when done */); 67 } 68 69 @Override 70 protected void onDetachedFromWindow() { 71 super.onDetachedFromWindow(); 72 mWindowAdapter.close(); 73 } 74 75 // Implementation of the interface OnItemClickListener 76 @Override 77 public void onItemClick(AdapterView<?> a, View v, int position, long id) { 78 if (id != -1) { 79 // Switch to the EventInfo view 80 EventInfo event = mWindowAdapter.getEventByPosition(position); 81 mWindowAdapter.setSelectedPosition(position); 82 if (event != null) { 83 CalendarController.getInstance(mContext).sendEventRelatedEvent(this, 84 EventType.VIEW_EVENT, event.id, event.begin, event.end, 0, 0); 85 } 86 } 87 } 88 89 public void goTo(Time time, String searchQuery, boolean forced) { 90 if (time == null) { 91 time = new Time(mTimeZone); 92 long goToTime = getFirstVisibleTime(); 93 if (goToTime <= 0) { 94 goToTime = System.currentTimeMillis(); 95 } 96 time.set(goToTime); 97 } 98 mWindowAdapter.refresh(time, searchQuery, forced); 99 } 100 101 public void refresh(boolean forced) { 102 Time time = new Time(Utils.getTimeZone(mContext, null)); 103 long goToTime = getFirstVisibleTime(); 104 if (goToTime <= 0) { 105 goToTime = System.currentTimeMillis(); 106 } 107 time.set(goToTime); 108 mWindowAdapter.refresh(time, null, forced); 109 } 110 111 public void deleteSelectedEvent() { 112 int position = getSelectedItemPosition(); 113 EventInfo event = mWindowAdapter.getEventByPosition(position); 114 if (event != null) { 115 mDeleteEventHelper.delete(event.begin, event.end, event.id, -1); 116 } 117 } 118 119 @Override 120 public int getFirstVisiblePosition() { 121 // TODO File bug! 122 // getFirstVisiblePosition doesn't always return the first visible 123 // item. Sometimes, it is above the visible one. 124 // instead. I loop through the viewgroup children and find the first 125 // visible one. BTW, getFirstVisiblePosition() == getChildAt(0). I 126 // am not looping through the entire list. 127 View v = getFirstVisibleView(); 128 if (v != null) { 129 if (DEBUG) { 130 Log.v(TAG, "getFirstVisiblePosition: " + AgendaWindowAdapter.getViewTitle(v)); 131 } 132 return getPositionForView(v); 133 } 134 return -1; 135 } 136 137 public View getFirstVisibleView() { 138 Rect r = new Rect(); 139 int childCount = getChildCount(); 140 for (int i = 0; i < childCount; ++i) { 141 View listItem = getChildAt(i); 142 listItem.getLocalVisibleRect(r); 143 if (r.top >= 0) { // if visible 144 return listItem; 145 } 146 } 147 return null; 148 } 149 150 public long getSelectedTime() { 151 int position = getSelectedItemPosition(); 152 if (position >= 0) { 153 EventInfo event = mWindowAdapter.getEventByPosition(position); 154 if (event != null) { 155 return event.begin; 156 } 157 } 158 return getFirstVisibleTime(); 159 } 160 161 public long getFirstVisibleTime() { 162 int position = getFirstVisiblePosition(); 163 if (DEBUG) { 164 Log.v(TAG, "getFirstVisiblePosition = " + position); 165 } 166 167 EventInfo event = mWindowAdapter.getEventByPosition(position); 168 if (event != null) { 169 return event.begin; 170 } 171 return 0; 172 } 173 174 // Move the currently selected or visible focus down by offset amount. 175 // offset could be negative. 176 public void shiftSelection(int offset) { 177 shiftPosition(offset); 178 int position = getSelectedItemPosition(); 179 if (position != INVALID_POSITION) { 180 setSelectionFromTop(position + offset, 0); 181 } 182 } 183 184 private void shiftPosition(int offset) { 185 if (DEBUG) { 186 Log.v(TAG, "Shifting position "+ offset); 187 } 188 189 View firstVisibleItem = getFirstVisibleView(); 190 191 if (firstVisibleItem != null) { 192 Rect r = new Rect(); 193 firstVisibleItem.getLocalVisibleRect(r); 194 // if r.top is < 0, getChildAt(0) and getFirstVisiblePosition() is 195 // returning an item above the first visible item. 196 int position = getPositionForView(firstVisibleItem); 197 setSelectionFromTop(position + offset, r.top > 0 ? -r.top : r.top); 198 if (DEBUG) { 199 if (firstVisibleItem.getTag() instanceof AgendaAdapter.ViewHolder) { 200 ViewHolder viewHolder = (AgendaAdapter.ViewHolder)firstVisibleItem.getTag(); 201 Log.v(TAG, "Shifting from " + position + " by " + offset + ". Title " 202 + viewHolder.title.getText()); 203 } else if (firstVisibleItem.getTag() instanceof AgendaByDayAdapter.ViewHolder) { 204 AgendaByDayAdapter.ViewHolder viewHolder = 205 (AgendaByDayAdapter.ViewHolder)firstVisibleItem.getTag(); 206 Log.v(TAG, "Shifting from " + position + " by " + offset + ". Date " 207 + viewHolder.dateView.getText()); 208 } else if (firstVisibleItem instanceof TextView) { 209 Log.v(TAG, "Shifting: Looking at header here. " + getSelectedItemPosition()); 210 } 211 } 212 } else if (getSelectedItemPosition() >= 0) { 213 if (DEBUG) { 214 Log.v(TAG, "Shifting selection from " + getSelectedItemPosition() + " by " + offset); 215 } 216 setSelection(getSelectedItemPosition() + offset); 217 } 218 } 219 220 public void setHideDeclinedEvents(boolean hideDeclined) { 221 mWindowAdapter.setHideDeclinedEvents(hideDeclined); 222 } 223 224 public void onResume() { 225 mTZUpdater.run(); 226 mWindowAdapter.onResume(); 227 } 228 public void onPause() { 229 mWindowAdapter.notifyDataSetInvalidated(); 230 } 231} 232