@@ -20,16 +20,41 @@ import UIKit
2020
2121// MARK: - CustomKeyboard
2222public 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
2348 public var shiftToggleInterval : NSTimeInterval = 0.5
2449 private var shiftToggleTimer : NSTimer ?
25- private var shiftCanBeToggled : Bool = false
26- private var uppercaseOnce : Bool = true
2750
51+ // MARK: Backspace
2852 public var backspaceDeleteInterval : NSTimeInterval = 0.1
2953 public var backspaceAutoDeleteModeInterval : NSTimeInterval = 0.5
3054 private var backspaceDeleteTimer : NSTimer ?
3155 private var backspaceAutoDeleteModeTimer : NSTimer ?
3256
57+ // MARK: KeyMenu
3358 public var keyMenuLocked : Bool = false
3459 public var keyMenuOpenTimer : NSTimer ?
3560 public var keyMenuOpenTimeInterval : NSTimeInterval = 1
@@ -43,62 +68,11 @@ public class CustomKeyboard: UIView, KeyboardLayoutDelegate {
4368 dispatch_after (
4469 dispatch_time ( DISPATCH_TIME_NOW, Int64 ( 0.1 * Double( NSEC_PER_SEC) ) ) ,
4570 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
4772 }
4873 }
4974 }
5075
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-
10276 // MARK: Init
10377 public init ( ) {
10478 super. init ( frame: CGRect . zero)
@@ -116,35 +90,60 @@ public class CustomKeyboard: UIView, KeyboardLayoutDelegate {
11690 }
11791
11892 private func defaultInit( ) {
119- reload ( )
120- currentLayout = uppercaseLayout
121- addSubview ( currentLayout)
93+ keyboardLayoutStateDidChange ( oldState: nil , newState: keyboardLayoutState)
12294 }
12395
12496 // MARK: Layout
12597 public override func layoutSubviews( ) {
12698 super. layoutSubviews ( )
127- currentLayout? . frame = CGRect (
99+
100+ getCurrentKeyboardLayout ( ) . frame = CGRect (
128101 x: 0 ,
129102 y: 0 ,
130103 width: frame. size. width,
131104 height: frame. size. height)
132105 }
133106
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
138123 }
139124 }
140125
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+ }
148147 }
149148
150149 // MARK: Backspace Auto Delete
@@ -187,7 +186,6 @@ public class CustomKeyboard: UIView, KeyboardLayoutDelegate {
187186
188187 // MARK: Shift Toggle
189188 private func startShiftToggleTimer( ) {
190- shiftCanBeToggled = true
191189 shiftToggleTimer = NSTimer . scheduledTimerWithTimeInterval (
192190 shiftToggleInterval,
193191 target: self ,
@@ -199,7 +197,6 @@ public class CustomKeyboard: UIView, KeyboardLayoutDelegate {
199197 internal func invalidateShiftToggleTimer( ) {
200198 shiftToggleTimer? . invalidate ( )
201199 shiftToggleTimer = nil
202- shiftCanBeToggled = false
203200 }
204201
205202 // MARK: KeyMenu Toggle
@@ -229,92 +226,91 @@ public class CustomKeyboard: UIView, KeyboardLayoutDelegate {
229226 invalidateBackspaceDeleteTimer ( )
230227 invalidateKeyMenuOpenTimer ( )
231228
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+ }
237233
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)
247239 }
240+ } else if keyboardButton. keyMenu != nil {
241+ keyMenuShowingKeyboardButton = keyboardButton
242+ keyMenuLocked = false
248243 }
249244 }
250245
251246 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 ( )
260296 }
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)
306300 }
307301 }
308302 }
309303 }
310304
311305 public func keyboardLayout( keyboardLayout: KeyboardLayout, didTouchesBegin touches: Set < UITouch > ) {
306+ // KeyMenu
312307 if let menu = keyMenuShowingKeyboardButton? . keyMenu, touch = touches. first {
313308 menu. updateSelection ( touchLocation: touch. locationInView ( self ) , inView: self )
314309 }
315310 }
316311
317312 public func keyboardLayout( keyboardLayout: KeyboardLayout, didTouchesMove touches: Set < UITouch > ) {
313+ // KeyMenu
318314 if let menu = keyMenuShowingKeyboardButton? . keyMenu, touch = touches. first {
319315 menu. updateSelection ( touchLocation: touch. locationInView ( self ) , inView: self )
320316 }
@@ -325,6 +321,7 @@ public class CustomKeyboard: UIView, KeyboardLayoutDelegate {
325321 invalidateBackspaceDeleteTimer ( )
326322 invalidateKeyMenuOpenTimer ( )
327323
324+ // KeyMenu
328325 if let menu = keyMenuShowingKeyboardButton? . keyMenu, touch = touches? . first {
329326 menu. updateSelection ( touchLocation: touch. locationInView ( self ) , inView: self )
330327 // select item
@@ -350,6 +347,7 @@ public class CustomKeyboard: UIView, KeyboardLayoutDelegate {
350347 invalidateBackspaceDeleteTimer ( )
351348 invalidateKeyMenuOpenTimer ( )
352349
350+ // KeyMenu
353351 if let menu = keyMenuShowingKeyboardButton? . keyMenu, touch = touches? . first {
354352 menu. updateSelection ( touchLocation: touch. locationInView ( self ) , inView: self )
355353 // select item
@@ -363,7 +361,7 @@ public class CustomKeyboard: UIView, KeyboardLayoutDelegate {
363361 if keyMenuLocked {
364362 keyMenuShowingKeyboardButton = nil
365363 keyMenuLocked = false
366- currentLayout . typingEnabled = true
364+ getCurrentKeyboardLayout ( ) . typingEnabled = true
367365 return
368366 }
369367 keyMenuLocked = true
0 commit comments