WhiteboardCanvas.swift 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. //
  2. // WhiteboardCanvas.swift
  3. // Nusa
  4. //
  5. // Created by Rifqy Fakhrul Rijal on 21/10/19.
  6. // Copyright © 2019 Development. All rights reserved.
  7. //
  8. import Foundation
  9. import UIKit
  10. // Rn
  11. // linecolor red peerlinecolor blue
  12. extension UIColor {
  13. convenience init(hexString: String, alpha: CGFloat = 1.0) {
  14. let hexString: String = hexString.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
  15. let scanner = Scanner(string: hexString)
  16. if (hexString.hasPrefix("#")) {
  17. scanner.scanLocation = 1
  18. }
  19. var color: UInt32 = 0
  20. scanner.scanHexInt32(&color)
  21. let mask = 0x000000FF
  22. let r = Int(color >> 16) & mask
  23. let g = Int(color >> 8) & mask
  24. let b = Int(color) & mask
  25. let red = CGFloat(r) / 255.0
  26. let green = CGFloat(g) / 255.0
  27. let blue = CGFloat(b) / 255.0
  28. self.init(red:red, green:green, blue:blue, alpha:alpha)
  29. }
  30. func toHexString() -> String {
  31. var r:CGFloat = 0
  32. var g:CGFloat = 0
  33. var b:CGFloat = 0
  34. var a:CGFloat = 0
  35. getRed(&r, green: &g, blue: &b, alpha: &a)
  36. let rgb:Int = (Int)(r*255)<<16 | (Int)(g*255)<<8 | (Int)(b*255)<<0
  37. return String(format:"#%06x", rgb)
  38. }
  39. }
  40. public class WhiteboardCanvas: UIView {
  41. var destination: String?
  42. var lineColor:UIColor = UIColor.red
  43. var lineWidth:CGFloat!
  44. var peerLineColor:UIColor = UIColor.blue
  45. var peerLineWidth:CGFloat!
  46. var path:UIBezierPath!
  47. var touchPoint:CGPoint!
  48. var startingPoint:CGPoint!
  49. let fRThreshold:CGFloat = 4.0;
  50. var eraseModeOn:Bool = false;
  51. var nWidth:CGFloat!
  52. var nHeight:CGFloat!
  53. var onDrawing : ((CGFloat, CGFloat, CGFloat, CGFloat, String, CGFloat, CGFloat, CGFloat) -> Void)?
  54. var onClearing : (() -> Void)?
  55. func listen(onDraw:@escaping ((CGFloat, CGFloat, CGFloat, CGFloat, String, CGFloat, CGFloat, CGFloat) -> Void), onClear:@escaping (() -> Void)) -> Void {
  56. onDrawing = onDraw
  57. onClearing = onClear
  58. }
  59. override public func layoutSubviews() {
  60. super.layoutSubviews()
  61. self.clipsToBounds = true
  62. self.isMultipleTouchEnabled = false
  63. nWidth = self.frame.size.width
  64. nHeight = self.frame.size.height
  65. lineWidth = 2
  66. self.layer.borderWidth = 0.5
  67. self.layer.borderColor = UIColor.black.cgColor
  68. self.layer.backgroundColor = UIColor.white.cgColor
  69. let margin_left = CGFloat(0.07) * UIScreen.main.bounds.width
  70. let margin_top = CGFloat(0.1) * UIScreen.main.bounds.height
  71. let margin_bottom = CGFloat(0.25) * UIScreen.main.bounds.height
  72. let width = UIScreen.main.bounds.width - CGFloat(margin_left) - CGFloat(margin_left)
  73. let height = UIScreen.main.bounds.height - margin_top - margin_bottom
  74. self.frame = CGRect(x: margin_left, y: margin_top, width: width, height: height)
  75. //
  76. }
  77. override public func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
  78. let touch = touches.first
  79. startingPoint = touch?.location(in: self)
  80. }
  81. override public func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
  82. let touch = touches.first
  83. touchPoint = touch?.location(in: self)
  84. let dx = abs(touchPoint.x - startingPoint.x)
  85. let dy = abs(touchPoint.x - startingPoint.x)
  86. if (dx >= fRThreshold || dy >= fRThreshold) {
  87. let onGoingCC = UserDefaults.standard.string(forKey: "onGoingCC") ?? ""
  88. if !onGoingCC.isEmpty {
  89. var colorDraw = UIColor.red
  90. let requester = onGoingCC.components(separatedBy: ",")[0]
  91. let idMe = UserDefaults.standard.string(forKey: "me")!
  92. if requester == idMe {
  93. colorDraw = UIColor.blue
  94. }
  95. onDrawing?(touchPoint.x, touchPoint.y, nWidth, nHeight, colorDraw.toHexString(), lineWidth, startingPoint.x, startingPoint.y)
  96. self.drawWhiteboard(destination: destination ?? "", x: toString(from: touchPoint.x), y: toString(from: touchPoint.y), w: toString(from: nWidth), h: toString(from: nHeight), fc: colorDraw.toHexString(),
  97. sw: toString(from: lineWidth), xo: toString(from: startingPoint.x), yo: toString(from: startingPoint.y))
  98. path = UIBezierPath()
  99. path.move(to: startingPoint)
  100. path.addLine(to: touchPoint)
  101. startingPoint = touchPoint
  102. drawShapeLayer(color: colorDraw)
  103. } else {
  104. onDrawing?(touchPoint.x, touchPoint.y, nWidth, nHeight, lineColor.toHexString(), lineWidth, startingPoint.x, startingPoint.y)
  105. self.drawWhiteboard(destination: destination ?? "", x: toString(from: touchPoint.x), y: toString(from: touchPoint.y), w: toString(from: nWidth), h: toString(from: nHeight), fc: peerLineColor.toHexString(),
  106. sw: toString(from: lineWidth), xo: toString(from: startingPoint.x), yo: toString(from: startingPoint.y))
  107. path = UIBezierPath()
  108. path.move(to: startingPoint)
  109. path.addLine(to: touchPoint)
  110. startingPoint = touchPoint
  111. drawShapeLayer()
  112. }
  113. }
  114. }
  115. func drawShapeLayer(color: UIColor = UIColor.red) {
  116. let shapelayer = CAShapeLayer()
  117. shapelayer.path = path.cgPath
  118. shapelayer.strokeColor = color.cgColor
  119. shapelayer.lineWidth = lineWidth
  120. shapelayer.fillColor = UIColor.clear.cgColor
  121. self.layer.addSublayer(shapelayer)
  122. self.setNeedsDisplay()
  123. }
  124. func clear() -> Void {
  125. self.layer.sublayers = nil
  126. self.setNeedsDisplay()
  127. onClearing?()
  128. }
  129. func incomingDraw(x:CGFloat, y:CGFloat, w:CGFloat, h:CGFloat, fc:String, sw:CGFloat, xo:CGFloat, yo:CGFloat) {
  130. print("DRAWING >> x:\(x) y:\(y) w:\(w) h:\(h) fc:\(fc) sw:\(sw) xo:\(xo) yo:\(yo)")
  131. let xoScaled = nWidth / w * xo;
  132. let yoScaled = nHeight / h * yo;
  133. let xScaled = nWidth / w * x;
  134. let yScaled = nHeight / h * y;
  135. let path = UIBezierPath()
  136. path.move(to: CGPoint(x: xoScaled, y: yoScaled))
  137. path.addLine(to: CGPoint(x: xScaled, y: yScaled))
  138. let line = CAShapeLayer()
  139. line.path = path.cgPath
  140. line.strokeColor = UIColor(hexString: fc).cgColor
  141. line.lineWidth = sw
  142. line.fillColor = UIColor(hexString: fc).cgColor
  143. self.layer.addSublayer(line)
  144. self.setNeedsDisplay()
  145. }
  146. func incomingData(x: String, y: String, w: String, h: String, fc: String, sw: String, xo: String, yo: String) {
  147. DispatchQueue.main.async {
  148. self.incomingDraw(x: self.toCGFloat(from: x),
  149. y: self.toCGFloat(from: y),
  150. w: self.toCGFloat(from: w),
  151. h: self.toCGFloat(from: h),
  152. fc: fc,
  153. sw: self.toCGFloat(from: sw),
  154. xo: self.toCGFloat(from: xo),
  155. yo: self.toCGFloat(from: yo))
  156. }
  157. }
  158. func toCGFloat(from:String!) -> CGFloat {
  159. if let n = Double(from) {
  160. return CGFloat(n)
  161. }
  162. return CGFloat(0)
  163. }
  164. func toString(from:CGFloat!) -> String {
  165. return from.description
  166. }
  167. func setDestination(destination: String) {
  168. self.destination = destination
  169. }
  170. public func setBackground(color:UIColor){
  171. backgroundColor = color
  172. }
  173. public func setStrokeSize(size: Double){
  174. lineWidth = CGFloat(size)
  175. }
  176. public func setLineColor(color:UIColor) {
  177. lineColor = color
  178. }
  179. public func setPeerStrokeSize(size: Double){
  180. peerLineWidth = CGFloat(size)
  181. }
  182. public func setPeerLineColor(color:UIColor){
  183. peerLineColor = color
  184. }
  185. public func resetLineColor() {
  186. lineColor = UIColor.gray
  187. }
  188. func drawWhiteboard(destination: String, x: String, y: String, w: String, h: String, fc: String, sw: String, xo: String, yo: String){
  189. print("DRAW HMM \(destination)")
  190. _ = Nexilis.writeDraw(data: "WB/1/\(x)/\(y)/\(w)/\(h)/\(fc)/\(sw)/\(xo)/\(yo)")
  191. }
  192. }