From 2326ede91c7ac7b22fcf51c6ebb305fdf9c6da92 Mon Sep 17 00:00:00 2001
From: Joshua <8Joshua@web.de>
Date: Thu, 12 Jul 2018 15:45:59 +0200
Subject: [PATCH] WeekView Bib eigenkreation
---
.idea/misc.xml | 2 +-
app/build.gradle | 2 +-
.../fuplanner/fragments/ScheduleFragment.java | 7 +-
.../ui/weekview/DateTimeInterpreter.java | 12 +
.../tools/ui/weekview/MonthLoader.java | 46 +
.../tools/ui/weekview/TextColorPicker.java | 12 +
.../fuplanner/tools/ui/weekview/WeekView.java | 2854 +++++++++++++++++
.../tools/ui/weekview/WeekViewEvent.java | 344 ++
.../tools/ui/weekview/WeekViewLoader.java | 27 +
.../tools/ui/weekview/WeekViewUtil.java | 88 +
app/src/main/res/layout/fragment_schedule.xml | 10 +-
app/src/main/res/values/attrs.xml | 69 +
12 files changed, 3464 insertions(+), 9 deletions(-)
create mode 100644 app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/DateTimeInterpreter.java
create mode 100644 app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/MonthLoader.java
create mode 100644 app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/TextColorPicker.java
create mode 100644 app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/WeekView.java
create mode 100644 app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/WeekViewEvent.java
create mode 100644 app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/WeekViewLoader.java
create mode 100644 app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/WeekViewUtil.java
create mode 100644 app/src/main/res/values/attrs.xml
diff --git a/.idea/misc.xml b/.idea/misc.xml
index a8cce1b..26dc4f5 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -25,5 +25,5 @@
-
Very important interface, it's the base to load events in the calendar. + * This method is called three times: once to load the previous month, once to load the next month and once to load the current month.
+ * That's why you can have three times the same event at the same place if you mess up with the configuration + * + * @param newYear : year of the events required by the view. + * @param newMonth :month of the events required by the view
1 based (not like JAVA API) : January = 1 and December = 12. + * @return a list of the events happening during the specified month. + */ + List extends WeekViewEvent> onMonthChange(int newYear, int newMonth); + } +} diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/TextColorPicker.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/TextColorPicker.java new file mode 100644 index 0000000..487874d --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/TextColorPicker.java @@ -0,0 +1,12 @@ +package de.sebse.fuplanner.tools.ui.weekview; + +import android.support.annotation.ColorInt; + + + +public interface TextColorPicker { + + @ColorInt + int getTextColor(WeekViewEvent event); + +} diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/WeekView.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/WeekView.java new file mode 100644 index 0000000..9afa5ec --- /dev/null +++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/WeekView.java @@ -0,0 +1,2854 @@ +package de.sebse.fuplanner.tools.ui.weekview; + +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; +import android.graphics.PointF; +import android.graphics.Rect; +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.annotation.RequiresApi; +import android.support.v4.view.GestureDetectorCompat; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.animation.FastOutLinearInInterpolator; +import android.text.Layout; +import android.text.SpannableStringBuilder; +import android.text.StaticLayout; +import android.text.TextPaint; +import android.text.TextUtils; +import android.text.format.DateFormat; +import android.text.style.StyleSpan; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.DragEvent; +import android.view.GestureDetector; +import android.view.HapticFeedbackConstants; +import android.view.MotionEvent; +import android.view.ScaleGestureDetector; +import android.view.SoundEffectConstants; +import android.view.View; +import android.view.ViewConfiguration; +import android.widget.OverScroller; + + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Locale; + +import de.sebse.fuplanner.R; + +import static de.sebse.fuplanner.tools.ui.weekview.WeekViewUtil.daysBetween; +import static de.sebse.fuplanner.tools.ui.weekview.WeekViewUtil.getPassedMinutesInDay; +import static de.sebse.fuplanner.tools.ui.weekview.WeekViewUtil.isSameDay; +import static de.sebse.fuplanner.tools.ui.weekview.WeekViewUtil.today; + + +/** + * Created by Raquib-ul-Alam Kanak on 7/21/2014. + * Website: http://alamkanak.github.io/ + */ +@SuppressWarnings("unused") +public class WeekView extends View { + + private enum Direction { + NONE, LEFT, RIGHT, VERTICAL + } + + @Deprecated + public static final int LENGTH_SHORT = 1; + @Deprecated + public static final int LENGTH_LONG = 2; + private final Context mContext; + private Calendar mHomeDate; + private Calendar mMinDate; + private Calendar mMaxDate; + private Paint mTimeTextPaint; + private float mTimeTextWidth; + private float mTimeTextHeight; + private Paint mHeaderTextPaint; + private float mHeaderTextHeight; + private float mHeaderHeight; + private GestureDetectorCompat mGestureDetector; + private OverScroller mScroller; + private PointF mCurrentOrigin = new PointF(0f, 0f); + private Direction mCurrentScrollDirection = Direction.NONE; + private Paint mHeaderBackgroundPaint; + private float mWidthPerDay; + private Paint mDayBackgroundPaint; + private Paint mHourSeparatorPaint; + private float mHeaderMarginBottom; + private Paint mTodayBackgroundPaint; + private Paint mFutureBackgroundPaint; + private Paint mPastBackgroundPaint; + private Paint mFutureWeekendBackgroundPaint; + private Paint mPastWeekendBackgroundPaint; + private Paint mNowLinePaint; + private Paint mTodayHeaderTextPaint; + private Paint mEventBackgroundPaint; + private Paint mNewEventBackgroundPaint; + private float mHeaderColumnWidth; + private List+ * Note: This method will only work if the week view is set to display more than 6 days at + * once. + *
+ * + * @param firstDayOfWeek The supported values are {@link Calendar#SUNDAY}, + * {@link Calendar#MONDAY}, {@link Calendar#TUESDAY}, + * {@link Calendar#WEDNESDAY}, {@link Calendar#THURSDAY}, + * {@link Calendar#FRIDAY}. + */ + public void setFirstDayOfWeek(int firstDayOfWeek) { + mFirstDayOfWeek = firstDayOfWeek; + invalidate(); + } + + public boolean isShowFirstDayOfWeekFirst() { + return mShowFirstDayOfWeekFirst; + } + + public void setShowFirstDayOfWeekFirst(boolean show) { + mShowFirstDayOfWeekFirst = show; + } + + public int getTextSize() { + return mTextSize; + } + + public void setTextSize(int textSize) { + mTextSize = textSize; + mTodayHeaderTextPaint.setTextSize(mTextSize); + mHeaderTextPaint.setTextSize(mTextSize); + mTimeTextPaint.setTextSize(mTextSize); + invalidate(); + } + + public int getHeaderColumnPadding() { + return mHeaderColumnPadding; + } + + public void setHeaderColumnPadding(int headerColumnPadding) { + mHeaderColumnPadding = headerColumnPadding; + invalidate(); + } + + public int getHeaderColumnTextColor() { + return mHeaderColumnTextColor; + } + + public void setHeaderColumnTextColor(int headerColumnTextColor) { + mHeaderColumnTextColor = headerColumnTextColor; + mHeaderTextPaint.setColor(mHeaderColumnTextColor); + mTimeTextPaint.setColor(mHeaderColumnTextColor); + invalidate(); + } + + public void setTypeface(Typeface typeface) { + if (typeface != null) { + mEventTextPaint.setTypeface(typeface); + mTodayHeaderTextPaint.setTypeface(typeface); + mTimeTextPaint.setTypeface(typeface); + mTypeface = typeface; + init(); + } + } + + public int getHeaderRowPadding() { + return mHeaderRowPadding; + } + + public void setHeaderRowPadding(int headerRowPadding) { + mHeaderRowPadding = headerRowPadding; + invalidate(); + } + + public int getHeaderRowBackgroundColor() { + return mHeaderRowBackgroundColor; + } + + public void setHeaderRowBackgroundColor(int headerRowBackgroundColor) { + mHeaderRowBackgroundColor = headerRowBackgroundColor; + mHeaderBackgroundPaint.setColor(mHeaderRowBackgroundColor); + invalidate(); + } + + public int getDayBackgroundColor() { + return mDayBackgroundColor; + } + + public void setDayBackgroundColor(int dayBackgroundColor) { + mDayBackgroundColor = dayBackgroundColor; + mDayBackgroundPaint.setColor(mDayBackgroundColor); + invalidate(); + } + + public int getHourSeparatorColor() { + return mHourSeparatorColor; + } + + public void setHourSeparatorColor(int hourSeparatorColor) { + mHourSeparatorColor = hourSeparatorColor; + mHourSeparatorPaint.setColor(mHourSeparatorColor); + invalidate(); + } + + public int getTodayBackgroundColor() { + return mTodayBackgroundColor; + } + + public void setTodayBackgroundColor(int todayBackgroundColor) { + mTodayBackgroundColor = todayBackgroundColor; + mTodayBackgroundPaint.setColor(mTodayBackgroundColor); + invalidate(); + } + + public int getHourSeparatorHeight() { + return mHourSeparatorHeight; + } + + public void setHourSeparatorHeight(int hourSeparatorHeight) { + mHourSeparatorHeight = hourSeparatorHeight; + mHourSeparatorPaint.setStrokeWidth(mHourSeparatorHeight); + invalidate(); + } + + public int getTodayHeaderTextColor() { + return mTodayHeaderTextColor; + } + + public void setTodayHeaderTextColor(int todayHeaderTextColor) { + mTodayHeaderTextColor = todayHeaderTextColor; + mTodayHeaderTextPaint.setColor(mTodayHeaderTextColor); + invalidate(); + } + + public int getEventTextSize() { + return mEventTextSize; + } + + public void setEventTextSize(int eventTextSize) { + mEventTextSize = eventTextSize; + mEventTextPaint.setTextSize(mEventTextSize); + invalidate(); + } + + public int getEventTextColor() { + return mEventTextColor; + } + + public void setEventTextColor(int eventTextColor) { + mEventTextColor = eventTextColor; + mEventTextPaint.setColor(mEventTextColor); + invalidate(); + } + + public void setTextColorPicker(TextColorPicker textColorPicker) { + this.textColorPicker = textColorPicker; + } + + public TextColorPicker getTextColorPicker() { + return textColorPicker; + } + + public int getEventPadding() { + return mEventPadding; + } + + public void setEventPadding(int eventPadding) { + mEventPadding = eventPadding; + invalidate(); + } + + public int getHeaderColumnBackgroundColor() { + return mHeaderColumnBackgroundColor; + } + + public void setHeaderColumnBackgroundColor(int headerColumnBackgroundColor) { + mHeaderColumnBackgroundColor = headerColumnBackgroundColor; + mHeaderColumnBackgroundPaint.setColor(mHeaderColumnBackgroundColor); + invalidate(); + } + + public int getDefaultEventColor() { + return mDefaultEventColor; + } + + public void setDefaultEventColor(int defaultEventColor) { + mDefaultEventColor = defaultEventColor; + invalidate(); + } + + public int getNewEventColor() { + return mNewEventColor; + } + + public void setNewEventColor(int defaultNewEventColor) { + mNewEventColor = defaultNewEventColor; + invalidate(); + } + + public String getNewEventIdentifier() { + return mNewEventIdentifier; + } + + @Deprecated + public int getNewEventId() { + return Integer.parseInt(mNewEventIdentifier); + } + + public void setNewEventIdentifier(String newEventId) { + this.mNewEventIdentifier = newEventId; + } + + @Deprecated + public void setNewEventId(int newEventId) { + this.mNewEventIdentifier = String.valueOf(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; + } + + /** + * Note: Use {@link #setDateTimeInterpreter(DateTimeInterpreter)} and + * {@link #getDateTimeInterpreter()} instead. + * + * @return Either long or short day name is being used. + */ + @Deprecated + public int getDayNameLength() { + return mDayNameLength; + } + + /** + * Set the length of the day name displayed in the header row. Example of short day names is + * 'M' for 'Monday' and example of long day names is 'Mon' for 'Monday'. + *+ * Note: Use {@link #setDateTimeInterpreter(DateTimeInterpreter)} instead. + *
+ * + * @param length Supported values are {@link WeekView#LENGTH_SHORT} and + * {@link WeekView#LENGTH_LONG}. + */ + @Deprecated + public void setDayNameLength(int length) { + if (length != LENGTH_LONG && length != LENGTH_SHORT) { + throw new IllegalArgumentException("length parameter must be either LENGTH_LONG or LENGTH_SHORT"); + } + this.mDayNameLength = length; + } + + public int getOverlappingEventGap() { + return mOverlappingEventGap; + } + + /** + * Set the gap between overlapping events. + * + * @param overlappingEventGap The gap between overlapping events. + */ + public void setOverlappingEventGap(int overlappingEventGap) { + this.mOverlappingEventGap = overlappingEventGap; + invalidate(); + } + + public int getEventCornerRadius() { + return mEventCornerRadius; + } + + /** + * Set corner radius for event rect. + * + * @param eventCornerRadius the radius in px. + */ + public void setEventCornerRadius(int eventCornerRadius) { + mEventCornerRadius = eventCornerRadius; + } + + public int getEventMarginVertical() { + return mEventMarginVertical; + } + + /** + * Set the top and bottom margin of the event. The event will release this margin from the top + * and bottom edge. This margin is useful for differentiation consecutive events. + * + * @param eventMarginVertical The top and bottom margin. + */ + public void setEventMarginVertical(int eventMarginVertical) { + this.mEventMarginVertical = eventMarginVertical; + invalidate(); + } + + /** + * Returns the first visible day in the week view. + * + * @return The first visible day in the week view. + */ + public Calendar getFirstVisibleDay() { + return mFirstVisibleDay; + } + + /** + * Returns the last visible day in the week view. + * + * @return The last visible day in the week view. + */ + public Calendar getLastVisibleDay() { + return mLastVisibleDay; + } + + /** + * Get the scrolling speed factor in horizontal direction. + * + * @return The speed factor in horizontal direction. + */ + public float getXScrollingSpeed() { + return mXScrollingSpeed; + } + + /** + * Sets the speed for horizontal scrolling. + * + * @param xScrollingSpeed The new horizontal scrolling speed. + */ + public void setXScrollingSpeed(float xScrollingSpeed) { + this.mXScrollingSpeed = xScrollingSpeed; + } + + /** + * Get the earliest day that can be displayed. Will return null if no minimum date is set. + * + * @return the earliest day that can be displayed, null if no minimum date set + */ + public Calendar getMinDate() { + return mMinDate; + } + + /** + * Set the earliest day that can be displayed. This will determine the left horizontal scroll + * limit. The default value is null (allow unlimited scrolling into the past). + * + * @param minDate The new minimum date (pass null for no minimum) + */ + public void setMinDate(Calendar minDate) { + if (minDate != null) { + minDate.set(Calendar.HOUR_OF_DAY, 0); + minDate.set(Calendar.MINUTE, 0); + minDate.set(Calendar.SECOND, 0); + minDate.set(Calendar.MILLISECOND, 0); + if (mMaxDate != null && minDate.after(mMaxDate)) { + throw new IllegalArgumentException("minDate cannot be later than maxDate"); + } + } + + mMinDate = minDate; + resetHomeDate(); + mCurrentOrigin.x = 0; + invalidate(); + } + + /** + * Get the latest day that can be displayed. Will return null if no maximum date is set. + * + * @return the latest day the can be displayed, null if no max date set + */ + public Calendar getMaxDate() { + return mMaxDate; + } + + /** + * Set the latest day that can be displayed. This will determine the right horizontal scroll + * limit. The default value is null (allow unlimited scrolling in to the future). + * + * @param maxDate The new maximum date (pass null for no maximum) + */ + public void setMaxDate(Calendar maxDate) { + if (maxDate != null) { + maxDate.set(Calendar.HOUR_OF_DAY, 0); + maxDate.set(Calendar.MINUTE, 0); + maxDate.set(Calendar.SECOND, 0); + maxDate.set(Calendar.MILLISECOND, 0); + if (mMinDate != null && maxDate.before(mMinDate)) { + throw new IllegalArgumentException("maxDate has to be after minDate"); + } + } + + mMaxDate = maxDate; + resetHomeDate(); + mCurrentOrigin.x = 0; + invalidate(); + } + + /** + * Whether weekends should have a background color different from the normal day background + * color. The weekend background colors are defined by the attributes + * `futureWeekendBackgroundColor` and `pastWeekendBackgroundColor`. + * + * @return True if weekends should have different background colors. + */ + public boolean isShowDistinctWeekendColor() { + return mShowDistinctWeekendColor; + } + + /** + * Set whether weekends should have a background color different from the normal day background + * color. The weekend background colors are defined by the attributes + * `futureWeekendBackgroundColor` and `pastWeekendBackgroundColor`. + * + * @param showDistinctWeekendColor True if weekends should have different background colors. + */ + public void setShowDistinctWeekendColor(boolean showDistinctWeekendColor) { + this.mShowDistinctWeekendColor = showDistinctWeekendColor; + invalidate(); + } + + /** + * auto calculate limit time on events in visible days. + */ + public void setAutoLimitTime(boolean isAuto) { + this.mAutoLimitTime = isAuto; + invalidate(); + } + + private void recalculateHourHeight() { + int height = (int) ((getHeight() - (mHeaderHeight + mHeaderRowPadding * 2 + mTimeTextHeight / 2 + mHeaderMarginBottom)) / (this.mMaxTime - this.mMinTime)); + if (height > mHourHeight) { + if (height > mMaxHourHeight) + mMaxHourHeight = height; + mNewHourHeight = height; + } + } + + /** + * Set visible time span. + * + * @param startHour limit time display on top (between 0~24) + * @param endHour limit time display at bottom (between 0~24 and larger than startHour) + */ + public void setLimitTime(int startHour, int endHour) { + if (endHour <= startHour) { + throw new IllegalArgumentException("endHour must larger startHour."); + } else if (startHour < 0) { + throw new IllegalArgumentException("startHour must be at least 0."); + } else if (endHour > 24) { + throw new IllegalArgumentException("endHour can't be higher than 24."); + } + this.mMinTime = startHour; + this.mMaxTime = endHour; + recalculateHourHeight(); + invalidate(); + } + + /** + * Set minimal shown time + * + * @param startHour limit time display on top (between 0~24) and smaller than endHour + */ + public void setMinTime(int startHour) { + if (mMaxTime <= startHour) { + throw new IllegalArgumentException("startHour must smaller than endHour"); + } else if (startHour < 0) { + throw new IllegalArgumentException("startHour must be at least 0."); + } + this.mMinTime = startHour; + recalculateHourHeight(); + } + + /** + * Set highest shown time + * + * @param endHour limit time display at bottom (between 0~24 and larger than startHour) + */ + public void setMaxTime(int endHour) { + if (endHour <= mMinTime) { + throw new IllegalArgumentException("endHour must larger startHour."); + } else if (endHour > 24) { + throw new IllegalArgumentException("endHour can't be higher than 24."); + } + this.mMaxTime = endHour; + recalculateHourHeight(); + invalidate(); + } + + /** + * Whether past and future days should have two different background colors. The past and + * future day colors are defined by the attributes `futureBackgroundColor` and + * `pastBackgroundColor`. + * + * @return True if past and future days should have two different background colors. + */ + public boolean isShowDistinctPastFutureColor() { + return mShowDistinctPastFutureColor; + } + + /** + * Set whether weekends should have a background color different from the normal day background + * color. The past and future day colors are defined by the attributes `futureBackgroundColor` + * and `pastBackgroundColor`. + * + * @param showDistinctPastFutureColor True if past and future should have two different + * background colors. + */ + public void setShowDistinctPastFutureColor(boolean showDistinctPastFutureColor) { + this.mShowDistinctPastFutureColor = showDistinctPastFutureColor; + invalidate(); + } + + /** + * Get whether "now" line should be displayed. "Now" line is defined by the attributes + * `nowLineColor` and `nowLineThickness`. + * + * @return True if "now" line should be displayed. + */ + public boolean isShowNowLine() { + return mShowNowLine; + } + + /** + * Set whether "now" line should be displayed. "Now" line is defined by the attributes + * `nowLineColor` and `nowLineThickness`. + * + * @param showNowLine True if "now" line should be displayed. + */ + public void setShowNowLine(boolean showNowLine) { + this.mShowNowLine = showNowLine; + invalidate(); + } + + /** + * Get the "now" line color. + * + * @return The color of the "now" line. + */ + public int getNowLineColor() { + return mNowLineColor; + } + + /** + * Set the "now" line color. + * + * @param nowLineColor The color of the "now" line. + */ + public void setNowLineColor(int nowLineColor) { + this.mNowLineColor = nowLineColor; + invalidate(); + } + + /** + * Get the "now" line thickness. + * + * @return The thickness of the "now" line. + */ + public int getNowLineThickness() { + return mNowLineThickness; + } + + /** + * Set the "now" line thickness. + * + * @param nowLineThickness The thickness of the "now" line. + */ + public void setNowLineThickness(int nowLineThickness) { + this.mNowLineThickness = nowLineThickness; + invalidate(); + } + + /** + * Get whether the week view should fling horizontally. + * + * @return True if the week view has horizontal fling enabled. + */ + public boolean isHorizontalFlingEnabled() { + return mHorizontalFlingEnabled; + } + + /** + * Set whether the week view should fling horizontally. + * + * @param enabled whether the week view should fling horizontally + */ + public void setHorizontalFlingEnabled(boolean enabled) { + mHorizontalFlingEnabled = enabled; + } + + /** + * Get whether the week view should fling vertically. + * + * @return True if the week view has vertical fling enabled. + */ + public boolean isVerticalFlingEnabled() { + return mVerticalFlingEnabled; + } + + /** + * Set whether the week view should fling vertically. + * + * @param enabled whether the week view should fling vertically + */ + public void setVerticalFlingEnabled(boolean enabled) { + mVerticalFlingEnabled = enabled; + } + + /** + * Get the height of AllDay-events. + * + * @return Height of AllDay-events. + */ + public int getAllDayEventHeight() { + return mAllDayEventHeight; + } + + /** + * Set the height of AllDay-events. + * + * @param height the new height of AllDay-events + */ + public void setAllDayEventHeight(int height) { + mAllDayEventHeight = height; + } + + /** + * Enable zoom focus point + * If you set this to false the `zoomFocusPoint` won't take effect any more while zooming. + * The zoom will always be focused at the center of your gesture. + * + * @param zoomFocusPointEnabled whether the zoomFocusPoint is enabled + */ + public void setZoomFocusPointEnabled(boolean zoomFocusPointEnabled) { + mZoomFocusPointEnabled = zoomFocusPointEnabled; + } + + /* + * Is focus point enabled + * @return fixed focus point enabled? + */ + public boolean isZoomFocusPointEnabled() { + return mZoomFocusPointEnabled; + } + + /* + * Get focus point + * 0 = top of view, 1 = bottom of view + * The focused point (multiplier of the view height) where the week view is zoomed around. + * This point will not move while zooming. + * @return focus point + */ + public float getZoomFocusPoint() { + return mZoomFocusPoint; + } + + /** + * Set focus point + * 0 = top of view, 1 = bottom of view + * The focused point (multiplier of the view height) where the week view is zoomed around. + * This point will not move while zooming. + * + * @param zoomFocusPoint the new zoomFocusPoint + */ + public void setZoomFocusPoint(float zoomFocusPoint) { + if (0 > zoomFocusPoint || zoomFocusPoint > 1) + throw new IllegalStateException("The zoom focus point percentage has to be between 0 and 1"); + mZoomFocusPoint = zoomFocusPoint; + } + + + /** + * Get scroll duration + * + * @return scroll duration + */ + public int getScrollDuration() { + return mScrollDuration; + } + + /** + * Set the scroll duration + * + * @param scrollDuration the new scrollDuraction + */ + public void setScrollDuration(int scrollDuration) { + mScrollDuration = scrollDuration; + } + + public int getMaxHourHeight() { + return mMaxHourHeight; + } + + public void setMaxHourHeight(int maxHourHeight) { + mMaxHourHeight = maxHourHeight; + } + + public int getMinHourHeight() { + return mMinHourHeight; + } + + public void setMinHourHeight(int minHourHeight) { + this.mMinHourHeight = minHourHeight; + } + + public int getPastBackgroundColor() { + return mPastBackgroundColor; + } + + public void setPastBackgroundColor(int pastBackgroundColor) { + this.mPastBackgroundColor = pastBackgroundColor; + mPastBackgroundPaint.setColor(mPastBackgroundColor); + } + + public int getFutureBackgroundColor() { + return mFutureBackgroundColor; + } + + public void setFutureBackgroundColor(int futureBackgroundColor) { + this.mFutureBackgroundColor = futureBackgroundColor; + mFutureBackgroundPaint.setColor(mFutureBackgroundColor); + } + + public int getPastWeekendBackgroundColor() { + return mPastWeekendBackgroundColor; + } + + public void setPastWeekendBackgroundColor(int pastWeekendBackgroundColor) { + this.mPastWeekendBackgroundColor = pastWeekendBackgroundColor; + this.mPastWeekendBackgroundPaint.setColor(mPastWeekendBackgroundColor); + } + + public int getFutureWeekendBackgroundColor() { + return mFutureWeekendBackgroundColor; + } + + public void setFutureWeekendBackgroundColor(int futureWeekendBackgroundColor) { + this.mFutureWeekendBackgroundColor = futureWeekendBackgroundColor; + this.mFutureWeekendBackgroundPaint.setColor(mFutureWeekendBackgroundColor); + } + + public Drawable getNewEventIconDrawable() { + return mNewEventIconDrawable; + } + + public void setNewEventIconDrawable(Drawable newEventIconDrawable) { + this.mNewEventIconDrawable = newEventIconDrawable; + } + + public void enableDropListener() { + this.mEnableDropListener = true; + //set drag and drop listener, required Honeycomb+ Api level + setOnDragListener(new DragListener()); + } + + public void disableDropListener() { + this.mEnableDropListener = false; + //set drag and drop listener, required Honeycomb+ Api level + setOnDragListener(null); + } + + public boolean isDropListenerEnabled() { + return this.mEnableDropListener; + } + + public void setMinOverlappingMinutes(int minutes) { + this.mMinOverlappingMinutes = minutes; + } + + public int getMinOverlappingMinutes() { + return this.mMinOverlappingMinutes; + } + + ///////////////////////////////////////////////////////////////// + // + // Functions related to scrolling. + // + ///////////////////////////////////////////////////////////////// + + @Override + public boolean onTouchEvent(MotionEvent event) { + mScaleDetector.onTouchEvent(event); + boolean val = mGestureDetector.onTouchEvent(event); + + // Check after call of mGestureDetector, so mCurrentFlingDirection and mCurrentScrollDirection are set. + if (event.getAction() == MotionEvent.ACTION_UP && !mIsZooming && mCurrentFlingDirection == Direction.NONE) { + if (mCurrentScrollDirection == Direction.RIGHT || mCurrentScrollDirection == Direction.LEFT) { + goToNearestOrigin(); + } + mCurrentScrollDirection = Direction.NONE; + } + + return val; + } + + private void goToNearestOrigin() { + double leftDays = mCurrentOrigin.x / (mWidthPerDay + mColumnGap); + + if (mCurrentFlingDirection != Direction.NONE) { + // snap to nearest day + leftDays = Math.round(leftDays); + } else if (mCurrentScrollDirection == Direction.LEFT) { + // snap to last day + leftDays = Math.floor(leftDays); + } else if (mCurrentScrollDirection == Direction.RIGHT) { + // snap to next day + leftDays = Math.ceil(leftDays); + } else { + // snap to nearest day + leftDays = Math.round(leftDays); + } + + int nearestOrigin = (int) (mCurrentOrigin.x - leftDays * (mWidthPerDay + mColumnGap)); + boolean mayScrollHorizontal = mCurrentOrigin.x - nearestOrigin < getXMaxLimit() + && mCurrentOrigin.x - nearestOrigin > getXMinLimit(); + + if (mayScrollHorizontal) { + mScroller.startScroll((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, -nearestOrigin, 0); + ViewCompat.postInvalidateOnAnimation(WeekView.this); + } + + if (nearestOrigin != 0 && mayScrollHorizontal) { + // Stop current animation. + mScroller.forceFinished(true); + // Snap to date. + mScroller.startScroll((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, -nearestOrigin, 0, (int) (Math.abs(nearestOrigin) / mWidthPerDay * mScrollDuration)); + ViewCompat.postInvalidateOnAnimation(WeekView.this); + } + // Reset scrolling and fling direction. + mCurrentScrollDirection = mCurrentFlingDirection = Direction.NONE; + } + + + @Override + public void computeScroll() { + super.computeScroll(); + + if (mScroller.isFinished()) { + if (mCurrentFlingDirection != Direction.NONE) { + // Snap to day after fling is finished. + goToNearestOrigin(); + } + } else { + if (mCurrentFlingDirection != Direction.NONE && forceFinishScroll()) { + goToNearestOrigin(); + } else if (mScroller.computeScrollOffset()) { + mCurrentOrigin.y = mScroller.getCurrY(); + mCurrentOrigin.x = mScroller.getCurrX(); + ViewCompat.postInvalidateOnAnimation(this); + } + } + } + + /** + * Check if scrolling should be stopped. + * + * @return true if scrolling should be stopped before reaching the end of animation. + */ + private boolean forceFinishScroll() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + // current velocity only available since api 14 + return mScroller.getCurrVelocity() <= mMinimumFlingVelocity; + } else { + return false; + } + } + + + ///////////////////////////////////////////////////////////////// + // + // Public methods. + // + ///////////////////////////////////////////////////////////////// + + /** + * Show today on the week view. + */ + public void goToToday() { + Calendar today = Calendar.getInstance(); + goToDate(today); + } + + /** + * Show a specific day on the week view. + * + * @param date The date to show. + */ + public void goToDate(Calendar date) { + mScroller.forceFinished(true); + mCurrentScrollDirection = mCurrentFlingDirection = Direction.NONE; + + date.set(Calendar.HOUR_OF_DAY, 0); + date.set(Calendar.MINUTE, 0); + date.set(Calendar.SECOND, 0); + date.set(Calendar.MILLISECOND, 0); + + if (mAreDimensionsInvalid) { + mScrollToDay = date; + return; + } + + mRefreshEvents = true; + + mCurrentOrigin.x = -daysBetween(mHomeDate, date) * (mWidthPerDay + mColumnGap); + invalidate(); + } + + /** + * Refreshes the view and loads the events again. + */ + public void notifyDatasetChanged() { + mRefreshEvents = true; + invalidate(); + } + + /** + * Vertically scroll to a specific hour in the week view. + * + * @param hour The hour to scroll to in 24-hour format. Supported values are 0-24. + */ + public void goToHour(double hour) { + if (mAreDimensionsInvalid) { + mScrollToHour = hour; + return; + } + + int verticalOffset = 0; + if (hour > mMaxTime) + verticalOffset = mHourHeight * (mMaxTime - mMinTime); + else if (hour > mMinTime) + verticalOffset = (int) (mHourHeight * hour); + + if (verticalOffset > mHourHeight * (mMaxTime - mMinTime) - getHeight() + mHeaderHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom) + verticalOffset = (int) (mHourHeight * (mMaxTime - mMinTime) - getHeight() + mHeaderHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom); + + mCurrentOrigin.y = -verticalOffset; + invalidate(); + } + + /** + * Get the first hour that is visible on the screen. + * + * @return The first hour that is visible. + */ + public double getFirstVisibleHour() { + return -mCurrentOrigin.y / mHourHeight; + } + + /** + * Determine whether a given calendar day falls within the scroll limits set for this view. + * + * @param day the day to check + * @return True if there are no limit or the date is within the limits. + * @see #setMinDate(Calendar) + * @see #setMaxDate(Calendar) + */ + public boolean dateIsValid(Calendar day) { + if (mMinDate != null && day.before(mMinDate)) { + return false; + } + if (mMaxDate != null && day.after(mMaxDate)) { + return false; + } + return true; + } + + ///////////////////////////////////////////////////////////////// + // + // Interfaces. + // + ///////////////////////////////////////////////////////////////// + + public interface DropListener { + /** + * Triggered when view dropped + * + * @param view: dropped view. + * @param date: object set with the date and time of the dropped coordinates on the view. + */ + void onDrop(View view, Calendar date); + } + + public interface EventClickListener { + /** + * Triggered when clicked on one existing event + * + * @param event: event clicked. + * @param eventRect: view containing the clicked event. + */ + void onEventClick(WeekViewEvent event, RectF eventRect); + } + + public interface EventLongPressListener { + /** + * Similar to {@link WeekView.EventClickListener} but with a long press. + * + * @param event: event clicked. + * @param eventRect: view containing the clicked event. + */ + void onEventLongPress(WeekViewEvent event, RectF eventRect); + } + + public interface EmptyViewClickListener { + /** + * Triggered when the users clicks on a empty space of the calendar. + * + * @param date: {@link Calendar} object set with the date and time of the clicked position on the view. + */ + void onEmptyViewClicked(Calendar date); + + } + + public interface EmptyViewLongPressListener { + /** + * Similar to {@link WeekView.EmptyViewClickListener} but with long press. + * + * @param time: {@link Calendar} object set with the date and time of the long pressed position on the view. + */ + void onEmptyViewLongPress(Calendar time); + } + + public interface ScrollListener { + /** + * Called when the first visible day has changed. + *
+ * (this will also be called during the first draw of the weekview)
+ *
+ * @param newFirstVisibleDay The new first visible day
+ * @param oldFirstVisibleDay The old first visible day (is null on the first call).
+ */
+ 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);
+ }
+
+ /**
+ * A simple GestureListener that holds the focused hour while scaling.
+ */
+ private class WeekViewGestureListener implements ScaleGestureDetector.OnScaleGestureListener {
+ float mFocusedPointY;
+
+ @Override
+ public void onScaleEnd(ScaleGestureDetector detector) {
+ mIsZooming = false;
+ }
+
+ @Override
+ public boolean onScaleBegin(ScaleGestureDetector detector) {
+ mIsZooming = true;
+ goToNearestOrigin();
+
+ // Calculate focused point for scale action
+ if (mZoomFocusPointEnabled) {
+ // Use fractional focus, percentage of height
+ mFocusedPointY = (getHeight() - mHeaderHeight - mHeaderRowPadding * 2 - mHeaderMarginBottom) * mZoomFocusPoint;
+ } else {
+ // Grab focus
+ mFocusedPointY = detector.getFocusY();
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean onScale(ScaleGestureDetector detector) {
+ final float scale = detector.getScaleFactor();
+
+ mNewHourHeight = Math.round(mHourHeight * scale);
+
+ // Calculating difference
+ float diffY = mFocusedPointY - mCurrentOrigin.y;
+ // Scaling difference
+ diffY = diffY * scale - diffY;
+ // Updating week view origin
+ mCurrentOrigin.y -= diffY;
+
+ invalidate();
+ return true;
+ }
+
+ }
+
+ @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
+ private class DragListener implements OnDragListener {
+ @Override
+ public boolean onDrag(View v, DragEvent e) {
+ switch (e.getAction()) {
+ case DragEvent.ACTION_DROP:
+ if (e.getX() > mHeaderColumnWidth && e.getY() > (mHeaderTextHeight + mHeaderRowPadding * 2 + mHeaderMarginBottom)) {
+ Calendar selectedTime = getTimeFromPoint(e.getX(), e.getY());
+ if (selectedTime != null) {
+ mDropListener.onDrop(v, selectedTime);
+ }
+ }
+ break;
+ }
+ return true;
+ }
+ }
+}
diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/WeekViewEvent.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/WeekViewEvent.java
new file mode 100644
index 0000000..3d279a7
--- /dev/null
+++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/WeekViewEvent.java
@@ -0,0 +1,344 @@
+package de.sebse.fuplanner.tools.ui.weekview;
+
+import android.graphics.Shader;
+import android.support.annotation.ColorInt;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.List;
+
+import static de.sebse.fuplanner.tools.ui.weekview.WeekViewUtil.isSameDay;
+
+
+/**
+ * Created by Raquib-ul-Alam Kanak on 7/21/2014.
+ * Website: http://april-shower.com
+ */
+public class WeekViewEvent {
+ private String mId;
+ private Calendar mStartTime;
+ private Calendar mEndTime;
+ private String mName;
+ private String mLocation;
+ private
+ @ColorInt
+ int mColor;
+ private boolean mAllDay;
+ private Shader mShader;
+
+ public WeekViewEvent() {
+
+ }
+
+ /**
+ * Initializes the event for week view.
+ *
+ * @param id The id of the event as String.
+ * @param name Name of the event.
+ * @param startYear Year when the event starts.
+ * @param startMonth Month when the event starts.
+ * @param startDay Day when the event starts.
+ * @param startHour Hour (in 24-hour format) when the event starts.
+ * @param startMinute Minute when the event starts.
+ * @param endYear Year when the event ends.
+ * @param endMonth Month when the event ends.
+ * @param endDay Day when the event ends.
+ * @param endHour Hour (in 24-hour format) when the event ends.
+ * @param endMinute Minute when the event ends.
+ */
+ public WeekViewEvent(String id, String name, int startYear, int startMonth, int startDay, int startHour, int startMinute, int endYear, int endMonth, int endDay, int endHour, int endMinute) {
+ this.mId = id;
+
+ this.mStartTime = Calendar.getInstance();
+ this.mStartTime.set(Calendar.YEAR, startYear);
+ this.mStartTime.set(Calendar.MONTH, startMonth - 1);
+ this.mStartTime.set(Calendar.DAY_OF_MONTH, startDay);
+ this.mStartTime.set(Calendar.HOUR_OF_DAY, startHour);
+ this.mStartTime.set(Calendar.MINUTE, startMinute);
+
+ this.mEndTime = Calendar.getInstance();
+ this.mEndTime.set(Calendar.YEAR, endYear);
+ this.mEndTime.set(Calendar.MONTH, endMonth - 1);
+ this.mEndTime.set(Calendar.DAY_OF_MONTH, endDay);
+ this.mEndTime.set(Calendar.HOUR_OF_DAY, endHour);
+ this.mEndTime.set(Calendar.MINUTE, endMinute);
+
+ this.mName = name;
+ }
+
+ /**
+ * Initializes the event for week view.
+ *
+ * @param id The id of the event.
+ * @param name Name of the event.
+ * @param startYear Year when the event starts.
+ * @param startMonth Month when the event starts.
+ * @param startDay Day when the event starts.
+ * @param startHour Hour (in 24-hour format) when the event starts.
+ * @param startMinute Minute when the event starts.
+ * @param endYear Year when the event ends.
+ * @param endMonth Month when the event ends.
+ * @param endDay Day when the event ends.
+ * @param endHour Hour (in 24-hour format) when the event ends.
+ * @param endMinute Minute when the event ends.
+ */
+ @Deprecated
+ public WeekViewEvent(long id, String name, int startYear, int startMonth, int startDay, int startHour, int startMinute, int endYear, int endMonth, int endDay, int endHour, int endMinute) {
+ this(String.valueOf(id), name, startYear, startMonth, startDay, startHour, startMinute, endYear, endMonth, endDay, endHour, endMinute);
+ }
+
+ /**
+ * Initializes the event for week view.
+ *
+ * @param id The id of the event as String.
+ * @param name Name of the event.
+ * @param location The location of the event.
+ * @param startTime The time when the event starts.
+ * @param endTime The time when the event ends.
+ * @param allDay Is the event an all day event.
+ * @param shader the Shader of the event rectangle
+ */
+ public WeekViewEvent(String id, String name, String location, Calendar startTime, Calendar endTime, boolean allDay, Shader shader) {
+ this.mId = id;
+ this.mName = name;
+ this.mLocation = location;
+ this.mStartTime = startTime;
+ this.mEndTime = endTime;
+ this.mAllDay = allDay;
+ this.mShader = shader;
+ }
+
+ /**
+ * Initializes the event for week view.
+ *
+ * @param id The id of the event.
+ * @param name Name of the event.
+ * @param location The location of the event.
+ * @param startTime The time when the event starts.
+ * @param endTime The time when the event ends.
+ * @param allDay Is the event an all day event.
+ * @param shader the Shader of the event rectangle
+ */
+ @Deprecated
+ public WeekViewEvent(long id, String name, String location, Calendar startTime, Calendar endTime, boolean allDay, Shader shader) {
+ this(String.valueOf(id), name, location, startTime, endTime, allDay, shader);
+ }
+
+ /**
+ * Initializes the event for week view.
+ *
+ * @param id The id of the event as String.
+ * @param name Name of the event.
+ * @param location The location of the event.
+ * @param startTime The time when the event starts.
+ * @param endTime The time when the event ends.
+ * @param allDay Is the event an all day event
+ */
+ public WeekViewEvent(String id, String name, String location, Calendar startTime, Calendar endTime, boolean allDay) {
+ this(id, name, location, startTime, endTime, allDay, null);
+ }
+
+ /**
+ * Initializes the event for week view.
+ *
+ * @param id The id of the event.
+ * @param name Name of the event.
+ * @param location The location of the event.
+ * @param startTime The time when the event starts.
+ * @param endTime The time when the event ends.
+ * @param allDay Is the event an all day event
+ */
+ @Deprecated
+ public WeekViewEvent(long id, String name, String location, Calendar startTime, Calendar endTime, boolean allDay) {
+ this(id, name, location, startTime, endTime, allDay, null);
+ }
+
+ /**
+ * Initializes the event for week view.
+ *
+ * @param id The id of the event as String.
+ * @param name Name of the event.
+ * @param location The location of the event.
+ * @param startTime The time when the event starts.
+ * @param endTime The time when the event ends.
+ */
+ public WeekViewEvent(String id, String name, String location, Calendar startTime, Calendar endTime) {
+ this(id, name, location, startTime, endTime, false);
+ }
+
+ /**
+ * Initializes the event for week view.
+ *
+ * @param id The id of the event.
+ * @param name Name of the event.
+ * @param location The location of the event.
+ * @param startTime The time when the event starts.
+ * @param endTime The time when the event ends.
+ */
+ @Deprecated
+ public WeekViewEvent(long id, String name, String location, Calendar startTime, Calendar endTime) {
+ this(id, name, location, startTime, endTime, false);
+ }
+
+ /**
+ * Initializes the event for week view.
+ *
+ * @param id The id of the event specified as String.
+ * @param name Name of the event.
+ * @param startTime The time when the event starts.
+ * @param endTime The time when the event ends.
+ */
+ public WeekViewEvent(String id, String name, Calendar startTime, Calendar endTime) {
+ this(id, name, null, startTime, endTime);
+ }
+
+ /**
+ * Initializes the event for week view.
+ *
+ * @param id The id of the event.
+ * @param name Name of the event.
+ * @param startTime The time when the event starts.
+ * @param endTime The time when the event ends.
+ */
+ @Deprecated
+ public WeekViewEvent(long id, String name, Calendar startTime, Calendar endTime) {
+ this(id, name, null, startTime, endTime);
+ }
+
+ public Calendar getStartTime() {
+ return mStartTime;
+ }
+
+ public void setStartTime(Calendar startTime) {
+ this.mStartTime = startTime;
+ }
+
+ public Calendar getEndTime() {
+ return mEndTime;
+ }
+
+ public void setEndTime(Calendar endTime) {
+ this.mEndTime = endTime;
+ }
+
+ public String getName() {
+ return mName;
+ }
+
+ public void setName(String name) {
+ this.mName = name;
+ }
+
+ public String getLocation() {
+ return mLocation;
+ }
+
+ public void setLocation(String location) {
+ this.mLocation = location;
+ }
+
+ public
+ @ColorInt
+ int getColor() {
+ return mColor;
+ }
+
+ public void setColor(int color) {
+ this.mColor = color;
+ }
+
+ public boolean isAllDay() {
+ return mAllDay;
+ }
+
+ public void setAllDay(boolean allDay) {
+ this.mAllDay = allDay;
+ }
+
+ public Shader getShader() {
+ return mShader;
+ }
+
+ public void setShader(Shader shader) {
+ mShader = shader;
+ }
+
+ public String getIdentifier() {
+ return mId;
+ }
+
+ @Deprecated
+ public long getId() {
+ return Long.parseLong(mId);
+ }
+
+ public void setIdentifier(String id) {
+ this.mId = id;
+ }
+
+ @Deprecated
+ public void setId(long id) {
+ this.mId = String.valueOf(id);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ WeekViewEvent that = (WeekViewEvent) o;
+
+ return mId.equals(that.mId);
+ }
+
+ @Override
+ public int hashCode() {
+ return mId.hashCode();
+ }
+
+ public List
+ * All periods that have the same integer part, define one period. Dates that are later in time
+ * should have a greater return value.
+ *
+ * @param instance the date
+ * @return The period index in which the date falls (floating point number).
+ */
+ double toWeekViewPeriodIndex(Calendar instance);
+
+ /**
+ * Load the events within the period
+ *
+ * @param periodIndex the period to load
+ * @return A list with the events of this period
+ */
+ List extends WeekViewEvent> onLoad(int periodIndex);
+}
diff --git a/app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/WeekViewUtil.java b/app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/WeekViewUtil.java
new file mode 100644
index 0000000..e05c7ca
--- /dev/null
+++ b/app/src/main/java/de/sebse/fuplanner/tools/ui/weekview/WeekViewUtil.java
@@ -0,0 +1,88 @@
+package de.sebse.fuplanner.tools.ui.weekview;
+
+import java.util.Calendar;
+
+/**
+ * Created by jesse on 6/02/2016.
+ */
+public class WeekViewUtil {
+
+
+ /////////////////////////////////////////////////////////////////
+ //
+ // Helper methods.
+ //
+ /////////////////////////////////////////////////////////////////
+
+ /**
+ * Checks if two dates are on the same day.
+ *
+ * @param dateOne The first date.
+ * @param dateTwo The second date. *
+ * @return Whether the dates are on the same day.
+ */
+ public static boolean isSameDay(Calendar dateOne, Calendar dateTwo) {
+ return dateOne.get(Calendar.YEAR) == dateTwo.get(Calendar.YEAR) && dateOne.get(Calendar.DAY_OF_YEAR) == dateTwo.get(Calendar.DAY_OF_YEAR);
+ }
+
+ /**
+ * Returns a calendar instance at the start of today
+ *
+ * @return the calendar instance
+ */
+ public static Calendar today() {
+ Calendar today = Calendar.getInstance();
+ today.set(Calendar.HOUR_OF_DAY, 0);
+ today.set(Calendar.MINUTE, 0);
+ today.set(Calendar.SECOND, 0);
+ today.set(Calendar.MILLISECOND, 0);
+ return today;
+ }
+
+ /**
+ * Checks if two dates are on the same day and hour.
+ *
+ * @param dateOne The first day.
+ * @param dateTwo The second day.
+ * @return Whether the dates are on the same day and hour.
+ */
+ public static boolean isSameDayAndHour(Calendar dateOne, Calendar dateTwo) {
+
+ if (dateTwo != null) {
+ return isSameDay(dateOne, dateTwo) && dateOne.get(Calendar.HOUR_OF_DAY) == dateTwo.get(Calendar.HOUR_OF_DAY);
+ }
+ return false;
+ }
+
+ /**
+ * Returns the amount of days between the second date and the first date
+ *
+ * @param dateOne the first date
+ * @param dateTwo the second date
+ * @return the amount of days between dateTwo and dateOne
+ */
+ public static int daysBetween(Calendar dateOne, Calendar dateTwo) {
+ return (int) (((dateTwo.getTimeInMillis() + dateTwo.getTimeZone().getOffset(dateTwo.getTimeInMillis())) / (1000 * 60 * 60 * 24)) -
+ ((dateOne.getTimeInMillis() + dateOne.getTimeZone().getOffset(dateOne.getTimeInMillis())) / (1000 * 60 * 60 * 24)));
+ }
+
+ /*
+ * Returns the amount of minutes passed in the day before the time in the given date
+ * @param date
+ * @return amount of minutes in day before time
+ */
+ public static int getPassedMinutesInDay(Calendar date) {
+ return getPassedMinutesInDay(date.get(Calendar.HOUR_OF_DAY), date.get(Calendar.MINUTE));
+ }
+
+ /**
+ * Returns the amount of minutes in the given hours and minutes
+ *
+ * @param hour
+ * @param minute
+ * @return amount of minutes in the given hours and minutes
+ */
+ public static int getPassedMinutesInDay(int hour, int minute) {
+ return hour * 60 + minute;
+ }
+}
diff --git a/app/src/main/res/layout/fragment_schedule.xml b/app/src/main/res/layout/fragment_schedule.xml
index cfba93e..994fa9e 100644
--- a/app/src/main/res/layout/fragment_schedule.xml
+++ b/app/src/main/res/layout/fragment_schedule.xml
@@ -9,11 +9,11 @@
-