ScheduleViewController.swift 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. // Copyright (C) 2016 Inigo Valentin
  2. //
  3. // This file is part of the Gasteizko Margolariak IOS app.
  4. //
  5. // The Gasteizko Margolariak IOS app is free software: you can
  6. // redistribute it and/or modify it under the terms of the
  7. // GNU General Public License as published by the Free Software
  8. // Foundation, either version 3 of the License, or (at your
  9. // option) any later version.
  10. //
  11. // The Gasteizko Margolariak IOS app is distributed in the
  12. // hope that it will be useful, but WITHOUT ANY WARRANTY;
  13. // without even the implied warranty of MERCHANTABILITY or
  14. // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
  15. // Public License for more details.
  16. //
  17. // You should have received a copy of the GNU General Public
  18. // License along with the Gasteizko Margolariak IOS app.
  19. // If not, see <http://www.gnu.org/licenses/>.
  20. import UIKit
  21. import CoreData
  22. /**
  23. The controller of the schedule view.
  24. */
  25. class ScheduleViewController: UIViewController, UIGestureRecognizerDelegate {
  26. // Outlets
  27. @IBOutlet weak var btPrev: UIButton!
  28. @IBOutlet weak var btNext: UIButton!
  29. @IBOutlet weak var lbDayNumber: UILabel!
  30. @IBOutlet weak var lbDayMonth: UILabel!
  31. @IBOutlet weak var lbDayName: UILabel!
  32. @IBOutlet weak var svScheduleList: UIStackView!
  33. var context: NSManagedObjectContext? = nil
  34. var lang: String? = nil
  35. var delegate: AppDelegate? = nil
  36. // Margolari schedule indicator
  37. var margolari: Bool = false
  38. // Day indicator
  39. var days: [String] = [String]()
  40. var selectedDay: Int = 0
  41. /**
  42. Gets the application context.
  43. :return: The application context.
  44. */
  45. func getContext () -> NSManagedObjectContext {
  46. return NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
  47. }
  48. /**
  49. Run when the app loads.
  50. */
  51. override func viewDidLoad() {
  52. NSLog(":SCHEDULECONTROLLER:LOG: Init schedule.")
  53. super.viewDidLoad()
  54. self.loadSchedule(margolari: margolari)
  55. //TODO Title
  56. // TODO Set button action
  57. //barButton.addTarget(self, action: #selector(self.back), for: .touchUpInside)
  58. }
  59. /**
  60. Returns to the main view controller.
  61. */
  62. func back() {
  63. NSLog(":SCHEDULECONTROLLER:DEBUG: Back")
  64. self.dismiss(animated: true, completion: nil)
  65. }
  66. /**
  67. Dispose of any resources that can be recreated.
  68. */
  69. override func didReceiveMemoryWarning() {
  70. super.didReceiveMemoryWarning()
  71. }
  72. /**
  73. Loads the schedule.
  74. */
  75. public func loadSchedule(margolari: Bool){
  76. NSLog(":SCHEDULECONTROLLER:DEBUG: Loading schedule: Margolariak \(margolari)")
  77. var rowcount = 0
  78. var row: RowSchedule
  79. var start: NSDate
  80. var title: String
  81. var text: String
  82. var locationId: Int
  83. var location: String
  84. self.context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
  85. self.delegate = UIApplication.shared.delegate as! AppDelegate
  86. self.lang = getLanguage()
  87. self.context?.persistentStoreCoordinator = self.delegate?.persistentStoreCoordinator
  88. // Get days
  89. let dayFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Festival_event")
  90. dayFetchRequest.propertiesToFetch = ["day"]
  91. if self.margolari == true{
  92. dayFetchRequest.predicate = NSPredicate(format: "gm = %i", 1)
  93. }
  94. else{
  95. dayFetchRequest.predicate = NSPredicate(format: "gm = %i", 0)
  96. }
  97. dayFetchRequest.returnsDistinctResults = true
  98. dayFetchRequest.resultType = NSFetchRequestResultType.dictionaryResultType
  99. do {
  100. let results = try self.context?.fetch(dayFetchRequest)
  101. let resultsDict = results as! [[String: String]]
  102. for r in resultsDict {
  103. self.days.append(r["name"]!)
  104. }
  105. }
  106. catch let err as NSError {
  107. NSLog(":SCHEDULECONTROLLER:ERROR: Error getting day list: \(err)")
  108. }
  109. // Select the day to show initially.
  110. // TODO: Check if any day corresponds to the current date.
  111. self.selectedDay = 0
  112. // Set listenerts for the arrow buttons
  113. let tapRecognizerPrevDay = UITapGestureRecognizer(target: self, action: #selector(prevDay(_:)))
  114. self.btPrev.isUserInteractionEnabled = true
  115. self.btPrev.addGestureRecognizer(tapRecognizerPrevDay)
  116. let tapRecognizerNextDay = UITapGestureRecognizer(target: self, action: #selector(nextDay(_:)))
  117. self.btNext.isUserInteractionEnabled = true
  118. self.btNext.addGestureRecognizer(tapRecognizerNextDay)
  119. loadDay()
  120. }
  121. /**
  122. Populates the schedule list with tehe events of the currently selected days.
  123. Usually there is no need to call this function manually.
  124. */
  125. func loadDay(){
  126. // TODO: Clear list.
  127. // TODO: Set toolbar elements.
  128. var rowcount = 0
  129. var row: RowSchedule
  130. var start: NSDate
  131. var title: String
  132. var text: String
  133. var locationId: Int
  134. var location: String
  135. let fetchRequest: NSFetchRequest<Festival_event> = Festival_event.fetchRequest()
  136. let sortDescriptor = NSSortDescriptor(key: "start", ascending: false)
  137. let sortDescriptors = [sortDescriptor]
  138. fetchRequest.sortDescriptors = sortDescriptors
  139. if margolari == true{
  140. fetchRequest.predicate = NSPredicate(format: "(gm = %i) AND (day = @)", argumentArray: [1, days[selectedDay]])
  141. }
  142. else{
  143. fetchRequest.predicate = NSPredicate(format: "(gm = %i) AND (day = @)", argumentArray: [0, days[selectedDay]])
  144. }
  145. do {
  146. // Get the result
  147. let searchResults = try self.context?.fetch(fetchRequest)
  148. NSLog(":SCHEDULECONTROLLER:DEBUG: Total events: \(searchResults?.count)")
  149. for r in searchResults as! [NSManagedObject] {
  150. title = r.value(forKey: "title_\(lang)") as! String
  151. if let tx = r.value(forKey: "description_\(lang)"){
  152. text = r.value(forKey: "description_\(lang)") as! String
  153. }
  154. else{
  155. text = ""
  156. }
  157. start = r.value(forKey: "start")! as! NSDate
  158. locationId = r.value(forKey: "place")! as! Int
  159. row = RowSchedule.init(s: "rowSchedule\(rowcount)", i: rowcount)
  160. row.setTitle(text: title)
  161. row.setText(text: text)
  162. row.setTime(dtime: start)
  163. // Get location info from Place entity
  164. let locationFetchRequest: NSFetchRequest<Place> = Place.fetchRequest()
  165. locationFetchRequest.predicate = NSPredicate(format: "id == %i", locationId)
  166. locationFetchRequest.fetchLimit = 1
  167. do{
  168. var locationSearchResults = try self.context?.fetch(locationFetchRequest)
  169. var locationR = locationSearchResults?[0]
  170. location = locationR?.value(forKey: "name_\(lang)")! as! String
  171. row.setLocation(text: location)
  172. } catch {
  173. NSLog(":SCHEDULECONTROLLER:ERROR: Error getting location: \(error)")
  174. }
  175. NSLog(":SCHEDULECONTROLLER:DEBUG: Adding row: height: \(row.frame.height)")
  176. svScheduleList.addArrangedSubview(row)
  177. rowcount = rowcount + 1
  178. }
  179. svScheduleList.setNeedsLayout()
  180. svScheduleList.layoutIfNeeded()
  181. } catch {
  182. NSLog(":SCHEDULECONTROLLER:ERROR: Error with request: \(error)")
  183. }
  184. }
  185. /**
  186. Shows the schedule of the next day
  187. :param: sender Event trigger.
  188. */
  189. func nextDay(_ sender:UITapGestureRecognizer? = nil){
  190. changeDay(increment: 1)
  191. }
  192. /**
  193. Shows the schedule of the previous day.
  194. :param: sender Event trigger.
  195. */
  196. func prevDay(_ sender:UITapGestureRecognizer? = nil){
  197. changeDay(increment: -1)
  198. }
  199. /**
  200. Changes the day by a fixed amount of days.
  201. Usualli called to move one step forward or backward.
  202. :param: increment Days to advance the schedule. Negative values to back it up.
  203. */
  204. func changeDay(increment: Int){
  205. selectedDay = selectedDay + increment
  206. if selectedDay <= -1{
  207. selectedDay = 0
  208. }
  209. if self.selectedDay >= self.days.count{
  210. selectedDay = (self.days.count - 1)
  211. }
  212. loadDay()
  213. }
  214. /**
  215. Gets the device language.
  216. :return: Two letter language code of the device.
  217. */
  218. func getLanguage() -> String{
  219. let pre = NSLocale.preferredLanguages[0].subStr(start: 0, end: 1)
  220. if(pre == "es" || pre == "en" || pre == "eu"){
  221. return pre
  222. }
  223. else{
  224. return "es"
  225. }
  226. }
  227. }