/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.redgeek.android.eventrend.calendar; import java.util.Calendar; import net.redgeek.android.eventrend.Preferences; import net.redgeek.android.eventrend.backgroundtasks.DataCollectionTask; import net.redgeek.android.eventrend.primitives.TimeSeriesCollector; import net.redgeek.android.eventrend.primitives.Tuple; import net.redgeek.android.eventrend.util.DateUtil; import net.redgeek.android.eventrend.util.GUITask; import net.redgeek.android.eventrend.util.GUITaskQueue; import net.redgeek.android.eventrend.util.ProgressIndicator; import net.redgeek.android.eventrend.util.DateUtil.Period; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.view.MotionEvent; import android.view.View; import android.view.View.OnLongClickListener; import android.widget.TextView; public class CalendarView extends View implements OnLongClickListener, GUITask { // Various UI parameters public static final int BORDER_X = 20; public static final int BORDER_Y = 20; public static final int CELL_BORDER_FOCUSED = 3; public static final int CELL_BORDER_HIGHLIGHT = 1; public static final int CELL_BORDER_AUX = 1; public static final int CELL_TEXT_STROKE = 1; public static final int TEXT_HEIGHT = 10; public static final int ZOOM_CTRL_HIDE_MS = 3000; // UI elements private TextView mStatus; private CalendarPlot mCalendarPlot; private ProgressIndicator.Titlebar mProgress; private Canvas mCanvas; // Private data private Context mCtx; private TimeSeriesCollector mTSC; private Calendar mCal; private Period mPeriod; private DateUtil mDates; private long mCatId; // Tasks and handlers private DataCollectionTask mCollector; public CalendarView(Context context, TimeSeriesCollector tsc) { super(context); mCtx = context; mTSC = tsc; setupData(); setupUI(); } private void setupData() { mCal = Calendar.getInstance(); mDates = new DateUtil(); mPeriod = Period.MONTH; mCollector = new DataCollectionTask(mTSC); mCalendarPlot = new CalendarPlot(mCtx, mTSC, getWidth(), getHeight()); } private void setupUI() { setupListeners(); setColorScheme(); setFocusableInTouchMode(true); setOnLongClickListener(this); mProgress = new ProgressIndicator.Titlebar(mCtx); mStatus = ((CalendarActivity) mCtx).getStatusTextView(); } private void setupListeners() { } public void setColorScheme() { if (Preferences.getDefaultGraphIsBlack(mCtx) == true) setBackgroundColor(Color.BLACK); else setBackgroundColor(Color.WHITE); mCalendarPlot.setColorScheme(); } public boolean onLongClick(View v) { return true; } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { mCalendarPlot.setCalendarSize(w, h); } @Override public boolean onTouchEvent(MotionEvent event) { // if (event.getAction() != MotionEvent.ACTION_UP) { // ((CalendarActivity) mCtx).graph(); // return super.onTouchEvent(event); // } return super.onTouchEvent(event); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (getWidth() > 0 && getHeight() > 0) { mCanvas = canvas; mCalendarPlot.plot(mCanvas); } } public void executeNonGuiTask() throws Exception { setStartEnd(); mCollector.doCollection(); } public void afterExecute() { updateStatus(); setFocusable(true); invalidate(); } public void onFailure(Throwable t) { } public void resetZoom() { long start = mCalendarPlot.getCalendarStart(); mCalendarPlot.setCalendarStart(start); } public void updateData() { setStartEnd(); // Useful debugging: uncomment the following, and comment out the // addTask() below -- this makes the data collection run synchronously. // mCollector.doCollection(); // updateStatus(); // invalidate(); GUITaskQueue.getInstance().addTask(mProgress, this); } public void setPeriod(Period p) { mPeriod = p; getCalendar().setSpan(p); } private void setStartEnd() { long displayStart = mCalendarPlot.getCalendarStart(); long collectionStart = displayStart; long collectionEnd; Calendar cal = mDates.getCalendar(); cal.setTimeInMillis(displayStart); if (mPeriod == Period.YEAR) { DateUtil.setToPeriodStart(cal, Period.YEAR); displayStart = cal.getTimeInMillis(); mDates.setBaseTime(displayStart); mDates.advance(Period.YEAR, -3); collectionStart = cal.getTimeInMillis(); collectionEnd = collectionStart + DateUtil.YEAR_MS * 5; } else if (mPeriod == Period.MONTH) { DateUtil.setToPeriodStart(cal, Period.MONTH); displayStart = cal.getTimeInMillis(); mDates.setBaseTime(displayStart); int month = mDates.get(Calendar.MONTH); int position = mDates.get(Calendar.DAY_OF_WEEK); if (month == 1 && position == cal.getFirstDayOfWeek()) { mDates.advance(Period.DAY, -7); } else { mDates.advance(Period.DAY, -position + 1); } collectionStart = cal.getTimeInMillis(); collectionEnd = collectionStart + DateUtil.DAY_MS * 42; } else { DateUtil.setToPeriodStart(cal, Period.DAY); displayStart = cal.getTimeInMillis(); mDates.setBaseTime(displayStart); mDates.advance(Period.DAY, -7); collectionStart = cal.getTimeInMillis(); collectionEnd = collectionStart + DateUtil.YEAR_MS * 8; } mCalendarPlot.setCalendarStart(displayStart); mCalendarPlot.setSpan(mPeriod); mTSC.setSmoothing(Preferences.getSmoothingConstant(mCtx)); mTSC.setAutoAggregationOffset(-2); mCollector.setSpan(collectionStart, collectionEnd); } private void updateStatus() { Calendar c = Calendar.getInstance(); c.setTimeInMillis(mCalendarPlot.getCalendarStart()); if (mPeriod == Period.YEAR) { mStatus.setText("" + c.get(Calendar.YEAR)); } else if (mPeriod == Period.MONTH) { mStatus.setText(DateUtil.MONTHS[c.get(Calendar.MONTH)] + " " + c.get(Calendar.YEAR)); } } private void jump(int offset) { Calendar cal = mDates.getCalendar(); cal.setTimeInMillis(mCalendarPlot.getCalendarStart()); if (mPeriod == Period.YEAR) { // nothing to do for this case } else if (mPeriod == Period.MONTH) { cal.add(Calendar.YEAR, offset); } else { cal.add(Calendar.MONTH, offset); } mCalendarPlot.setCalendarStart(cal.getTimeInMillis()); } private void shift(int offset) { Calendar cal = mDates.getCalendar(); cal.setTimeInMillis(mCalendarPlot.getCalendarStart()); if (mPeriod == Period.YEAR) { cal.add(Calendar.YEAR, offset); } else if (mPeriod == Period.MONTH) { cal.add(Calendar.MONTH, offset); } else { cal.add(Calendar.DAY_OF_MONTH, offset); } mCalendarPlot.setCalendarStart(cal.getTimeInMillis()); } public void prevJump() { jump(-1); } public void nextJump() { jump(1); } public void prevPeriod() { shift(-1); } public void nextPeriod() { shift(1); } public void lookupPeriod(Tuple t) { mCalendarPlot.lookupPeriod(t); } public CalendarPlot getCalendar() { return mCalendarPlot; } public void setCategoryId(long catId) { mCatId = catId; } public long getCategoryId() { return mCatId; } }