Skip to content

Commit

Permalink
feat: draft implementation with UIViewRepresentable
Browse files Browse the repository at this point in the history
use a UIKit UITextField inputAccessoryView and inputView
  • Loading branch information
bsorrentino committed Sep 20, 2022
1 parent ba1f587 commit c3f63a5
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 136 deletions.
20 changes: 5 additions & 15 deletions PlantUML/PlantUMLEditorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ struct PlantUMLEditorView: View {
EditButton()
SaveButton()
}


}
}

Expand Down Expand Up @@ -121,6 +123,7 @@ struct PlantUMLEditorView: View {

// MARK: Editor View
func EditorView() -> some View {

List() {
ForEach( diagram.items ) { item in

Expand All @@ -134,28 +137,15 @@ struct PlantUMLEditorView: View {
}
}

PlantUMLTextFieldWithCustomKeyboard()
// PlantUMLTextField( value: item.rawValue,
// customKeyboard: customKeyboard,
// onChange: updateItem )
PlantUMLTextFieldWithCustomKeyboard( value: item.rawValue, onChange: updateItem )
.focused($focusedItem, equals: .row(id: item.id))
}


}
.onMove(perform: move)
.onDelete( perform: delete)

}
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
AddBelowButton()
AddAboveButton()
ShowKeyboardButton( show: $customKeyboard.showKeyboard )

}

}
.font(.footnote)
.listStyle(SidebarListStyle())

