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

Added support for working hours #24

Open
wants to merge 1 commit into
base: master
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
8 changes: 8 additions & 0 deletions JZCalendarWeekView.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
8EF7EBCD20A55C8E00D5CEEA /* JZAllDayCorner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EF7EBCC20A55C8E00D5CEEA /* JZAllDayCorner.swift */; };
8EF7EBCF20A55CF900D5CEEA /* JZAllDayHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EF7EBCE20A55CF900D5CEEA /* JZAllDayHeader.swift */; };
8EF7EBD120A55D1000D5CEEA /* JZAllDayHeaderBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8EF7EBD020A55D1000D5CEEA /* JZAllDayHeaderBackground.swift */; };
F84EDF81218287F4009FCA08 /* JZWorkDay.swift in Sources */ = {isa = PBXBuildFile; fileRef = F84EDF80218287F4009FCA08 /* JZWorkDay.swift */; };
F84EDF832182A505009FCA08 /* JZNonWorkingHoursBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = F84EDF822182A505009FCA08 /* JZNonWorkingHoursBackground.swift */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -75,6 +77,8 @@
8EF7EBCC20A55C8E00D5CEEA /* JZAllDayCorner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JZAllDayCorner.swift; sourceTree = "<group>"; };
8EF7EBCE20A55CF900D5CEEA /* JZAllDayHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JZAllDayHeader.swift; sourceTree = "<group>"; };
8EF7EBD020A55D1000D5CEEA /* JZAllDayHeaderBackground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JZAllDayHeaderBackground.swift; sourceTree = "<group>"; };
F84EDF80218287F4009FCA08 /* JZWorkDay.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JZWorkDay.swift; sourceTree = "<group>"; };
F84EDF822182A505009FCA08 /* JZNonWorkingHoursBackground.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JZNonWorkingHoursBackground.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -135,6 +139,7 @@
8E023C83206C732300C523BE /* JZBaseEvent.swift */,
8E40B2DF20B65C4600FFEB68 /* JZAllDayEvent.swift */,
8E1BA969206B5350007BE13C /* JZWeekViewHelper.swift */,
F84EDF80218287F4009FCA08 /* JZWorkDay.swift */,
8E1BA95C206B4AD9007BE13C /* ReusableViews */,
8E1BA955206B4687007BE13C /* Utils */,
8E1BA94D206B4329007BE13C /* JZCalendarWeekView.h */,
Expand Down Expand Up @@ -167,6 +172,7 @@
8EF7EBCC20A55C8E00D5CEEA /* JZAllDayCorner.swift */,
8EF7EBCE20A55CF900D5CEEA /* JZAllDayHeader.swift */,
8EF7EBD020A55D1000D5CEEA /* JZAllDayHeaderBackground.swift */,
F84EDF822182A505009FCA08 /* JZNonWorkingHoursBackground.swift */,
);
path = ReusableViews;
sourceTree = "<group>";
Expand Down Expand Up @@ -298,9 +304,11 @@
1FB6140D2130FE7400F08ACD /* JZCurrentTimelinePage.swift in Sources */,
8EF7EBCF20A55CF900D5CEEA /* JZAllDayHeader.swift in Sources */,
8E1BA95B206B4826007BE13C /* JZWeekViewFlowLayout.swift in Sources */,
F84EDF832182A505009FCA08 /* JZNonWorkingHoursBackground.swift in Sources */,
8E40B2E020B65C4600FFEB68 /* JZAllDayEvent.swift in Sources */,
8E1BA968206B4F40007BE13C /* JZCurrentTimelineSection.swift in Sources */,
8E1BA960206B4B84007BE13C /* JZColumnHeader.swift in Sources */,
F84EDF81218287F4009FCA08 /* JZWorkDay.swift in Sources */,
8E023C84206C732300C523BE /* JZBaseEvent.swift in Sources */,
8E1BA964206B4E82007BE13C /* JZCornerHeader.swift in Sources */,
8E1BA96E206B5B55007BE13C /* JZRowHeaderBackground.swift in Sources */,
Expand Down
8 changes: 7 additions & 1 deletion JZCalendarWeekView/JZBaseWeekView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ open class JZBaseWeekView: UIView {
}
}
public var firstDayOfWeek: DayOfWeek?
public var workDayForDate: ((_ date: Date) -> JZWorkDay?)?
public var allEventsBySection: [Date: [JZBaseEvent]]! {
didSet {
self.isAllDaySupported = allEventsBySection is [Date: [JZAllDayEvent]]
Expand Down Expand Up @@ -100,7 +101,7 @@ open class JZBaseWeekView: UIView {

// decoration
flowLayout.registerDecorationViews([JZColumnHeaderBackground.self, JZRowHeaderBackground.self,
JZAllDayHeaderBackground.self, JZAllDayCorner.self])
JZAllDayHeaderBackground.self, JZAllDayCorner.self, JZNonWorkingHoursBackground.self])
flowLayout.register(JZGridLine.self, forDecorationViewOfKind: JZDecorationViewKinds.verticalGridline)
flowLayout.register(JZGridLine.self, forDecorationViewOfKind: JZDecorationViewKinds.horizontalGridline)
}
Expand Down Expand Up @@ -541,6 +542,11 @@ extension JZBaseWeekView: WeekViewFlowLayoutDelegate {
return date!
}

