Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add events #325

Open
wants to merge 19 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
217 changes: 183 additions & 34 deletions library/src/main/java/com/alamkanak/weekview/WeekView.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
Expand All @@ -10,6 +11,8 @@
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.Nullable;
import android.support.v4.view.GestureDetectorCompat;
Expand Down Expand Up @@ -81,12 +84,14 @@ private enum Direction {
private Paint mNowLinePaint;
private Paint mTodayHeaderTextPaint;
private Paint mEventBackgroundPaint;
private Paint mNewEventBackgroundPaint;
private float mHeaderColumnWidth;
private List<EventRect> mEventRects;
private List<? extends WeekViewEvent> mPreviousPeriodEvents;
private List<? extends WeekViewEvent> mCurrentPeriodEvents;
private List<? extends WeekViewEvent> mNextPeriodEvents;
private TextPaint mEventTextPaint;
private TextPaint mNewEventTextPaint;
private Paint mHeaderColumnBackgroundPaint;
private int mFetchedPeriod = -1; // the middle period the calendar has fetched.
private boolean mRefreshEvents = false;
Expand All @@ -95,9 +100,10 @@ private enum Direction {
private boolean mIsZooming;
private Calendar mFirstVisibleDay;
private Calendar mLastVisibleDay;
private int mDefaultEventColor;
private int mMinimumFlingVelocity = 0;
private int mScaledTouchSlop = 0;
private EventRect mNewEventRect;

// Attributes and their default values.
private int mHourHeight = 50;
private int mNewHourHeight = -1;
Expand Down Expand Up @@ -127,13 +133,22 @@ private enum Direction {
private int mEventTextColor = Color.BLACK;
private int mEventPadding = 8;
private int mHeaderColumnBackgroundColor = Color.WHITE;
private int mDefaultEventColor;
private int mNewEventColor;
private int mNewEventId = -100;
private Drawable mNewEventIconDrawable;
private int mNewEventLengthInMinutes = 60;
private int mNewEventTimeResolutionInMinutes = 15;

private boolean mIsFirstDraw = true;
private boolean mAreDimensionsInvalid = true;
@Deprecated private int mDayNameLength = LENGTH_LONG;
@Deprecated
private int mDayNameLength = LENGTH_LONG;
private int mOverlappingEventGap = 0;
private int mEventMarginVertical = 0;
private float mXScrollingSpeed = 1f;
private Calendar mScrollToDay = null;
private Calendar mCacheEmptyEventDay;
private double mScrollToHour = -1;
private int mEventCornerRadius = 0;
private boolean mShowDistinctWeekendColor = false;
Expand All @@ -151,6 +166,7 @@ private enum Direction {
private EmptyViewLongPressListener mEmptyViewLongPressListener;
private DateTimeInterpreter mDateTimeInterpreter;
private ScrollListener mScrollListener;
private AddEventClickListener mAddEventClickListener;

private final GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() {

Expand Down Expand Up @@ -242,28 +258,76 @@ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float ve

@Override
public boolean onSingleTapConfirmed(MotionEvent e) {

// If the tap was on an event then trigger the callback.
if (mEventRects != null && mEventClickListener != null) {
List<EventRect> reversedEventRects = mEventRects;
Collections.reverse(reversedEventRects);
for (EventRect event : reversedEventRects) {
if (event.rectF != null && e.getX() > event.rectF.left && e.getX() < event.rectF.right && e.getY() > event.rectF.top && e.getY() < event.rectF.bottom) {
mEventClickListener.onEventClick(event.originalEvent, event.rectF);
for (EventRect eventRect : reversedEventRects) {
if (eventRect.event.getId() != mNewEventId &&eventRect.rectF != null && e.getX() > eventRect.rectF.left && e.getX() < eventRect.rectF.right && e.getY() > eventRect.rectF.top && e.getY() < eventRect.rectF.bottom) {
mEventClickListener.onEventClick(eventRect.originalEvent, eventRect.rectF);
playSoundEffect(SoundEffectConstants.CLICK);
return super.onSingleTapConfirmed(e);
}
}
}

// If the tap was on in an empty space, then trigger the callback.
if (mEmptyViewClickListener != null && e.getX() > mHeaderColumnWidth && e.getY() > (mHeaderHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom)) {
// If the tap was on add new Event space, then trigger the callback
if (mAddEventClickListener != null && mNewEventRect != null && mNewEventRect.rectF != null && e.getX() > mNewEventRect.rectF.left && e.getX() < mNewEventRect.rectF.right && e.getY() > mNewEventRect.rectF.top && e.getY() < mNewEventRect.rectF.bottom) {
mAddEventClickListener.onAddEventClicked(mNewEventRect.event.getStartTime(), mNewEventRect.event.getEndTime());
return super.onSingleTapConfirmed(e);
}

// If the tap was on an empty space, then trigger the callback.
if ((mEmptyViewClickListener != null || mAddEventClickListener != null) && e.getX() > mHeaderColumnWidth && e.getY() > (mHeaderHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom)) {
Calendar selectedTime = getTimeFromPoint(e.getX(), e.getY());
List<EventRect> tempEventRects = mEventRects;
mEventRects = new ArrayList<EventRect>();
if (selectedTime != null) {
if(mNewEventRect != null) {
tempEventRects.remove(mNewEventRect);
mNewEventRect = null;
}

playSoundEffect(SoundEffectConstants.CLICK);
mEmptyViewClickListener.onEmptyViewClicked(selectedTime);
if(mEmptyViewClickListener != null)
mEmptyViewClickListener.onEmptyViewClicked(selectedTime, mCacheEmptyEventDay, isSameDayAndHour(selectedTime, mCacheEmptyEventDay));

if(mAddEventClickListener != null) {
//round selectedTime to resolution
int unroundedMinutes = selectedTime.get(Calendar.MINUTE);
int mod = unroundedMinutes % mNewEventTimeResolutionInMinutes;
selectedTime.add(Calendar.MINUTE, mod < Math.ceil(mNewEventTimeResolutionInMinutes / 2) ? -mod : (mNewEventTimeResolutionInMinutes - mod));

Calendar endTime = (Calendar) selectedTime.clone();
endTime.add(Calendar.MINUTE, Math.min(mNewEventLengthInMinutes, (24-selectedTime.get(Calendar.HOUR_OF_DAY))*60 - selectedTime.get(Calendar.MINUTE)));
WeekViewEvent newEvent = new WeekViewEvent(mNewEventId, "", null, selectedTime, endTime);

float top = selectedTime.get(Calendar.HOUR_OF_DAY) * 60;
top = mHourHeight * 24 * top / 1440 + mCurrentOrigin.y + mHeaderHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom + mTimeTextHeight / 2 + mEventMarginVertical;
float bottom = endTime.get(Calendar.HOUR_OF_DAY) * 60;
bottom = mHourHeight * 24 * bottom / 1440 + mCurrentOrigin.y + mHeaderHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom + mTimeTextHeight / 2 - mEventMarginVertical;

// Calculate left and right.
float left = 0;
float right = left + mWidthPerDay;
// Draw the event and the event name on top of it.
if (left < right &&
left < getWidth() &&
top < getHeight() &&
right > mHeaderColumnWidth &&
bottom > 0
) {
RectF dayRectF = new RectF(left, top, right, bottom);
newEvent.setColor(mNewEventColor);
mNewEventRect = new EventRect(newEvent, newEvent, dayRectF);
tempEventRects.add(mNewEventRect);
invalidate();
computePositionOfEvents(tempEventRects);
}
}
}
}

return super.onSingleTapConfirmed(e);
}

Expand Down Expand Up @@ -336,7 +400,12 @@ public WeekView(Context context, AttributeSet attrs, int defStyleAttr) {
mTodayHeaderTextColor = a.getColor(R.styleable.WeekView_todayHeaderTextColor, mTodayHeaderTextColor);
mEventTextSize = a.getDimensionPixelSize(R.styleable.WeekView_eventTextSize, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, mEventTextSize, context.getResources().getDisplayMetrics()));
mEventTextColor = a.getColor(R.styleable.WeekView_eventTextColor, mEventTextColor);
mEventPadding = a.getDimensionPixelSize(R.styleable.WeekView_eventPadding, mEventPadding);
mNewEventColor = a.getColor(R.styleable.WeekView_newEventColor, mNewEventColor);
mNewEventIconDrawable = a.getDrawable(R.styleable.WeekView_newEventIconResource);
mNewEventId = a.getInt(R.styleable.WeekView_newEventId, mNewEventId);
mNewEventLengthInMinutes = a.getInt(R.styleable.WeekView_newEventLengthInMinutes, mNewEventLengthInMinutes);
mNewEventTimeResolutionInMinutes = a.getInt(R.styleable.WeekView_newEventTimeResolutionInMinutes, mNewEventTimeResolutionInMinutes);
mEventPadding = a.getDimensionPixelSize(R.styleable.WeekView_hourSeparatorHeight, mEventPadding);
mHeaderColumnBackgroundColor = a.getColor(R.styleable.WeekView_headerColumnBackground, mHeaderColumnBackgroundColor);
mDayNameLength = a.getInteger(R.styleable.WeekView_dayNameLength, mDayNameLength);
mOverlappingEventGap = a.getDimensionPixelSize(R.styleable.WeekView_overlappingEventGap, mOverlappingEventGap);
Expand Down Expand Up @@ -425,6 +494,9 @@ private void init() {
// Prepare event background color.
mEventBackgroundPaint = new Paint();
mEventBackgroundPaint.setColor(Color.rgb(174, 208, 238));
// Prepare empty event background color.
mNewEventBackgroundPaint = new Paint();
mNewEventBackgroundPaint.setColor(Color.rgb(60, 147, 217));

// Prepare header column background color.
mHeaderColumnBackgroundPaint = new Paint();
Expand All @@ -436,8 +508,13 @@ private void init() {
mEventTextPaint.setColor(mEventTextColor);
mEventTextPaint.setTextSize(mEventTextSize);


//mStartDate = (Calendar) mFirstVisibleDay.clone();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you remove the commented code?


// Set default event color.
mDefaultEventColor = Color.parseColor("#9fc6e7");
// Set default empty event color.
mNewEventColor = Color.parseColor("#3c93d9");

mScaleDetector = new ScaleGestureDetector(mContext, new ScaleGestureDetector.OnScaleGestureListener() {
@Override
Expand Down Expand Up @@ -803,7 +880,10 @@ top < getHeight() &&
mEventRects.get(i).rectF = new RectF(left, top, right, bottom);
mEventBackgroundPaint.setColor(mEventRects.get(i).event.getColor() == 0 ? mDefaultEventColor : mEventRects.get(i).event.getColor());
canvas.drawRoundRect(mEventRects.get(i).rectF, mEventCornerRadius, mEventCornerRadius, mEventBackgroundPaint);
drawEventTitle(mEventRects.get(i).event, mEventRects.get(i).rectF, canvas, top, left);
if(mEventRects.get(i).event.getId() != mNewEventId)
drawEventTitle(mEventRects.get(i).event, mEventRects.get(i).rectF, canvas, top, left);
else
drawEmptyImage(mEventRects.get(i).event, mEventRects.get(i).rectF, canvas, top, left);
}
else
mEventRects.get(i).rectF = null;
Expand Down Expand Up @@ -856,7 +936,6 @@ top < getHeight() &&
}
}


/**
* Draw the name of the event on top of the event rectangle.
* @param event The event of which the title (and location) should be drawn.
Expand Down Expand Up @@ -887,30 +966,46 @@ private void drawEventTitle(WeekViewEvent event, RectF rect, Canvas canvas, floa

// Get text dimensions.
StaticLayout textLayout = new StaticLayout(bob, mEventTextPaint, availableWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);

int lineHeight = textLayout.getHeight() / textLayout.getLineCount();

if (availableHeight >= lineHeight) {
// Calculate available number of line counts.
int availableLineCount = availableHeight / lineHeight;
do {
// Ellipsize text to fit into event rect.
textLayout = new StaticLayout(TextUtils.ellipsize(bob, mEventTextPaint, availableLineCount * availableWidth, TextUtils.TruncateAt.END), mEventTextPaint, (int) (rect.right - originalLeft - mEventPadding * 2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);

// Reduce line count.
availableLineCount--;

// Repeat until text is short enough.
} while (textLayout.getHeight() > availableHeight);

// Draw text.
canvas.save();
canvas.translate(originalLeft + mEventPadding, originalTop + mEventPadding);
textLayout.draw(canvas);
canvas.restore();
if(textLayout.getLineCount() > 0) {
int lineHeight = textLayout.getHeight() / textLayout.getLineCount();

if (availableHeight >= lineHeight) {
// Calculate available number of line counts.
int availableLineCount = availableHeight / lineHeight;
do {
// Ellipsize text to fit into event rect.
if (event.getId() != mNewEventId)
textLayout = new StaticLayout(TextUtils.ellipsize(bob, mEventTextPaint, availableLineCount * availableWidth, TextUtils.TruncateAt.END), mEventTextPaint, (int) (rect.right - originalLeft - mEventPadding * 2), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);

// Reduce line count.
availableLineCount--;

// Repeat until text is short enough.
} while (textLayout.getHeight() > availableHeight);

// Draw text.
canvas.save();
canvas.translate(originalLeft + mEventPadding, originalTop + mEventPadding);
textLayout.draw(canvas);
canvas.restore();
}
}
}

/**
* Draw the text on top of the rectangle in the empty event.
*
*
*/
private void drawEmptyImage(WeekViewEvent event, RectF rect, Canvas canvas, float originalTop, float originalLeft) {
int size = Math.max(1,(int)Math.floor(Math.min(0.8 * rect.height(), 0.8 * rect.width())));
if(mNewEventIconDrawable == null)
mNewEventIconDrawable = getResources().getDrawable(android.R.drawable.ic_input_add);
Bitmap icon = ((BitmapDrawable) mNewEventIconDrawable).getBitmap();
icon = Bitmap.createScaledBitmap(icon, size, size, false);
canvas.drawBitmap(icon, originalLeft + (rect.width() - icon.getWidth())/ 2, originalTop + (rect.height() - icon.getHeight()) / 2, new Paint());

}

/**
* A class to hold reference to the events and their visual representation. An EventRect is
Expand Down Expand Up @@ -1288,6 +1383,14 @@ public ScrollListener getScrollListener(){
return mScrollListener;
}

public void setAddEventClickListener(AddEventClickListener addEventClickListener){
this.mAddEventClickListener = addEventClickListener;
}

public AddEventClickListener getAddEventClickListener(){
return mAddEventClickListener;
}

/**
* Get the interpreter which provides the text to show in the header column and the header row.
* @return The date, time interpreter.
Expand Down Expand Up @@ -1544,6 +1647,39 @@ public void setDefaultEventColor(int defaultEventColor) {
invalidate();
}

public int getNewEventColor() {
return mNewEventColor;
}

public void setNewEventColor(int defaultNewEventColor) {
mNewEventColor = defaultNewEventColor;
invalidate();
}

public int getNewEventId(){
return mNewEventId;
}

public void setNewEventId(int newEventId){
this.mNewEventId = newEventId;
}

public int getNewEventLengthInMinutes(){
return mNewEventLengthInMinutes;
}

public void setNewEventLengthInMinutes(int newEventLengthInMinutes) {
this.mNewEventLengthInMinutes = newEventLengthInMinutes;
}

public int getNewEventTimeResolutionInMinutes(){
return mNewEventTimeResolutionInMinutes;
}

public void setNewEventTimeResolutionInMinutes(int newEventTimeResolutionInMinutes){
this.mNewEventTimeResolutionInMinutes = newEventTimeResolutionInMinutes;
}

/**
* <b>Note:</b> Use {@link #setDateTimeInterpreter(DateTimeInterpreter)} and
* {@link #getDateTimeInterpreter()} instead.
Expand Down Expand Up @@ -1882,6 +2018,7 @@ private boolean forceFinishScroll() {
public void goToToday() {
Calendar today = Calendar.getInstance();
goToDate(today);
mCacheEmptyEventDay = null;
}

/**
Expand Down Expand Up @@ -1988,7 +2125,9 @@ public interface EmptyViewClickListener {
* Triggered when the users clicks on a empty space of the calendar.
* @param time: {@link Calendar} object set with the date and time of the clicked position on the view.
*/
void onEmptyViewClicked(Calendar time);
//void onEmptyViewClicked(Calendar time);
void onEmptyViewClicked(Calendar time, Calendar tempTime, boolean clickedTwice);

}

public interface EmptyViewLongPressListener {
Expand All @@ -2009,4 +2148,14 @@ public interface ScrollListener {
*/
void onFirstVisibleDayChanged(Calendar newFirstVisibleDay, Calendar oldFirstVisibleDay);
}

public interface AddEventClickListener {
/**
* Triggered when the users clicks to create a new event.
* @param startTime The startTime of a new event
* @param endTime The endTime of a new event
*/
void onAddEventClicked(Calendar startTime, Calendar endTime);

}
}
15 changes: 15 additions & 0 deletions library/src/main/java/com/alamkanak/weekview/WeekViewUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,19 @@ public static Calendar today(){
today.set(Calendar.MILLISECOND, 0);
return today;
}

/**
* Checks if two times are on the same day and hour.
*
* @param dayOne The first day.
* @param dayTwo The second day.
* @return Whether the times are on the same day and hour.
*/
public static boolean isSameDayAndHour(Calendar dayOne, Calendar dayTwo) {

if (dayTwo != null) {
return dayOne.get(Calendar.YEAR) == dayTwo.get(Calendar.YEAR) && dayOne.get(Calendar.DAY_OF_YEAR) == dayTwo.get(Calendar.DAY_OF_YEAR) && dayOne.get(Calendar.HOUR_OF_DAY) == dayTwo.get(Calendar.HOUR_OF_DAY);
}
return false;
}
}
Loading