Expand Down Expand Up @@ -251,7 +241,7 @@ extension PlantUMLEditorView {
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
PlantUMLEditorView(document: .constant(PlantUMLDocument()))
.environment(\.editMode, Binding.constant(EditMode.active))
.environment(\.editMode, Binding.constant(EditMode.inactive))
.previewInterfaceOrientation(.landscapeRight)
.environmentObject( PlantUMLDiagramObject( text:
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,6 @@ public class CustomKeyboardObject : ObservableObject {

private var cancellable:AnyCancellable?

var keyboardView:UIView {

let controller = UIHostingController( rootView: PlantUMLKeyboardView( customKeyboard: self ) )

let MAGIC_NUMBER = 50.0 // magic number .. height of keyboard top bar
var customKeyboardRect = keyboardRect
customKeyboardRect.origin.y += MAGIC_NUMBER
customKeyboardRect.size.height -= MAGIC_NUMBER
controller.view.frame = customKeyboardRect
return controller.view

}
public init() {

NotificationCenter.default.addObserver(
Expand Down
40 changes: 11 additions & 29 deletions PlantUMLKeyboard/Sources/PlantUMLKeyboard/PlantUMLKeyboard.swift
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
import SwiftUI
import UIKit






public struct PlantUMLKeyboardView: View {

@ObservedObject var customKeyboard: CustomKeyboardObject
struct PlantUMLKeyboardView: View {

// public init( show: Binding<Bool>, result:Binding<[String]> ) {
// self._show = show
// self._result = result
// }
var onHide:() -> Void
var onPressSymbol: (Symbol) -> Void

public var body : some View{
var body : some View{

ZStack(alignment: .topLeading) {

Expand All @@ -31,14 +22,14 @@ public struct PlantUMLKeyboardView: View {

Button {

replaceSymbolAtCursorPosition(symbol)
onPressSymbol(symbol)

} label: {

ButtonLabel( rowIndex: rowIndex, cellIndex: cellIndex, symbol: symbol )

}
.buttonStyle( KeyButtonStyle() )
.buttonStyle( KeyButtonStyle2() )
}
}
}
Expand All @@ -50,9 +41,7 @@ public struct PlantUMLKeyboardView: View {
.background(Color.gray.opacity(0.1))
.cornerRadius(25)

Button(action: {
customKeyboard.showKeyboard.toggle()
}) {
Button(action: onHide) {
Image(systemName: "xmark").foregroundColor(.black)
}
.padding()
Expand All @@ -63,6 +52,7 @@ public struct PlantUMLKeyboardView: View {
//
//
func replaceSymbolAtCursorPosition( _ symbol: Symbol) {
/*
guard let handleToYourTextView = getFirstTextFieldResponder() else {
return
}
Expand All @@ -78,11 +68,11 @@ public struct PlantUMLKeyboardView: View {
if let additionalValues = symbol.additionalValues {
customKeyboard.itemsToAdd = additionalValues
}

*/
}
}

struct KeyButtonStyle: ButtonStyle {
fileprivate struct KeyButtonStyle2: ButtonStyle {

func makeBody(configuration: Configuration) -> some View {
configuration.label
Expand Down Expand Up @@ -115,17 +105,9 @@ extension PlantUMLKeyboardView {
}

struct PlantUMLKeyboardView_Previews: PreviewProvider {

struct UserView : View {
@ObservedObject var customKeyboard = CustomKeyboardObject()

public var body : some View {
PlantUMLKeyboardView( customKeyboard: customKeyboard )
}
}

static var previews: some View {
UserView()
PlantUMLKeyboardView( onHide: { }, onPressSymbol: { _ in } )
.previewInterfaceOrientation(.landscapeLeft)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,17 @@ import UIKit
import SwiftUI

public struct PlantUMLTextFieldWithCustomKeyboard : UIViewRepresentable {

public typealias ChangeHandler = ( String ) -> Void
public typealias UIViewType = UITextField

private let textField = UITextField()

public init() {


public var value:String
public var onChange:ChangeHandler

public init( value:String, onChange:@escaping ChangeHandler ) {
self.value = value
self.onChange = onChange
}

public func makeCoordinator() -> PlantUMLTextFieldWithCustomKeyboard.Coordinator {
Expand All @@ -25,22 +29,156 @@ public struct PlantUMLTextFieldWithCustomKeyboard : UIViewRepresentable {
public func makeUIView(context: Context) -> UITextField {

textField.delegate = context.coordinator
textField.keyboardType = .asciiCapableNumberPad
textField.autocapitalizationType = .none
textField.font = UIFont.monospacedSystemFont(ofSize: 15, weight: .regular)
textField.returnKeyType = .done
textField.text = value
return textField
}

public func updateUIView(_ uiView: UITextField, context: Context) {

context.coordinator.updateAccesoryView()

}
}


// MARK: - CustomKeyboardPresenter protocol
protocol CustomKeyboardPresenter {

func toggleCustomKeyobard() -> Void

func onPressSymbol( _ symbol: Symbol ) -> Void

}

public class Coordinator: NSObject, UITextFieldDelegate {
// MARK: - Coordinator extension
extension PlantUMLTextFieldWithCustomKeyboard {

public class Coordinator: NSObject, UITextFieldDelegate, CustomKeyboardPresenter {


private var keyboardRect:CGRect = .zero
private let owner : PlantUMLTextFieldWithCustomKeyboard
private var showCustomKeyboard:Bool

private let parent : PlantUMLTextFieldWithCustomKeyboard

public init(textfield : PlantUMLTextFieldWithCustomKeyboard) {
self.parent = textfield
self.owner = textfield
self.showCustomKeyboard = false
super.init()

updateAccesoryView()

NotificationCenter.default.addObserver(

forName: UIResponder.keyboardDidShowNotification, object: nil, queue: .main) { [weak self] notification in

print( "keyboardDidShowNotification" )

if let keyboardFrameEndUser = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue) {

print( "keyboardFrameEndUser pos=\(keyboardFrameEndUser)")

self?.keyboardRect = keyboardFrameEndUser.cgRectValue
}

}

NotificationCenter.default.addObserver(

forName: UIResponder.keyboardDidHideNotification, object: nil, queue: .main) { [weak self] _ in

print( "keyboardDidHideNotification" )

self?.keyboardRect = .zero

}


}

func updateAccesoryView() {
if owner.textField.inputAccessoryView == nil {

let bar = UIToolbar()
let toggleKeyboard = UIBarButtonItem(title: "PlantUML Keyboard", style: .plain, target: self, action: #selector(toggleCustomKeyobard))
bar.items = [
toggleKeyboard
]
bar.sizeToFit()
owner.textField.inputAccessoryView = bar

}

}
public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

// print( "shouldChangeCharactersIn", range, string )
if let text = textField.text, let range = Range(range, in: text) {
owner.onChange( text.replacingCharacters(in: range, with: string) )
}

return true
}

/// Lazy creation Input View
var customKeyboardView:UIView {
let keyboardView = PlantUMLKeyboardView(onHide: toggleCustomKeyobard, onPressSymbol: onPressSymbol )
let controller = UIHostingController( rootView: keyboardView )

let MAGIC_NUMBER = 100.0 // 50.0 // magic number .. height of keyboard top bar
var customKeyboardRect = keyboardRect
customKeyboardRect.origin.y += MAGIC_NUMBER
customKeyboardRect.size.height -= MAGIC_NUMBER
controller.view.frame = customKeyboardRect
return controller.view

}

@objc public func toggleCustomKeyobard() {
print("toggleCustomKeyobard:", showCustomKeyboard)

showCustomKeyboard.toggle()

if( showCustomKeyboard ) {
owner.textField.inputView = customKeyboardView
}
else {
owner.textField.inputView = nil
}
owner.textField.reloadInputViews()

}

func onPressSymbol(_ symbol: Symbol) {

// [How to programmatically enter text in UITextView at the current cursor position](https://stackoverflow.com/a/35888634/521197)
if let range = owner.textField.selectedTextRange {
// From your question I assume that you do not want to replace a selection, only insert some text where the cursor is.
owner.textField.replace(range, withText: symbol.value )

if let text = owner.textField.text {
owner.onChange( text )
}

/*
// https://stackoverflow.com/a/63555951/521197
let _range = NSMakeRange(
owner.textField.offset(from: owner.textField.beginningOfDocument, to: range.start),
owner.textField.offset(from: range.start, to: range.end))
let _ = self.textField(owner.textField, shouldChangeCharactersIn: _range, replacementString: symbol.value)
*/
}

// if let additionalValues = symbol.additionalValues {
// customKeyboard.itemsToAdd = additionalValues
// }

}

}

}

0 comments on commit c3f63a5

Please sign in to comment.