Bläddra i källkod

Offers shown in the La Blanca section. Improved schedule view.

Iñigo Valentin 9 år sedan
förälder
incheckning
11e72b4e2f

+ 8 - 0
app.xcodeproj/project.pbxproj

@@ -20,6 +20,8 @@
 		93294FF81E336FA000FDAF50 /* Entry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93294FF71E336FA000FDAF50 /* Entry.swift */; };
 		93294FFA1E337D0D00FDAF50 /* RowHomePastActivities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93294FF91E337D0D00FDAF50 /* RowHomePastActivities.swift */; };
 		935892D01E493C2300E1CD5F /* UIImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 935892CF1E493C2300E1CD5F /* UIImageView.swift */; };
+		935AE18C1ECE162C0055E71F /* RowLablancaOffer.xib in Resources */ = {isa = PBXBuildFile; fileRef = 935AE18B1ECE162B0055E71F /* RowLablancaOffer.xib */; };
+		935AE18E1ECE1F180055E71F /* RowLablancaOffer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 935AE18D1ECE1F180055E71F /* RowLablancaOffer.swift */; };
 		935D6E2D1E8678B700CED3A1 /* GalleryView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 935D6E2C1E8678B700CED3A1 /* GalleryView.xib */; };
 		935D6E2F1E86792000CED3A1 /* GalleryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 935D6E2E1E86792000CED3A1 /* GalleryView.swift */; };
 		935D6E311E867C5E00CED3A1 /* RowGallery.xib in Resources */ = {isa = PBXBuildFile; fileRef = 935D6E301E867C5E00CED3A1 /* RowGallery.xib */; };
@@ -72,6 +74,8 @@
 		93294FF71E336FA000FDAF50 /* Entry.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Entry.swift; sourceTree = "<group>"; };
 		93294FF91E337D0D00FDAF50 /* RowHomePastActivities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowHomePastActivities.swift; sourceTree = "<group>"; };
 		935892CF1E493C2300E1CD5F /* UIImageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIImageView.swift; sourceTree = "<group>"; };
+		935AE18B1ECE162B0055E71F /* RowLablancaOffer.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RowLablancaOffer.xib; sourceTree = "<group>"; };
+		935AE18D1ECE1F180055E71F /* RowLablancaOffer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowLablancaOffer.swift; sourceTree = "<group>"; };
 		935D6E2C1E8678B700CED3A1 /* GalleryView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = GalleryView.xib; sourceTree = "<group>"; };
 		935D6E2E1E86792000CED3A1 /* GalleryView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GalleryView.swift; sourceTree = "<group>"; };
 		935D6E301E867C5E00CED3A1 /* RowGallery.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RowGallery.xib; sourceTree = "<group>"; };
@@ -193,6 +197,8 @@
 				93E0C5F31EBE306900905811 /* ScheduleViewController.swift */,
 				93EB2F0B1EBF5AEB00F64186 /* RowSchedule.swift */,
 				93EB2F0D1EBF5BF500F64186 /* RowSchedule.xib */,
+				935AE18B1ECE162B0055E71F /* RowLablancaOffer.xib */,
+				935AE18D1ECE1F180055E71F /* RowLablancaOffer.swift */,
 			);
 			path = app;
 			sourceTree = "<group>";
@@ -279,6 +285,7 @@
 				93B84BA41D9C31AB006C0F67 /* Assets.xcassets in Resources */,
 				935D6E2D1E8678B700CED3A1 /* GalleryView.xib in Resources */,
 				93EB2F0E1EBF5BF500F64186 /* RowSchedule.xib in Resources */,
+				935AE18C1ECE162C0055E71F /* RowLablancaOffer.xib in Resources */,
 				93BAD2EE1E585578009DF853 /* RowHomeBlog.xib in Resources */,
 				9326C4F41EA51C39007DF2A4 /* RowLablancaDay.xib in Resources */,
 				935D6E311E867C5E00CED3A1 /* RowGallery.xib in Resources */,
