@@ -20,16 +20,41 @@ import UIKit
20
20
21
21
// MARK: - CustomKeyboard
22
22
public class CustomKeyboard: UIView , KeyboardLayoutDelegate {
23
+ private( set) var keyboardLayout = CustomKeyboardLayout ( )
24
+ public weak var delegate : CustomKeyboardDelegate ?
25
+
26
+ // MARK: CustomKeyobardShiftState
27
+ public enum CustomKeyboardShiftState {
28
+ case Once
29
+ case Off
30
+ case On
31
+ }
32
+
33
+ // MARK: CustomKeyboardLayoutState
34
+ public enum CustomKeyboardLayoutState {
35
+ case Letters( shiftState: CustomKeyboardShiftState )
36
+ case Numbers
37
+ case Symbols
38
+ }
39
+
40
+ private( set) var previousShiftState : CustomKeyboardShiftState = . Once
41
+ private( set) var keyboardLayoutState : CustomKeyboardLayoutState = . Letters( shiftState: CustomKeyboardShiftState . Once) {
42
+ didSet {
43
+ keyboardLayoutStateDidChange ( oldState: oldValue, newState: keyboardLayoutState)
44
+ }
45
+ }
46
+
47
+ // MARK: Shift
23
48
public var shiftToggleInterval : NSTimeInterval = 0.5
24
49
private var shiftToggleTimer : NSTimer ?
25
- private var shiftCanBeToggled : Bool = false
26
- private var uppercaseOnce : Bool = true
27
50
51
+ // MARK: Backspace
28
52
public var backspaceDeleteInterval : NSTimeInterval = 0.1
29
53
public var backspaceAutoDeleteModeInterval : NSTimeInterval = 0.5
30
54
private var backspaceDeleteTimer : NSTimer ?
31
55
private var backspaceAutoDeleteModeTimer : NSTimer ?
32
56
57
+ // MARK: KeyMenu
33
58
public var keyMenuLocked : Bool = false
34
59
public var keyMenuOpenTimer : NSTimer ?
35
60
public var keyMenuOpenTimeInterval : NSTimeInterval = 1
@@ -43,62 +68,11 @@ public class CustomKeyboard: UIView, KeyboardLayoutDelegate {
43
68
dispatch_after (
44
69
dispatch_time ( DISPATCH_TIME_NOW, Int64 ( 0.1 * Double( NSEC_PER_SEC) ) ) ,
45
70
dispatch_get_main_queue ( ) ) { [ weak self] in
46
- self ? . currentLayout . typingEnabled = self !. keyMenuShowingKeyboardButton == nil && self !. keyMenuLocked == false
71
+ self ? . getCurrentKeyboardLayout ( ) . typingEnabled = self !. keyMenuShowingKeyboardButton == nil && self !. keyMenuLocked == false
47
72
}
48
73
}
49
74
}
50
75
51
- public var uppercaseToggledLayout : KeyboardLayout ! {
52
- didSet {
53
- layoutDidChange (
54
- oldLayout: oldValue,
55
- newLayout: uppercaseToggledLayout)
56
- }
57
- }
58
-
59
- public var uppercaseLayout : KeyboardLayout ! {
60
- didSet {
61
- layoutDidChange (
62
- oldLayout: oldValue,
63
- newLayout: uppercaseLayout)
64
- }
65
- }
66
-
67
- public var lowercaseLayout : KeyboardLayout ! {
68
- didSet {
69
- layoutDidChange (
70
- oldLayout: oldValue,
71
- newLayout: lowercaseLayout)
72
- }
73
- }
74
-
75
- public var numbersLayout : KeyboardLayout ! {
76
- didSet {
77
- layoutDidChange (
78
- oldLayout: oldValue,
79
- newLayout: numbersLayout)
80
- }
81
- }
82
-
83
- public var symbolsLayout : KeyboardLayout ! {
84
- didSet {
85
- layoutDidChange (
86
- oldLayout: oldValue,
87
- newLayout: symbolsLayout)
88
- }
89
- }
90
-
91
- private( set) var currentLayout : KeyboardLayout ! {
92
- didSet {
93
- oldValue? . delegate = nil
94
- oldValue? . removeFromSuperview ( )
95
- currentLayout. delegate = self
96
- addSubview ( currentLayout)
97
- }
98
- }
99
-
100
- public weak var delegate : CustomKeyboardDelegate ?
101
-
102
76
// MARK: Init
103
77
public init ( ) {
104
78
super. init ( frame: CGRect . zero)
@@ -116,35 +90,60 @@ public class CustomKeyboard: UIView, KeyboardLayoutDelegate {
116
90
}
117
91
118
92
private func defaultInit( ) {
119
- reload ( )
120
- currentLayout = uppercaseLayout
121
- addSubview ( currentLayout)
93
+ keyboardLayoutStateDidChange ( oldState: nil , newState: keyboardLayoutState)
122
94
}
123
95
124
96
// MARK: Layout
125
97
public override func layoutSubviews( ) {
126
98
super. layoutSubviews ( )
127
- currentLayout? . frame = CGRect (
99
+
100
+ getCurrentKeyboardLayout ( ) . frame = CGRect (
128
101
x: 0 ,
129
102
y: 0 ,
130
103
width: frame. size. width,
131
104
height: frame. size. height)
132
105
}
133
106
134
- private func layoutDidChange( oldLayout oldLayout: KeyboardLayout ? , newLayout: KeyboardLayout ) {
135
- guard currentLayout != nil && oldLayout != nil else { return }
136
- if currentLayout == oldLayout {
137
- currentLayout = newLayout
107
+ // MARK: KeyboardLayout
108
+ public func getKeyboardLayout( ofState state: CustomKeyboardLayoutState ) -> KeyboardLayout {
109
+ switch state {
110
+ case . Letters( let shiftState) :
111
+ switch shiftState {
112
+ case . Once:
113
+ return keyboardLayout. uppercase
114
+ case . On:
115
+ return keyboardLayout. uppercaseToggled
116
+ case . Off:
117
+ return keyboardLayout. lowercase
118
+ }
119
+ case . Numbers:
120
+ return keyboardLayout. numbers
121
+ case . Symbols:
122
+ return keyboardLayout. symbols
138
123
}
139
124
}
140
125
141
- // MARK: Reload
142
- public func reload( ) {
143
- uppercaseToggledLayout = CustomKeyboardLayout . UppercaseToggled. keyboardLayout
144
- uppercaseLayout = CustomKeyboardLayout . Uppercase. keyboardLayout
145
- lowercaseLayout = CustomKeyboardLayout . Lowercase. keyboardLayout
146
- numbersLayout = CustomKeyboardLayout . Numbers. keyboardLayout
147
- symbolsLayout = CustomKeyboardLayout . Symbols. keyboardLayout
126
+ public func getCurrentKeyboardLayout( ) -> KeyboardLayout {
127
+ return getKeyboardLayout ( ofState: keyboardLayoutState)
128
+ }
129
+
130
+ public func keyboardLayoutStateDidChange( oldState oldState: CustomKeyboardLayoutState ? , newState: CustomKeyboardLayoutState ) {
131
+ // Remove old keyboard layout
132
+ if let oldState = oldState {
133
+ let oldKeyboardLayout = getKeyboardLayout ( ofState: oldState)
134
+ oldKeyboardLayout. delegate = nil
135
+ oldKeyboardLayout. removeFromSuperview ( )
136
+ }
137
+
138
+ // Add new keyboard layout
139
+ let newKeyboardLayout = getKeyboardLayout ( ofState: newState)
140
+ newKeyboardLayout. delegate = self
141
+ addSubview ( newKeyboardLayout)
142
+
143
+ // Set previous shift state
144
+ if case CustomKeyboardLayoutState . Letters( let shiftState) = newState {
145
+ previousShiftState = shiftState
146
+ }
148
147
}
149
148
150
149
// MARK: Backspace Auto Delete
@@ -187,7 +186,6 @@ public class CustomKeyboard: UIView, KeyboardLayoutDelegate {
187
186
188
187
// MARK: Shift Toggle
189
188
private func startShiftToggleTimer( ) {
190
- shiftCanBeToggled = true
191
189
shiftToggleTimer = NSTimer . scheduledTimerWithTimeInterval (
192
190
shiftToggleInterval,
193
191
target: self ,
@@ -199,7 +197,6 @@ public class CustomKeyboard: UIView, KeyboardLayoutDelegate {
199
197
internal func invalidateShiftToggleTimer( ) {
200
198
shiftToggleTimer? . invalidate ( )
201
199
shiftToggleTimer = nil
202
- shiftCanBeToggled = false
203
200
}
204
201
205
202
// MARK: KeyMenu Toggle
@@ -229,92 +226,91 @@ public class CustomKeyboard: UIView, KeyboardLayoutDelegate {
229
226
invalidateBackspaceDeleteTimer ( )
230
227
invalidateKeyMenuOpenTimer ( )
231
228
232
- if keyboardLayout == currentLayout {
233
- // Backspace
234
- if keyboardButton. identifier == CustomKeyboardIdentifier . Backspace. rawValue {
235
- startBackspaceAutoDeleteModeTimer ( )
236
- }
229
+ // Backspace
230
+ if keyboardButton. identifier == CustomKeyboardIdentifier . Backspace. rawValue {
231
+ startBackspaceAutoDeleteModeTimer ( )
232
+ }
237
233
238
- // KeyPop and KeyMenu
239
- if keyboardButton. style. keyPopType != nil {
240
- keyboardButton. showKeyPop ( show: true )
241
- if keyboardButton. keyMenu != nil {
242
- startKeyMenuOpenTimer ( forKeyboardButton: keyboardButton)
243
- }
244
- } else if keyboardButton. keyMenu != nil {
245
- keyMenuShowingKeyboardButton = keyboardButton
246
- keyMenuLocked = false
234
+ // KeyPop and KeyMenu
235
+ if keyboardButton. style. keyPopType != nil {
236
+ keyboardButton. showKeyPop ( show: true )
237
+ if keyboardButton. keyMenu != nil {
238
+ startKeyMenuOpenTimer ( forKeyboardButton: keyboardButton)
247
239
}
240
+ } else if keyboardButton. keyMenu != nil {
241
+ keyMenuShowingKeyboardButton = keyboardButton
242
+ keyMenuLocked = false
248
243
}
249
244
}
250
245
251
246
public func keyboardLayout( keyboardLayout: KeyboardLayout , didKeyPressEnd keyboardButton: KeyboardButton ) {
252
- if keyboardLayout == currentLayout {
253
- delegate? . customKeyboard ? ( self , keyboardButtonPressed: keyboardButton)
254
- switch keyboardButton. type {
255
- case . Key( let key) :
256
- delegate? . customKeyboard ? ( self , keyButtonPressed: key)
257
- if uppercaseOnce {
258
- uppercaseOnce = false
259
- currentLayout = lowercaseLayout
247
+ // If keyboard key is pressed notify no questions asked
248
+ if case KeyboardButtonType . Key( let text) = keyboardButton. type {
249
+ delegate? . customKeyboard ? ( self , keyButtonPressed: text)
250
+
251
+ // If shift state was CustomKeyboardShiftState.Once then make keyboard layout lowercase
252
+ if case CustomKeyboardLayoutState . Letters( let shiftState) = keyboardLayoutState where shiftState == CustomKeyboardShiftState . Once {
253
+ keyboardLayoutState = CustomKeyboardLayoutState . Letters ( shiftState: . Off)
254
+ return
255
+ }
256
+ }
257
+
258
+ // Chcek special keyboard buttons
259
+ if let keyId = keyboardButton. identifier, identifier = CustomKeyboardIdentifier ( rawValue: keyId) {
260
+ switch identifier {
261
+
262
+ // Notify special keys
263
+ case . Backspace:
264
+ delegate? . customKeyboardBackspaceButtonPressed ? ( self )
265
+ case . Space:
266
+ delegate? . customKeyboardSpaceButtonPressed ? ( self )
267
+ case . Globe:
268
+ delegate? . customKeyboardGlobeButtonPressed ? ( self )
269
+ case . Return:
270
+ delegate? . customKeyboardReturnButtonPressed ? ( self )
271
+
272
+ // Update keyboard layout state
273
+ case . Letters:
274
+ keyboardLayoutState = . Letters( shiftState: previousShiftState)
275
+ case . Numbers:
276
+ keyboardLayoutState = . Numbers
277
+ case . Symbols:
278
+ keyboardLayoutState = . Symbols
279
+
280
+ // Update shift state
281
+ case . Shift:
282
+ if shiftToggleTimer == nil {
283
+ keyboardLayoutState = . Letters( shiftState: . Once)
284
+ startShiftToggleTimer ( )
285
+ } else {
286
+ keyboardLayoutState = . Letters( shiftState: . On)
287
+ invalidateShiftToggleTimer ( )
288
+ }
289
+ case . ShiftToggledOnce:
290
+ if shiftToggleTimer == nil {
291
+ keyboardLayoutState = . Letters( shiftState: . Off)
292
+ startShiftToggleTimer ( )
293
+ } else {
294
+ keyboardLayoutState = . Letters( shiftState: . On)
295
+ invalidateShiftToggleTimer ( )
260
296
}
261
- default :
262
- if let id = keyboardButton. identifier,
263
- let identifier = CustomKeyboardIdentifier ( rawValue: id) {
264
- switch identifier {
265
- case . Numbers:
266
- currentLayout = numbersLayout
267
- case . Symbols:
268
- currentLayout = symbolsLayout
269
- case . Letters:
270
- currentLayout = uppercaseLayout
271
- uppercaseOnce = true
272
- case . Globe:
273
- delegate? . customKeyboardGlobeButtonPressed ? ( self )
274
- case . Return:
275
- delegate? . customKeyboardReturnButtonPressed ? ( self )
276
- case . Space:
277
- delegate? . customKeyboardSpaceButtonPressed ? ( self )
278
- uppercaseOnce = false
279
- case . Backspace:
280
- delegate? . customKeyboardBackspaceButtonPressed ? ( self )
281
- uppercaseOnce = false
282
- case . Shift:
283
- if shiftCanBeToggled {
284
- currentLayout = uppercaseToggledLayout
285
- uppercaseOnce = false
286
- invalidateShiftToggleTimer ( )
287
- } else {
288
- currentLayout = uppercaseLayout
289
- uppercaseOnce = true
290
- startShiftToggleTimer ( )
291
- }
292
- case . ShiftToggledOnce:
293
- if shiftCanBeToggled {
294
- currentLayout = uppercaseToggledLayout
295
- uppercaseOnce = false
296
- invalidateShiftToggleTimer ( )
297
- } else {
298
- uppercaseOnce = false
299
- currentLayout = lowercaseLayout
300
- startShiftToggleTimer ( )
301
- }
302
- case . ShiftToggled:
303
- currentLayout = lowercaseLayout
304
- uppercaseOnce = false
305
- }
297
+ case . ShiftToggled:
298
+ if shiftToggleTimer == nil {
299
+ keyboardLayoutState = . Letters( shiftState: . Off)
306
300
}
307
301
}
308
302
}
309
303
}
310
304
311
305
public func keyboardLayout( keyboardLayout: KeyboardLayout, didTouchesBegin touches: Set < UITouch > ) {
306
+ // KeyMenu
312
307
if let menu = keyMenuShowingKeyboardButton? . keyMenu, touch = touches. first {
313
308
menu. updateSelection ( touchLocation: touch. locationInView ( self ) , inView: self )
314
309
}
315
310
}
316
311
317
312
public func keyboardLayout( keyboardLayout: KeyboardLayout, didTouchesMove touches: Set < UITouch > ) {
313
+ // KeyMenu
318
314
if let menu = keyMenuShowingKeyboardButton? . keyMenu, touch = touches. first {
319
315
menu. updateSelection ( touchLocation: touch. locationInView ( self ) , inView: self )
320
316
}
@@ -325,6 +321,7 @@ public class CustomKeyboard: UIView, KeyboardLayoutDelegate {
325
321
invalidateBackspaceDeleteTimer ( )
326
322
invalidateKeyMenuOpenTimer ( )
327
323
324
+ // KeyMenu
328
325
if let menu = keyMenuShowingKeyboardButton? . keyMenu, touch = touches? . first {
329
326
menu. updateSelection ( touchLocation: touch. locationInView ( self ) , inView: self )
330
327
// select item
@@ -350,6 +347,7 @@ public class CustomKeyboard: UIView, KeyboardLayoutDelegate {
350
347
invalidateBackspaceDeleteTimer ( )
351
348
invalidateKeyMenuOpenTimer ( )
352
349
350
+ // KeyMenu
353
351
if let menu = keyMenuShowingKeyboardButton? . keyMenu, touch = touches? . first {
354
352
menu. updateSelection ( touchLocation: touch. locationInView ( self ) , inView: self )
355
353
// select item
@@ -363,7 +361,7 @@ public class CustomKeyboard: UIView, KeyboardLayoutDelegate {
363
361
if keyMenuLocked {
364
362
keyMenuShowingKeyboardButton = nil
365
363
keyMenuLocked = false
366
- currentLayout . typingEnabled = true
364
+ getCurrentKeyboardLayout ( ) . typingEnabled = true
367
365
return
368
366
}
369
367
keyMenuLocked = true
0 commit comments