public func collectionView(_ collectionView: UICollectionView, layout: JZWeekViewFlowLayout, workDayForSection section: Int) -> JZWorkDay? {
let date = Calendar.current.date(byAdding: .day, value: section, to: initDate)
return self.workDayForDate?(date!)
}

public func collectionView(_ collectionView: UICollectionView, layout: JZWeekViewFlowLayout, startTimeForItemAtIndexPath indexPath: IndexPath) -> Date {
let date = flowLayout.dateForColumnHeader(at: indexPath)

Expand Down
52 changes: 52 additions & 0 deletions JZCalendarWeekView/JZWeekViewFlowLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
public protocol WeekViewFlowLayoutDelegate: class {
/// Get the date for given section
func collectionView(_ collectionView: UICollectionView, layout: JZWeekViewFlowLayout, dayForSection section: Int) -> Date
/// Get the work day for given section
func collectionView(_ collectionView: UICollectionView, layout: JZWeekViewFlowLayout, workDayForSection section: Int) -> JZWorkDay?
/// Get the start time for given item indexPath
func collectionView(_ collectionView: UICollectionView, layout: JZWeekViewFlowLayout, startTimeForItemAtIndexPath indexPath: IndexPath) -> Date
/// Get the end time for given item indexPath
Expand Down Expand Up @@ -67,6 +69,7 @@ open class JZWeekViewFlowLayout: UICollectionViewFlowLayout {
var itemAttributes = AttDic()
var columnHeaderAttributes = AttDic()
var columnHeaderBackgroundAttributes = AttDic()
var nonWorkingHoursBackgroundAttributes = AttDic()
var rowHeaderAttributes = AttDic()
var rowHeaderBackgroundAttributes = AttDic()
var verticalGridlineAttributes = AttDic()
Expand Down Expand Up @@ -174,6 +177,7 @@ open class JZWeekViewFlowLayout: UICollectionViewFlowLayout {
allAttributes.append(contentsOf: columnHeaderBackgroundAttributes.values)
allAttributes.append(contentsOf: rowHeaderAttributes.values)
allAttributes.append(contentsOf: rowHeaderBackgroundAttributes.values)
allAttributes.append(contentsOf: nonWorkingHoursBackgroundAttributes.values)
allAttributes.append(contentsOf: verticalGridlineAttributes.values)
allAttributes.append(contentsOf: horizontalGridlineAttributes.values)
allAttributes.append(contentsOf: cornerHeaderAttributes.values)
Expand Down Expand Up @@ -288,6 +292,7 @@ open class JZWeekViewFlowLayout: UICollectionViewFlowLayout {
attributes.frame = CGRect(x: sectionMinX, y: columnHeaderMinY, width: sectionWidth, height: columnHeaderHeight)
attributes.zIndex = zIndexForElementKind(JZSupplementaryViewKinds.columnHeader)

layoutNonWorkingHoursBackgroundAttributes(section: section, sectionX: sectionMinX, calendarGridMinY: calendarGridMinY, sectionHeight: sectionHeight)
layoutVerticalGridLinesAttributes(section: section, sectionX: sectionMinX, calendarGridMinY: calendarGridMinY, sectionHeight: sectionHeight)
layoutItemsAttributes(section: section, sectionX: sectionMinX, calendarStartY: calendarGridMinY)
}
Expand Down Expand Up @@ -331,6 +336,48 @@ open class JZWeekViewFlowLayout: UICollectionViewFlowLayout {
currentSectionZ: zIndexForElementKind(JZSupplementaryViewKinds.eventCell))
}

func layoutNonWorkingHoursBackgroundAttributes(section: Int, sectionX: CGFloat, calendarGridMinY: CGFloat, sectionHeight: CGFloat) {
var attributes = UICollectionViewLayoutAttributes()

let workDay = delegate?.collectionView(collectionView!, layout: self, workDayForSection: section)
for hour in 0...23 {
(attributes, nonWorkingHoursBackgroundAttributes) = layoutAttributesForDecorationView(at: IndexPath(item: hour, section: section),
ofKind: JZDecorationViewKinds.nonWorkingHoursBackground,
withItemCache: nonWorkingHoursBackgroundAttributes)
if workDay != nil {
let nonWorkingHoursBackgroundMinX = nearbyint(sectionX - defaultGridThickness / 2.0)
var nonWorkingHoursBackgroundMinY = nearbyint(calendarGridMinY + (hourHeight * CGFloat(hour))) - (defaultGridThickness / 2.0)
let nonWorkingHoursBackgroundWidth = fmin(sectionWidth, collectionView!.frame.width)
var nonWorkingHoursBackgroundHeight: CGFloat = 0
if let day = delegate?.collectionView(collectionView!, layout: self, dayForSection: section) {
let startTime = day.startOfDay.addingTimeInterval(TimeInterval(hour) * 60 * 60)
let endTime = startTime.addingTimeInterval(60 * 60)
if startTime < workDay!.startTime || endTime > workDay!.endTime {
if (startTime < workDay!.startTime && endTime <= workDay!.startTime) || (startTime >= workDay!.endTime) {
nonWorkingHoursBackgroundHeight = hourHeight
}
else if (startTime < workDay!.startTime && endTime > workDay!.startTime) {
nonWorkingHoursBackgroundHeight = hourHeight - (hourHeight * CGFloat((workDay!.startTime.timeIntervalSince(startTime) / endTime.timeIntervalSince(startTime))))
}
else if (startTime > workDay!.startTime && endTime > workDay!.endTime) {
nonWorkingHoursBackgroundMinY += hourHeight * CGFloat((workDay!.endTime.timeIntervalSince(startTime) / endTime.timeIntervalSince(startTime)))
nonWorkingHoursBackgroundHeight = hourHeight - nonWorkingHoursBackgroundMinY
}
}
}
else {
fatalError()
}
attributes.frame = CGRect(x: nonWorkingHoursBackgroundMinX, y: nonWorkingHoursBackgroundMinY,
width: nonWorkingHoursBackgroundWidth, height: nonWorkingHoursBackgroundHeight)
}
else {
attributes.frame = .zero
}
attributes.zIndex = zIndexForElementKind(JZDecorationViewKinds.nonWorkingHoursBackground)
}
}

func layoutVerticalGridLinesAttributes(section: Int, sectionX: CGFloat, calendarGridMinY: CGFloat, sectionHeight: CGFloat) {
var attributes = UICollectionViewLayoutAttributes()

Expand Down Expand Up @@ -435,6 +482,8 @@ open class JZWeekViewFlowLayout: UICollectionViewFlowLayout {
return allDayHeaderBackgroundAttributes[indexPath]
case JZDecorationViewKinds.allDayCorner:
return allDayCornerAttributes[indexPath]
case JZDecorationViewKinds.nonWorkingHoursBackground:
return nonWorkingHoursBackgroundAttributes[indexPath]
default:
return nil
}
Expand Down Expand Up @@ -597,6 +646,7 @@ open class JZWeekViewFlowLayout: UICollectionViewFlowLayout {
rowHeaderAttributes.removeAll()
rowHeaderBackgroundAttributes.removeAll()
cornerHeaderAttributes.removeAll()
nonWorkingHoursBackgroundAttributes.removeAll()
itemAttributes.removeAll()
allAttributes.removeAll()

Expand Down Expand Up @@ -712,6 +762,8 @@ open class JZWeekViewFlowLayout: UICollectionViewFlowLayout {
return minBackgroundZ + 2
case JZDecorationViewKinds.verticalGridline:
return minBackgroundZ + 1
case JZDecorationViewKinds.nonWorkingHoursBackground:
return minBackgroundZ
default:
return minCellZ
}
Expand Down
1 change: 1 addition & 0 deletions JZCalendarWeekView/JZWeekViewHelper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public enum JZSupplementaryViewKinds {
public enum JZDecorationViewKinds {
public static let columnHeaderBackground = JZColumnHeaderBackground.className
public static let rowHeaderBackground = JZRowHeaderBackground.className
public static let nonWorkingHoursBackground = JZNonWorkingHoursBackground.className
public static let allDayHeaderBackground = JZAllDayHeaderBackground.className
public static let allDayCorner = JZAllDayCorner.className
public static let verticalGridline = "VerticalGridline"
Expand Down
21 changes: 21 additions & 0 deletions JZCalendarWeekView/JZWorkDay.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// JZWorkDay.swift
// JZCalendarWeekView
//
// Created by Stefan on 26/10/18.
// Copyright © 2018 Jeff Zhang. All rights reserved.
//

import Foundation

open class JZWorkDay: NSObject {

public var startTime: Date
public var endTime: Date

public init(startTime: Date, endTime: Date) {
self.startTime = startTime
self.endTime = endTime
}

}
23 changes: 23 additions & 0 deletions JZCalendarWeekView/ReusableViews/JZNonWorkingHoursBackground.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
//
// JZNonWorkingHoursBackground.swift
// JZCalendarWeekView
//
// Created by Stefan on 26/10/18.
// Copyright © 2018 Jeff Zhang. All rights reserved.
//

import Foundation

/// The background drawed on layout to outline non working hours
class JZNonWorkingHoursBackground: UICollectionReusableView {

public override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = JZWeekViewColors.nonWorkingHours
}

required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

}
1 change: 1 addition & 0 deletions JZCalendarWeekView/Utils/JZWeekViewColors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Foundation
/// cannot change for now, will implement theme in the future
class JZWeekViewColors {

class var nonWorkingHours: UIColor { return UIColor(hex: 0xF0F0F0) }
class var columnHeaderWeekday: UIColor { return UIColor(hex: 0x757575) }
class var columnHeaderDay: UIColor { return UIColor(hex: 0x757575) }
class var allDayHeader: UIColor { return UIColor(hex: 0x757575) }
Expand Down