@@ -320,6 +327,7 @@
 				936966ED1E98445200A11055 /* AlbumViewController.swift in Sources */,
 				93D9EA681DE342AC00089002 /* UIView.swift in Sources */,
 				938D211F1EA2306300C47EC3 /* LablancaView.swift in Sources */,
+				935AE18E1ECE1F180055E71F /* RowLablancaOffer.swift in Sources */,
 				93075C701E59D04A00396389 /* RowBlog.swift in Sources */,
 				93B408031D9ED44C000FBC99 /* MenuCollectionViewCell.swift in Sources */,
 				935D6E2F1E86792000CED3A1 /* GalleryView.swift in Sources */,

+ 85 - 11
app/LablancaView.swift

@@ -38,7 +38,6 @@ class LablancaView: UIView {
 	@IBOutlet weak var fDayList: UIStackView!	// Stack view to hold the single days price list.
 	
 	
-	
 	// App delegate
 	var delegate: AppDelegate? = nil
 	
@@ -80,7 +79,10 @@ class LablancaView: UIView {
 			showNoFestivals()
 		}
 	}
-	
+
+	/**
+	Displays the section to be shown while (and near) the La Blanca festivals.
+	*/	
 	func showFestivals(){
 		NSLog(":LABLANCA:LOG: Showing festivals section.")
 		self.nfWindow.isHidden = true
@@ -109,17 +111,21 @@ class LablancaView: UIView {
 				self.fText.text = r.value(forKey: "text_\(lang)") as! String?
 			}
 
-		} catch {
+		}
+		catch {
 			NSLog(":LABLANCA:ERROR: Error getting festivals info: \(error)")
 		}
 		
 		// Set up schedule buttons
