Skip to content
Open

Tags #32

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
2 changes: 1 addition & 1 deletion QVRWeekView.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

Pod::Spec.new do |s|
s.name = 'QVRWeekView'
s.version = '0.14.2'
s.version = '0.15.0'
s.summary = 'QVRWeekView is a simple calendar week view with support for horizontal, vertical scrolling and zooming.'
s.swift_version = '5'

Expand Down
Empty file removed QVRWeekView/Assets/.gitkeep
Empty file.
13 changes: 13 additions & 0 deletions QVRWeekView/Classes/Common/Constants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,19 @@ struct LayoutDefaults {
static let passedWeekendDayViewColor = UIColor(red: 228/255, green: 228/255, blue: 228/255, alpha: 1.0)
// Color for today's view cell.
static let todayViewColor = defaultDayViewColor

// MARK: - TAG DEFAULTS -

// Default tag height
static let tagHeight = CGFloat(18)
// Default tag spacing (horizontal gap between tags)
static let tagSpacing = CGFloat(4)
// Default tag corner radius
static let tagCornerRadius = CGFloat(9)
// Default tag text size
static let tagTextSize = CGFloat(10)
// Default tag vertical margin (distance from bottom of event)
static let tagVerticalMargin = CGFloat(4)
}

struct NibNames {
Expand Down
62 changes: 62 additions & 0 deletions QVRWeekView/Classes/Common/Customization.swift
Original file line number Diff line number Diff line change
Expand Up @@ -482,4 +482,66 @@ public extension WeekView {
self.dayScrollView.horizontalScrolling = option
}
}

// MARK: - TAG CUSTOMIZATION -

/**
Height of tags in event cells.
*/
@objc var dayViewTagHeight: CGFloat {
get {
return self.dayScrollView.dayViewCellLayout.tagHeight
}
set(height) {
self.dayScrollView.dayViewCellLayout.tagHeight = height
}
}

/**
Horizontal spacing between tags.
*/
@objc var dayViewTagSpacing: CGFloat {
get {
return self.dayScrollView.dayViewCellLayout.tagSpacing
}
set(spacing) {
self.dayScrollView.dayViewCellLayout.tagSpacing = spacing
}
}

/**
Corner radius of tags.
*/
@objc var dayViewTagCornerRadius: CGFloat {
get {
return self.dayScrollView.dayViewCellLayout.tagCornerRadius
}
set(radius) {
self.dayScrollView.dayViewCellLayout.tagCornerRadius = radius
}
}

/**
Font size of tag text.
*/
@objc var dayViewTagTextSize: CGFloat {
get {
return self.dayScrollView.dayViewCellLayout.tagTextSize
}
set(size) {
self.dayScrollView.dayViewCellLayout.tagTextSize = size
}
}

/**
Vertical margin between tag and bottom of event.
*/
@objc var dayViewTagVerticalMargin: CGFloat {
get {
return self.dayScrollView.dayViewCellLayout.tagVerticalMargin
}
set(margin) {
self.dayScrollView.dayViewCellLayout.tagVerticalMargin = margin
}
}
}
13 changes: 13 additions & 0 deletions QVRWeekView/Classes/Common/DayViewCellLayout.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,17 @@ class DayViewCellLayout {
var previewEventMinutePrecision: Double = LayoutDefaults.previewEventPrecisionInMinutes { didSet { update?() } }
// Height of the preview event in hours.
var previewEventHourHeight: Double = LayoutDefaults.previewEventHeightInHours { didSet { update?() } }

// MARK: - TAG PROPERTIES -

// Height of tags
var tagHeight: CGFloat = LayoutDefaults.tagHeight { didSet { update?() } }
// Horizontal spacing between tags
var tagSpacing: CGFloat = LayoutDefaults.tagSpacing { didSet { update?() } }
// Corner radius of tags
var tagCornerRadius: CGFloat = LayoutDefaults.tagCornerRadius { didSet { update?() } }
// Font size of tag text
var tagTextSize: CGFloat = LayoutDefaults.tagTextSize { didSet { update?() } }
// Vertical margin between tag and bottom of event
var tagVerticalMargin: CGFloat = LayoutDefaults.tagVerticalMargin { didSet { update?() } }
}
56 changes: 49 additions & 7 deletions QVRWeekView/Classes/Common/EventData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@

