added iOS source code
[wl-app.git] / iOS / Pods / FolioReaderKit / Vendor / SMSegmentView / SMSegmentView.swift
1 //
2 //  SMSegmentView.swift
3 //
4 //  Created by Si MA on 03/01/2015.
5 //  Copyright (c) 2015 Si Ma. All rights reserved.
6 //
7
8 import UIKit
9
10 /*
11   Keys for segment properties
12 */
13
14 // This is mainly for the top/bottom margin of the imageView
15 let keyContentVerticalMargin = "VerticalMargin"
16
17 // The colour when the segment is under selected/unselected
18 let keySegmentOnSelectionColour = "OnSelectionBackgroundColour"
19 let keySegmentOffSelectionColour = "OffSelectionBackgroundColour"
20
21 // The colour of the text in the segment for the segment is under selected/unselected
22 let keySegmentOnSelectionTextColour = "OnSelectionTextColour"
23 let keySegmentOffSelectionTextColour = "OffSelectionTextColour"
24
25 // The font of the text in the segment
26 let keySegmentTitleFont = "TitleFont"
27
28
29 enum SegmentOrganiseMode: Int {
30     case segmentOrganiseHorizontal = 0
31     case segmentOrganiseVertical
32 }
33
34
35 protocol SMSegmentViewDelegate: class {
36     func segmentView(_ segmentView: SMSegmentView, didSelectSegmentAtIndex index: Int)
37 }
38
39 class SMSegmentView: UIView, SMSegmentDelegate {
40     weak var delegate: SMSegmentViewDelegate?
41     
42     var indexOfSelectedSegment = NSNotFound
43     var numberOfSegments = 0
44     
45     var organiseMode: SegmentOrganiseMode = SegmentOrganiseMode.segmentOrganiseHorizontal {
46         didSet {
47             self.setNeedsDisplay()
48         }
49     }
50     
51     var segmentVerticalMargin: CGFloat = 5.0 {
52         didSet {
53             for segment in self.segments {
54                 segment.verticalMargin = self.segmentVerticalMargin
55             }
56         }
57     }
58     
59     // Segment Separator
60     var separatorColour: UIColor = UIColor.lightGray {
61         didSet {
62             self.setNeedsDisplay()
63         }
64     }
65     var separatorWidth: CGFloat = 1.0 {
66         didSet {
67             for segment in self.segments {
68                 segment.separatorWidth = self.separatorWidth
69             }
70             self.updateFrameForSegments()
71         }
72     }
73     
74     // Segment Colour
75     var segmentOnSelectionColour: UIColor = UIColor.darkGray {
76         didSet {
77             for segment in self.segments {
78                 segment.onSelectionColour = self.segmentOnSelectionColour
79             }
80         }
81     }
82     var segmentOffSelectionColour: UIColor = UIColor.white {
83         didSet {
84             for segment in self.segments {
85                 segment.offSelectionColour = self.segmentOffSelectionColour
86             }
87         }
88     }
89     
90     // Segment Title Text Colour & Font
91     var segmentOnSelectionTextColour: UIColor = UIColor.white {
92         didSet {
93             for segment in self.segments {
94                 segment.onSelectionTextColour = self.segmentOnSelectionTextColour
95             }
96         }
97     }
98     var segmentOffSelectionTextColour: UIColor = UIColor.darkGray {
99         didSet {
100             for segment in self.segments {
101                 segment.offSelectionTextColour = self.segmentOffSelectionTextColour
102             }
103         }
104     }
105     var segmentTitleFont: UIFont = UIFont.systemFont(ofSize: 17.0) {
106         didSet {
107             for segment in self.segments {
108                 segment.titleFont = self.segmentTitleFont
109             }
110         }
111     }
112     
113     override var frame: CGRect {
114         didSet {
115             self.updateFrameForSegments()
116         }
117     }
118     
119     var segments: Array<SMSegment> = Array()
120     
121     required init?(coder aDecoder: NSCoder) {
122         fatalError("init(coder:) has not been implemented")
123     }
124     
125     override init(frame: CGRect) {
126         super.init(frame: frame)
127         self.backgroundColor = UIColor.clear
128         self.layer.masksToBounds = true
129     }
130     
131     init(frame: CGRect, separatorColour: UIColor, separatorWidth: CGFloat, segmentProperties: Dictionary<String, AnyObject>?) {
132         self.separatorColour = separatorColour
133         self.separatorWidth = separatorWidth
134         
135         if let margin = segmentProperties?[keyContentVerticalMargin] as? Float {
136             self.segmentVerticalMargin = CGFloat(margin)
137         }
138         
139         if let onSelectionColour = segmentProperties?[keySegmentOnSelectionColour] as? UIColor {
140             self.segmentOnSelectionColour = onSelectionColour
141         }
142         else {
143             self.segmentOnSelectionColour = UIColor.darkGray
144         }
145         
146         if let offSelectionColour = segmentProperties?[keySegmentOffSelectionColour] as? UIColor {
147             self.segmentOffSelectionColour = offSelectionColour
148         }
149         else {
150             self.segmentOffSelectionColour = UIColor.white
151         }
152         
153         if let onSelectionTextColour = segmentProperties?[keySegmentOnSelectionTextColour] as? UIColor {
154             self.segmentOnSelectionTextColour = onSelectionTextColour
155         }
156         else {
157             self.segmentOnSelectionTextColour = UIColor.white
158         }
159         
160         if let offSelectionTextColour = segmentProperties?[keySegmentOffSelectionTextColour] as? UIColor {
161             self.segmentOffSelectionTextColour = offSelectionTextColour
162         }
163         else {
164             self.segmentOffSelectionTextColour = UIColor.darkGray
165         }
166         
167         if let titleFont = segmentProperties?[keySegmentTitleFont] as? UIFont {
168             self.segmentTitleFont = titleFont
169         }
170         else {
171             self.segmentTitleFont = UIFont.systemFont(ofSize: 17.0)
172         }
173         
174         super.init(frame: frame)
175         self.backgroundColor = UIColor.clear
176         self.layer.masksToBounds = true
177     }
178     
179     func addSegmentWithTitle(_ title: String?, onSelectionImage: UIImage?, offSelectionImage: UIImage?) {
180         
181         let segment = SMSegment(
182             separatorWidth: self.separatorWidth,
183             verticalMargin: self.segmentVerticalMargin,
184             onSelectionColour: self.segmentOnSelectionColour,
185             offSelectionColour: self.segmentOffSelectionColour,
186             onSelectionTextColour: self.segmentOnSelectionTextColour,
187             offSelectionTextColour: self.segmentOffSelectionTextColour,
188             titleFont: self.segmentTitleFont
189         )
190         segment.index = self.segments.count
191         self.segments.append(segment)
192         self.updateFrameForSegments()
193         
194         segment.delegate = self
195         segment.title = title
196         segment.onSelectionImage = onSelectionImage
197         segment.offSelectionImage = offSelectionImage
198         
199         self.addSubview(segment)
200         
201         self.numberOfSegments = self.segments.count
202     }
203     
204     func updateFrameForSegments() {
205         if self.segments.count == 0 {
206             return
207         }
208         
209         let count = self.segments.count
210         if count > 1 {
211             if self.organiseMode == SegmentOrganiseMode.segmentOrganiseHorizontal {
212                 let segmentWidth = (self.frame.size.width - self.separatorWidth*CGFloat(count-1)) / CGFloat(count)
213                 var originX: CGFloat = 0.0
214                 for segment in self.segments {
215                     segment.frame = CGRect(x: originX, y: 0.0, width: segmentWidth, height: self.frame.size.height)
216                     originX += segmentWidth + self.separatorWidth
217                 }
218             }
219             else {
220                 let segmentHeight = (self.frame.size.height - self.separatorWidth*CGFloat(count-1)) / CGFloat(count)
221                 var originY: CGFloat = 0.0
222                 for segment in self.segments {
223                     segment.frame = CGRect(x: 0.0, y: originY, width: self.frame.size.width, height: segmentHeight)
224                     originY += segmentHeight + self.separatorWidth
225                 }
226             }
227         }
228         else {
229             self.segments[0].frame = CGRect(x: 0.0, y: 0.0, width: self.frame.size.width, height: self.frame.size.height)
230         }
231         
232         self.setNeedsDisplay()
233     }
234     
235     // MARK: SMSegment Delegate
236     func selectSegment(_ segment: SMSegment) {
237         if self.indexOfSelectedSegment != NSNotFound {
238             let previousSelectedSegment = self.segments[self.indexOfSelectedSegment]
239             previousSelectedSegment.setSelected(false)
240         }
241         self.indexOfSelectedSegment = segment.index
242         segment.setSelected(true)
243         self.delegate?.segmentView(self, didSelectSegmentAtIndex: segment.index)
244     }
245     
246     // MARK: Actions
247     func selectSegmentAtIndex(_ index: Int) {
248         assert(index >= 0 && index < self.segments.count, "Index at \(index) is out of bounds")
249         self.selectSegment(self.segments[index])
250     }
251     
252     func deselectSegment() {
253         if self.indexOfSelectedSegment != NSNotFound {
254             let segment = self.segments[self.indexOfSelectedSegment]
255             segment.setSelected(false)
256             self.indexOfSelectedSegment = NSNotFound
257         }
258     }
259     
260     // MARK: Drawing Segment Separators
261     override func draw(_ rect: CGRect) {
262         let context = UIGraphicsGetCurrentContext()
263         self.drawSeparatorWithContext(context!)
264     }
265     
266     func drawSeparatorWithContext(_ context: CGContext) {
267         context.saveGState()
268         
269         if self.segments.count > 1 {
270             let path = CGMutablePath()
271             
272             if self.organiseMode == SegmentOrganiseMode.segmentOrganiseHorizontal {
273                 var originX: CGFloat = self.segments[0].frame.size.width + self.separatorWidth/2.0
274                 for index in 1..<self.segments.count {
275                     path.move(to: CGPoint(x: originX, y: 0.0))
276                     path.addLine(to: CGPoint(x: originX, y: frame.size.height))
277                     
278                     originX += self.segments[index].frame.width + self.separatorWidth
279                 }
280             }
281             else {
282                 var originY: CGFloat = self.segments[0].frame.size.height + self.separatorWidth/2.0
283                 for index in 1..<self.segments.count {
284                     path.move(to: CGPoint(x: 0.0, y: originY))
285                     path.addLine(to: CGPoint(x: frame.size.width, y: originY))
286                     
287                     originY += self.segments[index].frame.height + self.separatorWidth
288                 }
289             }
290             
291             context.addPath(path)
292             context.setStrokeColor(self.separatorColour.cgColor)
293             context.setLineWidth(self.separatorWidth)
294             context.drawPath(using: CGPathDrawingMode.stroke)
295         }
296         
297         context.restoreGState()
298     }
299 }