-		let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(openSchedule(_:)))
+		let tapRecognizerSchedule = UITapGestureRecognizer(target: self, action: #selector(openSchedule(_:)))
 		fBtSchedule.isUserInteractionEnabled = true
-		fBtSchedule.addGestureRecognizer(tapRecognizer)
-		
+		fBtSchedule.addGestureRecognizer(tapRecognizerSchedule)
+		let tapRecognizerGMSchedule = UITapGestureRecognizer(target: self, action: #selector(openGMSchedule(_:)))
+		fBtGMSchedule.isUserInteractionEnabled = true
+		fBtGMSchedule.addGestureRecognizer(tapRecognizerGMSchedule)
+
 		
-		// Get info about the day prices.
+		// Get info about the days and offers.
 		let dateFormatter = DateFormatter()
 		dateFormatter.dateFormat = "yyyy-MM-dd"
 		dateFormatter.locale = Locale.init(identifier: "en_GB")
@@ -131,7 +137,51 @@ class LablancaView: UIView {
 		// Last date of year
 		dateString = "\(year)-12-31"
 		let eDate = dateFormatter.date(from: dateString)
-		
+
+		// Get offers
+		let offerFetchRequest: NSFetchRequest<Festival_offer> = Festival_offer.fetchRequest()
+		offerFetchRequest.predicate = NSPredicate(format: "year = %i", year)
+
+		do {
+
+			// Get info from festivals
+			let offerSearchResults = try context.fetch(offerFetchRequest)
+			
+			NSLog(":LABLANCA:DEBUG: \(offerSearchResults.count) offes found.")
+
+			var row: RowLablancaOffer
+			var count: Int = 0
+
+			for offer in offerSearchResults as [NSManagedObject]{
+
+				let name: String = offer.value(forKey: "name_\(lang)")! as! String
+				let price: Int = offer.value(forKey: "price")! as! Int
+				let description: String = offer.value(forKey: "description_\(lang)")! as! String
+
+				// Create the row and set data.
+				row = RowLablancaOffer.init(s: "rowLablancaOffer\(count)", i: count)
+				row.setName(name: name)
+				row.setPrice(price: price)
+				row.setDescription(description: description)
+
+				// Add the row
+				fOfferList.addArrangedSubview(row)
+				row.setNeedsLayout()
+				row.layoutIfNeeded()
+
+				// Hide the separator of the last row
+				if count == offerSearchResults.count - 1 {
+					row.hidSeparator()
+				}
+
+				count = count + 1
+			}
+
+		}
+		catch {
+			NSLog(":LABLANCA:ERROR: Error getting festival offers: \(error)")
+		}
+
 		// Get days
 		let dayFetchRequest: NSFetchRequest<Festival_day> = Festival_day.fetchRequest()
 		dayFetchRequest.predicate = NSPredicate(format: "(date >= %@) AND (date <= %@)", argumentArray: [sDate, eDate])
@@ -180,24 +230,48 @@ class LablancaView: UIView {
 		} catch {
 			NSLog(":LABLANCA:ERROR: Error getting festival days info: \(error)")
 		}
-		
-		
-		
 	}
 	
+
+	/**
+	Hides the view to be shown during (and near) the festivals.
+	*/
 	func showNoFestivals(){
 		NSLog(":LABLANCA:LOG: Showing no festivals section.")
 		self.fWindow.isHidden = true
 		// Nothing else to be done.
 	}
 	
+
+	/**
+  Commands the view controller to show the city schedule view.
+  :param: sender The view that triggered the event.
+  */
 	func openSchedule(_ sender:UITapGestureRecognizer? = nil){
 		NSLog(":LABLANCA:DEBUG: Getting delegate and showing schedule.")
 		let delegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate
 		delegate.controller?.showSchedule(margolari: false)
 		NSLog(":LABLANCA:DEBUG: Schedule should be shown.")
 	}
+
+
+	/**
+	Commands the view controller to show the Gasteizko Margolariak schedule view.
+	:param: sender The view that triggered the event.
+	*/
+	func openGMSchedule(_ sender:UITapGestureRecognizer? = nil){
+    NSLog(":LABLANCA:DEBUG: Getting delegate and showing GM schedule.")
+    let delegate: AppDelegate = UIApplication.shared.delegate as! AppDelegate
+    delegate.controller?.showSchedule(margolari: true)
+    NSLog(":LABLANCA:DEBUG: GM schedule should be shown.")
+  }
+
 	
+	/**
+	Gets the device language. The only recognized languages are Spanish, English and Basque.
+	If the device has another language, Spanish will be selected by default.
+	:return: Two-letter language code.
+	*/
 	func getLanguage() -> String{
 		let pre = NSLocale.preferredLanguages[0].subStr(start: 0, end: 1)
 		if(pre == "es" || pre == "en" || pre == "eu"){

+ 125 - 0
app/RowLablancaOffer.swift

@@ -0,0 +1,125 @@
+// Copyright (C) 2016 Inigo Valentin
+//
+// This file is part of the Gasteizko Margolariak IOS app.
+//
+// The Gasteizko Margolariak IOS app is free software: you can
+// redistribute it and/or modify it under the terms of the
+// GNU General Public License as published by the Free Software
+// Foundation, either version 3 of the License, or (at your
+// option) any later version.
+//
+// The Gasteizko Margolariak IOS app is distributed in the
+// hope that it will be useful, but WITHOUT ANY WARRANTY;
+// without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
+// Public License for more details.
+//
+// You should have received a copy of the GNU General Public
+// License along with the Gasteizko Margolariak IOS app.
+// If not, see <http://www.gnu.org/licenses/>.
+
+import Foundation
+import UIKit
+
+/**
+Extension of UIView to be formatted as sections.
+*/
+@IBDesignable class RowLablancaOffer: UIView {
+	
+	// Outlets
+	/*@IBOutlet weak var container: UIView!
+	@IBOutlet weak var number: UILabel!
+	@IBOutlet weak var month: UILabel!
+	@IBOutlet weak var name: UILabel!
+	@IBOutlet weak var price: UILabel!
+	@IBOutlet weak var separator: UIView!*/
+	@IBOutlet weak var vwContainer: UIView!
+	@IBOutlet weak var lbName: UILabel!
+	@IBOutlet weak var lbDescription: UILabel!
+	@IBOutlet weak var lbPrice: UILabel!
+	@IBOutlet weak var vwSeparator: UIView!
+	
+	
+	
+	
+	/**
+	Default constructor
+	*/
+	required init?(coder aDecoder: NSCoder) {
+		super.init(coder: aDecoder)
+	}
+	
+	/**
+	Loads the view from the xib with the same name as the class.
+	*/
+	private func loadViewFromNib() {
+		let bundle = Bundle(for: type(of: self))
+		let nib = UINib(nibName: String(describing: type(of: self)), bundle: bundle)
+		nib.instantiate(withOwner: self, options: nil).first as! UIView
+		
+		self.frame = self.bounds
+		self.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+		self.translatesAutoresizingMaskIntoConstraints = true
+		
+		self.vwContainer.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+		self.vwContainer.translatesAutoresizingMaskIntoConstraints = true
+		
+		self.vwContainer.frame = self.bounds
+		self.addSubview(self.vwContainer)
+		
+	}
+	
+	/**
+	Default constructor.
+	:param: s Custom identifier
+	:param: i Custom identifier
+	*/
+	init(s: String, i: Int) {
+		NSLog(":ROWLABLANCAOFFER:DEBUG: Init \(s), \(i)")
+		
+		super.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
+		loadViewFromNib()
+		self.frame = self.bounds
+		self.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+		self.translatesAutoresizingMaskIntoConstraints = true
+	}
+	
+	/**
+	Default constructor for the interface builder
+	*/
+	override init(frame: CGRect){
+		super.init(frame: frame)
+	}
+	
+	/**
+	Sets the name of the offer.
+	:param: name The name of the offer.
+	*/
+	func setName(name: String){
+		self.lbName.text = name
+	}
+	
+	/**
+	Sets the description of the offer.
+	:param: description The description of the offer.
+	*/
+	func setDescription(description: String){
+		self.lbDescription.text = description
+	}
+	
+	/**
+	Sets the price of the offer.
+	:param: price The description of the offer.
+	*/
+	func setPrice(price: Int){
+		self.lbPrice.text = "\(price) €"
+	}
+	
+	/**
+	Hiddes the separator bar.
+	*/
+	func hidSeparator(){
+		self.vwSeparator.alpha = 0
+	}
+	
+}

+ 89 - 0
app/RowLablancaOffer.xib

@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12120" systemVersion="16E195" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina4_7" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12088"/>
+        <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="RowLablancaOffer" customModule="app">
+            <connections>
+                <outlet property="lbDescription" destination="OZG-PW-52K" id="paE-nY-wpl"/>
+                <outlet property="lbName" destination="W8f-8e-Vh4" id="pZo-B2-bWg"/>
+                <outlet property="lbPrice" destination="t8q-un-0XX" id="biT-Px-FiR"/>
+                <outlet property="vwContainer" destination="PZc-6H-I81" id="3ZX-CR-yxx"/>
+                <outlet property="vwSeparator" destination="I6q-za-hiX" id="HSJ-us-lgx"/>
+            </connections>
+        </placeholder>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view contentMode="scaleToFill" id="iN0-l3-epB" customClass="RowLablancaOffer" customModule="app">
+            <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <subviews>
+                <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="PZc-6H-I81" userLabel="Container">
+                    <rect key="frame" x="0.0" y="278.5" width="375" height="110"/>
+                    <subviews>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Name" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="W8f-8e-Vh4" userLabel="Name">
+                            <rect key="frame" x="10" y="0.0" width="285" height="30"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="30" id="9HV-WP-2oH"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="boldSystem" pointSize="30"/>
+                            <nil key="textColor"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Description" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OZG-PW-52K" userLabel="Description">
+                            <rect key="frame" x="15" y="30" width="270" height="64"/>
+                            <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                            <nil key="textColor"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="60 E" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="t8q-un-0XX" userLabel="Price">
+                            <rect key="frame" x="295" y="0.0" width="70" height="110"/>
+                            <constraints>
+                                <constraint firstAttribute="width" constant="70" id="gbg-aG-Zmc"/>
+                            </constraints>
+                            <fontDescription key="fontDescription" type="boldSystem" pointSize="30"/>
+                            <color key="textColor" red="0.0" green="0.47058823529999999" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+                            <nil key="highlightedColor"/>
+                        </label>
+                        <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="I6q-za-hiX" userLabel="BSeparator">
+                            <rect key="frame" x="19" y="104" width="337.5" height="1"/>
+                            <color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
+                            <constraints>
+                                <constraint firstAttribute="height" constant="1" id="v4A-HT-auJ"/>
+                            </constraints>
+                        </view>
+                    </subviews>
+                    <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                    <constraints>
+                        <constraint firstAttribute="trailing" secondItem="t8q-un-0XX" secondAttribute="trailing" constant="10" id="0MW-XZ-qwo"/>
+                        <constraint firstAttribute="bottom" secondItem="t8q-un-0XX" secondAttribute="bottom" id="EUe-pN-c3o"/>
+                        <constraint firstAttribute="height" constant="110" id="GMt-Dq-C0S"/>
+                        <constraint firstItem="W8f-8e-Vh4" firstAttribute="top" secondItem="PZc-6H-I81" secondAttribute="top" id="LxG-fT-ndV"/>
+                        <constraint firstItem="OZG-PW-52K" firstAttribute="top" secondItem="W8f-8e-Vh4" secondAttribute="bottom" id="PUk-Sf-BmJ"/>
+                        <constraint firstItem="OZG-PW-52K" firstAttribute="trailing" secondItem="t8q-un-0XX" secondAttribute="leading" constant="-10" id="R2G-LD-nql"/>
+                        <constraint firstItem="t8q-un-0XX" firstAttribute="height" secondItem="PZc-6H-I81" secondAttribute="height" id="aJN-bs-o8J"/>
+                        <constraint firstItem="OZG-PW-52K" firstAttribute="bottom" secondItem="I6q-za-hiX" secondAttribute="top" constant="-10" id="iBu-xJ-9uF"/>
+                        <constraint firstItem="W8f-8e-Vh4" firstAttribute="trailing" secondItem="t8q-un-0XX" secondAttribute="leading" id="r4u-JN-4Ha"/>
+                        <constraint firstItem="W8f-8e-Vh4" firstAttribute="leading" secondItem="PZc-6H-I81" secondAttribute="leading" constant="10" id="tzL-MW-RWT"/>
+                        <constraint firstItem="OZG-PW-52K" firstAttribute="leading" secondItem="PZc-6H-I81" secondAttribute="leading" constant="15" id="vna-d2-mZd"/>
+                        <constraint firstAttribute="bottom" secondItem="I6q-za-hiX" secondAttribute="bottom" constant="5" id="wFz-ft-j8d"/>
+                        <constraint firstItem="I6q-za-hiX" firstAttribute="width" secondItem="PZc-6H-I81" secondAttribute="width" multiplier="0.9" id="zPU-dZ-XRD"/>
+                        <constraint firstItem="I6q-za-hiX" firstAttribute="centerX" secondItem="PZc-6H-I81" secondAttribute="centerX" id="zcK-G2-veL"/>
+                    </constraints>
+                </view>
+            </subviews>
+            <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+            <constraints>
+                <constraint firstItem="PZc-6H-I81" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="centerY" id="Ye8-Cc-AcG"/>
+                <constraint firstItem="PZc-6H-I81" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="njx-T3-y3a"/>
+                <constraint firstItem="PZc-6H-I81" firstAttribute="width" secondItem="iN0-l3-epB" secondAttribute="width" id="tJi-F1-Ydx"/>
+            </constraints>
+        </view>
+    </objects>
+</document>

+ 123 - 30
app/ScheduleViewController.swift

@@ -22,7 +22,7 @@ import UIKit
 import CoreData
 
 /**
-The view controller of the app.
+The controller of the schedule view.
 */
 class ScheduleViewController: UIViewController, UIGestureRecognizerDelegate {
 
@@ -34,12 +34,21 @@ class ScheduleViewController: UIViewController, UIGestureRecognizerDelegate {
 	@IBOutlet weak var lbDayName: UILabel!
 	@IBOutlet weak var svScheduleList: UIStackView!
 	
+	var context: NSManagedObjectContext? = nil
+	var lang: String? = nil
+	var delegate: AppDelegate? = nil
+	
 	// Margolari schedule indicator
 	var margolari: Bool = false
-	
-	// App delegate
-	var delegate: AppDelegate?
-	
+
+	// Day indicator
+	var days: [String] = [String]()
+	var selectedDay: Int = 0
+
+	/**
+	Gets the application context.
+	:return: The application context.
+	*/
 	func getContext () -> NSManagedObjectContext {
 		return NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
 	}
@@ -91,39 +100,91 @@ class ScheduleViewController: UIViewController, UIGestureRecognizerDelegate {
 		var locationId: Int
 		var location: String
 		
-		NSLog(":SCHEDULECONTROLLER:DEBUG: 1")
-		let context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
-		let appDelegate = UIApplication.shared.delegate as! AppDelegate
-		let lang : String = getLanguage()
-		NSLog(":SCHEDULECONTROLLER:DEBUG: 2")
-		context.persistentStoreCoordinator = appDelegate.persistentStoreCoordinator
+		self.context = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)
+		self.delegate = UIApplication.shared.delegate as! AppDelegate
+		self.lang = getLanguage()
+		self.context?.persistentStoreCoordinator = self.delegate?.persistentStoreCoordinator
+
+		// Get days
+		let dayFetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "Festival_event")
+		dayFetchRequest.propertiesToFetch = ["day"]
+		if self.margolari == true{
+			dayFetchRequest.predicate = NSPredicate(format: "gm = %i", 1)
+		}
+		else{
+			dayFetchRequest.predicate = NSPredicate(format: "gm = %i", 0)
+		}
+
+		dayFetchRequest.returnsDistinctResults = true
+		dayFetchRequest.resultType = NSFetchRequestResultType.dictionaryResultType
+
+		do {
+			let results = try self.context?.fetch(dayFetchRequest)
+
+				let resultsDict = results as! [[String: String]]
+				for r in resultsDict {
+					self.days.append(r["name"]!)
+				}
+
+		}
+		catch let err as NSError {
+			NSLog(":SCHEDULECONTROLLER:ERROR: Error getting day list: \(err)")
+		}
+
+		// Select the day to show initially.
+		// TODO: Check if any day corresponds to the current date.
+		self.selectedDay = 0
+
+		// Set listenerts for the arrow buttons
+		let tapRecognizerPrevDay = UITapGestureRecognizer(target: self, action: #selector(prevDay(_:)))
+		self.btPrev.isUserInteractionEnabled = true
+		self.btPrev.addGestureRecognizer(tapRecognizerPrevDay)
+		let tapRecognizerNextDay = UITapGestureRecognizer(target: self, action: #selector(nextDay(_:)))
+		self.btNext.isUserInteractionEnabled = true
+		self.btNext.addGestureRecognizer(tapRecognizerNextDay)
+
+	loadDay()
+
+	}
+
+
+	/**
+	Populates the schedule list with tehe events of the currently selected days.
+	Usually there is no need to call this function manually.
+	*/
+	func loadDay(){
+		
+		// TODO: Clear list.
+		// TODO: Set toolbar elements.
+		
+		var rowcount = 0
+		var row: RowSchedule
+		var start: NSDate
+		var title: String
+		var text: String
+		var locationId: Int
+		var location: String
+
 		let fetchRequest: NSFetchRequest<Festival_event> = Festival_event.fetchRequest()
 		let sortDescriptor = NSSortDescriptor(key: "start", ascending: false)
 		let sortDescriptors = [sortDescriptor]
-		NSLog(":SCHEDULECONTROLLER:DEBUG: 3")
 		fetchRequest.sortDescriptors = sortDescriptors
 		
 		if margolari == true{
-			fetchRequest.predicate = NSPredicate(format: "gm = %i", 1)
+			fetchRequest.predicate = NSPredicate(format: "(gm = %i) AND (day = @)", argumentArray: [1, days[selectedDay]])
 		}
 		else{
-			fetchRequest.predicate = NSPredicate(format: "gm = %i", 0)
+			fetchRequest.predicate = NSPredicate(format: "(gm = %i) AND (day = @)", argumentArray: [0, days[selectedDay]])
 		}
-		
-		// TODO: filter by date, not by number
-		fetchRequest.fetchLimit = 20
-		
-		NSLog(":SCHEDULECONTROLLER:DEBUG: 4")
-		
+				
 		do {
 			
 			// Get the result
-			let searchResults = try context.fetch(fetchRequest)
-			NSLog(":SCHEDULECONTROLLER:DEBUG: 5")
+			let searchResults = try self.context?.fetch(fetchRequest)
 			
-			NSLog(":SCHEDULECONTROLLER:DEBUG: Total events: \(searchResults.count)")
+			NSLog(":SCHEDULECONTROLLER:DEBUG: Total events: \(searchResults?.count)")
 			
-			for r in searchResults as [NSManagedObject] {
+			for r in searchResults as! [NSManagedObject] {
 				
 				title = r.value(forKey: "title_\(lang)") as! String
 				if let tx = r.value(forKey: "description_\(lang)"){
@@ -145,9 +206,9 @@ class ScheduleViewController: UIViewController, UIGestureRecognizerDelegate {
 				locationFetchRequest.predicate = NSPredicate(format: "id == %i", locationId)
 				locationFetchRequest.fetchLimit = 1
 				do{
-					var locationSearchResults = try context.fetch(locationFetchRequest)
-					var locationR = locationSearchResults[0]
-					location = locationR.value(forKey: "name_\(lang)")! as! String
+					var locationSearchResults = try self.context?.fetch(locationFetchRequest)
+					var locationR = locationSearchResults?[0]
+					location = locationR?.value(forKey: "name_\(lang)")! as! String
 					
 					row.setLocation(text: location)
 				} catch {
@@ -156,8 +217,6 @@ class ScheduleViewController: UIViewController, UIGestureRecognizerDelegate {
 				
 				NSLog(":SCHEDULECONTROLLER:DEBUG: Adding row: height: \(row.frame.height)")
 				svScheduleList.addArrangedSubview(row)
-				//row.setNeedsLayout()
-				//row.layoutIfNeeded()
 				
 				rowcount = rowcount + 1
 			}
@@ -170,6 +229,41 @@ class ScheduleViewController: UIViewController, UIGestureRecognizerDelegate {
 		}
 
 	}
+
+
+	/**
+	Shows the schedule of the next day
+	:param: sender Event trigger.
+	*/
+	func nextDay(_ sender:UITapGestureRecognizer? = nil){
+		changeDay(increment: 1)
+	}
+
+
+	/**
+	Shows the schedule of the previous day.
+	:param: sender Event trigger.
+	*/
+	func prevDay(_ sender:UITapGestureRecognizer? = nil){
+    changeDay(increment: -1)
+  }
+
+
+	/**
+	Changes the day by a fixed amount of days.
+	Usualli called to move one step forward or backward.
+	:param: increment Days to advance the schedule. Negative values to back it up.
+	*/
+	func changeDay(increment: Int){
+		selectedDay = selectedDay + increment
+		if selectedDay <= -1{
+			selectedDay = 0
+		}
+		if self.selectedDay >= self.days.count{
+			selectedDay = (self.days.count - 1)
+		}
+		loadDay()
+	}
 	
 	/**
 	Gets the device language.
@@ -186,4 +280,3 @@ class ScheduleViewController: UIViewController, UIGestureRecognizerDelegate {
 	}
 	
 }
-