WhiteboardCanvas.swift 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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. let dataWB = UserDefaults.standard.string(forKey: "wb_vc")!
  105. //print(("DATA WB \(dataWB)")
  106. var colorDraw = UIColor.red
  107. let requester = dataWB.components(separatedBy: ",")[0]
  108. let idMe = UserDefaults.standard.string(forKey: "me")!
  109. if requester == idMe {
  110. colorDraw = UIColor.blue
  111. }
  112. onDrawing?(touchPoint.x, touchPoint.y, nWidth, nHeight, colorDraw.toHexString(), lineWidth, startingPoint.x, startingPoint.y)
  113. 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(),
  114. sw: toString(from: lineWidth), xo: toString(from: startingPoint.x), yo: toString(from: startingPoint.y))
  115. path = UIBezierPath()
  116. path.move(to: startingPoint)
  117. path.addLine(to: touchPoint)
  118. startingPoint = touchPoint
  119. drawShapeLayer(color: colorDraw)
  120. }
  121. }
  122. }
  123. func drawShapeLayer(color: UIColor = UIColor.red) {
  124. let shapelayer = CAShapeLayer()
  125. shapelayer.path = path.cgPath
  126. shapelayer.strokeColor = color.cgColor
  127. shapelayer.lineWidth = lineWidth
  128. shapelayer.fillColor = UIColor.clear.cgColor
  129. self.layer.addSublayer(shapelayer)
  130. self.setNeedsDisplay()
  131. }
  132. func clear() -> Void {
  133. self.layer.sublayers = nil
  134. self.setNeedsDisplay()
  135. onClearing?()
  136. }
  137. func incomingDraw(x:CGFloat, y:CGFloat, w:CGFloat, h:CGFloat, fc:String, sw:CGFloat, xo:CGFloat, yo:CGFloat) {
  138. //print(("DRAWING >> x:\(x) y:\(y) w:\(w) h:\(h) fc:\(fc) sw:\(sw) xo:\(xo) yo:\(yo)")
  139. let xoScaled = nWidth / w * xo;
  140. let yoScaled = nHeight / h * yo;
  141. let xScaled = nWidth / w * x;
  142. let yScaled = nHeight / h * y;
  143. let path = UIBezierPath()
  144. path.move(to: CGPoint(x: xoScaled, y: yoScaled))
  145. path.addLine(to: CGPoint(x: xScaled, y: yScaled))
  146. let line = CAShapeLayer()
  147. line.path = path.cgPath
  148. line.strokeColor = UIColor(hexString: fc).cgColor
  149. line.lineWidth = sw
  150. line.fillColor = UIColor(hexString: fc).cgColor
  151. self.layer.addSublayer(line)
  152. self.setNeedsDisplay()
  153. }
  154. func incomingData(x: String, y: String, w: String, h: String, fc: String, sw: String, xo: String, yo: String) {
  155. DispatchQueue.main.async {
  156. self.incomingDraw(x: self.toCGFloat(from: x),
  157. y: self.toCGFloat(from: y),
  158. w: self.toCGFloat(from: w),
  159. h: self.toCGFloat(from: h),
  160. fc: fc,
  161. sw: self.toCGFloat(from: sw),
  162. xo: self.toCGFloat(from: xo),
  163. yo: self.toCGFloat(from: yo))
  164. }
  165. }
  166. func toCGFloat(from:String!) -> CGFloat {
  167. if let n = Double(from) {
  168. return CGFloat(n)
  169. }
  170. return CGFloat(0)
  171. }
  172. func toString(from:CGFloat!) -> String {
  173. return from.description
  174. }
  175. func setDestination(destination: String) {
  176. self.destination = destination
  177. }
  178. public func setBackground(color:UIColor){
  179. backgroundColor = color
  180. }
  181. public func setStrokeSize(size: Double){
  182. lineWidth = CGFloat(size)
  183. }
  184. public func setLineColor(color:UIColor) {
  185. lineColor = color
  186. }
  187. public func setPeerStrokeSize(size: Double){
  188. peerLineWidth = CGFloat(size)
  189. }
  190. public func setPeerLineColor(color:UIColor){
  191. peerLineColor = color
  192. }
  193. public func resetLineColor() {
  194. lineColor = UIColor.gray
  195. }
  196. func drawWhiteboard(destination: String, x: String, y: String, w: String, h: String, fc: String, sw: String, xo: String, yo: String){
  197. //print(("DRAW HMM \(destination)")
  198. _ = Nexilis.writeDraw(data: "WB/1/\(x)/\(y)/\(w)/\(h)/\(fc)/\(sw)/\(xo)/\(yo)")
  199. }
  200. }