import Foundation

/**
Represents a single tag with its associated color
*/
public struct EventTag {
public let name: String
public let color: UIColor

public init(name: String, color: UIColor) {
self.name = name
self.color = color
}
}

/**
Class event data stores basic data needed by the rest of the code to calculate and draw events in the dayViewCells in the dayScrollView.
*/
Expand All @@ -26,6 +39,8 @@ open class EventData: NSObject, NSCoding {
public let color: UIColor
// Stores if event is an all day event
public let allDay: Bool
// Tags associated with the event with their colors
public let eventTags: [EventTag]
// Stores an optional gradient layer which will be used to draw event. Can only be set once.
private(set) var gradientLayer: CAGradientLayer? { didSet { gradientLayer = oldValue ?? gradientLayer } }

Expand All @@ -37,12 +52,13 @@ open class EventData: NSObject, NSCoding {
/**
Main initializer. All properties.
*/
public init(id: String, title: String, startDate: Date, endDate: Date, location: String, color: UIColor, allDay: Bool, gradientLayer: CAGradientLayer? = nil) {
public init(id: String, title: String, startDate: Date, endDate: Date, location: String, color: UIColor, allDay: Bool, eventTags: [EventTag] = [], gradientLayer: CAGradientLayer? = nil) {
self.id = id
self.title = title
self.location = location
self.color = color
self.allDay = allDay
self.eventTags = eventTags
guard startDate.compare(endDate).rawValue <= 0 else {
self.startDate = startDate
self.endDate = startDate
Expand Down Expand Up @@ -119,6 +135,11 @@ open class EventData: NSObject, NSCoding {
coder.encode(location, forKey: EventDataEncoderKey.location)
coder.encode(color, forKey: EventDataEncoderKey.color)
coder.encode(allDay, forKey: EventDataEncoderKey.allDay)
// Encode tags back to arrays for backward compatibility
let tagNames = eventTags.map { $0.name }
let tagColors = eventTags.map { $0.color }
coder.encode(tagNames, forKey: EventDataEncoderKey.tags)
coder.encode(tagColors, forKey: "tagColors")
coder.encode(gradientLayer, forKey: EventDataEncoderKey.gradientLayer)
}

Expand All @@ -131,13 +152,22 @@ open class EventData: NSObject, NSCoding {
let dColor = coder.decodeObject(forKey: EventDataEncoderKey.color) as? UIColor {
let dGradientLayer = coder.decodeObject(forKey: EventDataEncoderKey.gradientLayer) as? CAGradientLayer
let dAllDay = coder.decodeBool(forKey: EventDataEncoderKey.allDay)
let dTagNames = coder.decodeObject(forKey: EventDataEncoderKey.tags) as? [String] ?? []
let dTagColors = coder.decodeObject(forKey: "tagColors") as? [UIColor] ?? []
// Reconstruct EventTag objects from decoded arrays
var eventTags: [EventTag] = []
for i in 0..<dTagNames.count {
let color = i < dTagColors.count ? dTagColors[i] : UIColor.white
eventTags.append(EventTag(name: dTagNames[i], color: color))
}
self.init(id: dId,
title: dTitle,
startDate: dStartDate,
endDate: dEndDate,
location: dLocation,
color: dColor,
allDay: dAllDay,
eventTags: eventTags,
gradientLayer: dGradientLayer)
} else {
return nil
Expand All @@ -152,7 +182,13 @@ open class EventData: NSObject, NSCoding {
(lhs.title == rhs.title) &&
(lhs.location == rhs.location) &&
(lhs.allDay == rhs.allDay) &&
(lhs.color.isEqual(rhs.color))
(lhs.color.isEqual(rhs.color)) &&
(lhs.eventTags.count == rhs.eventTags.count) &&
(lhs.eventTags.enumerated().allSatisfy { i, tag in
i < rhs.eventTags.count &&
tag.name == rhs.eventTags[i].name &&
tag.color.isEqual(rhs.eventTags[i].color)
})
}

public override var hash: Int {
Expand All @@ -167,8 +203,13 @@ open class EventData: NSObject, NSCoding {
open func getDisplayString(withMainFont mainFont: UIFont, infoFont: UIFont, andColor color: UIColor) -> NSAttributedString {
let df = DateFormatter()
df.dateFormat = "HH:mm"
let mainFontAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: mainFont, NSAttributedString.Key.foregroundColor: color.cgColor]
let infoFontAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: infoFont, NSAttributedString.Key.foregroundColor: color.cgColor]

// Use Montserrat Bold for title, Montserrat Medium for description
let titleFont = UIFont(name: "Montserrat-Bold", size: 12) ?? UIFont.boldSystemFont(ofSize: 12)
let descFont = UIFont(name: "Montserrat-Medium", size: 10) ?? UIFont.systemFont(ofSize: 10, weight: .medium)

let mainFontAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: titleFont, NSAttributedString.Key.foregroundColor: UIColor.white]
let infoFontAttributes: [NSAttributedString.Key: Any] = [NSAttributedString.Key.font: descFont, NSAttributedString.Key.foregroundColor: UIColor.white]
let mainAttributedString = NSMutableAttributedString(string: self.title, attributes: mainFontAttributes)
if !self.allDay {
mainAttributedString.append(NSMutableAttributedString(
Expand Down Expand Up @@ -204,19 +245,19 @@ open class EventData: NSObject, NSCoding {
}

public func remakeEventData(withStart start: Date, andEnd end: Date) -> EventData {
let newEvent = EventData(id: self.id, title: self.title, startDate: start, endDate: end, location: self.location, color: self.color, allDay: self.allDay)
let newEvent = EventData(id: self.id, title: self.title, startDate: start, endDate: end, location: self.location, color: self.color, allDay: self.allDay, eventTags: self.eventTags)
newEvent.configureGradient(self.gradientLayer)
return newEvent
}

public func remakeEventData(withColor color: UIColor) -> EventData {
let newEvent = EventData(id: self.id, title: self.title, startDate: self.startDate, endDate: self.endDate, location: self.location, color: color, allDay: self.allDay)
let newEvent = EventData(id: self.id, title: self.title, startDate: self.startDate, endDate: self.endDate, location: self.location, color: color, allDay: self.allDay, eventTags: self.eventTags)
newEvent.configureGradient(self.gradientLayer)
return newEvent
}

public func remakeEventDataAsAllDay(forDate date: Date) -> EventData {
let newEvent = EventData(id: self.id, title: self.title, startDate: date.getStartOfDay(), endDate: date.getEndOfDay(), location: self.location, color: self.color, allDay: true)
let newEvent = EventData(id: self.id, title: self.title, startDate: date.getStartOfDay(), endDate: date.getEndOfDay(), location: self.location, color: self.color, allDay: true, eventTags: self.eventTags)
newEvent.configureGradient(self.gradientLayer)
return newEvent
}
Expand Down Expand Up @@ -297,5 +338,6 @@ struct EventDataEncoderKey {
static let location = "EVENT_DATA_LOCATION"
static let color = "EVENT_DATA_COLOR"
static let allDay = "EVENT_DATA_ALL_DAY"
static let tags = "EVENT_DATA_TAGS"
static let gradientLayer = "EVENT_DATA_GRADIENT_LAYER"
}
Loading