KMLineInspector.swift 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. //
  2. // KMLineInspector.swift
  3. // PDF Master
  4. //
  5. // Created by tangchao on 2023/11/10.
  6. //
  7. import Cocoa
  8. enum KMLineChangeAction: Int {
  9. case no = 0
  10. case lineWidth
  11. case style
  12. case dashPattern
  13. case startLineStyle
  14. case endLineStyle
  15. }
  16. class KMLineInspector: NSWindowController {
  17. private let LINEWIDTH_KEY = "style"
  18. private let STYLE_KEY = "lineWidth"
  19. private let DASHPATTERN_KEY = "dashPattern"
  20. private let STARTLINESTYLE_KEY = "startLineStyle"
  21. private let ENDLINESTYLE_KEY = "endLineStyle"
  22. private let ACTION_KEY = "action"
  23. private let SKLineInspectorFrameAutosaveName = "SKLineInspector"
  24. let SKLineInspectorLineAttributeDidChangeNotification = "SKLineInspectorLineAttributeDidChangeNotification"
  25. /*
  26. + (BOOL)sharedLineInspectorExists;
  27. - (void)setAnnotationStyle:(PDFAnnotation *)annotation;
  28. */
  29. private var _currentLineChangeAction: KMLineChangeAction = .lineWidth
  30. var currentLineChangeAction: KMLineChangeAction {
  31. get {
  32. return self._currentLineChangeAction
  33. }
  34. }
  35. @IBOutlet var lineWidthSlider: NSSlider!
  36. @IBOutlet var lineWidthField: NSTextField!
  37. @IBOutlet var dashPatternField: NSTextField!
  38. @IBOutlet var styleButton: NSSegmentedControl!
  39. @IBOutlet var startLineStyleButton: NSSegmentedControl!
  40. @IBOutlet var endLineStyleButton: NSSegmentedControl!
  41. @IBOutlet var lineWidthLabelField: NSTextField!
  42. @IBOutlet var styleLabelField: NSTextField!
  43. @IBOutlet var dashPatternLabelField: NSTextField!
  44. @IBOutlet var startLineStyleLabelField: NSTextField!
  45. @IBOutlet var endLineStyleLabelField: NSTextField!
  46. @IBOutlet var lineWell: KMLineWell!
  47. @IBOutlet weak var labelField1: NSTextField!
  48. @IBOutlet weak var labelField2: NSTextField!
  49. @IBOutlet weak var labelField3: NSTextField!
  50. @IBOutlet weak var labelField4: NSTextField!
  51. @IBOutlet weak var labelField5: NSTextField!
  52. var labelFields: [NSTextField] = []
  53. private var _lineWidth: CGFloat = 0
  54. var lineWidth: CGFloat {
  55. get {
  56. return self._lineWidth
  57. }
  58. set {
  59. if (abs(self.lineWidth - newValue) > 0.00001) {
  60. self._lineWidth = newValue
  61. self._notifyChangeAction(.lineWidth)
  62. }
  63. }
  64. }
  65. private var _style: Int = CPDFBorderStyle.solid.rawValue
  66. var style: Int {
  67. get {
  68. return self._style
  69. }
  70. set {
  71. if (newValue != self._style) {
  72. self._style = newValue
  73. self._notifyChangeAction(.style)
  74. }
  75. }
  76. }
  77. private var _startLineStyle: Int = CPDFLineStyle.none.rawValue
  78. var startLineStyle: Int {
  79. get {
  80. return self._startLineStyle
  81. }
  82. set {
  83. if (newValue != self.startLineStyle) {
  84. self._startLineStyle = newValue
  85. self._notifyChangeAction(.startLineStyle)
  86. }
  87. }
  88. }
  89. var _endLineStyle: Int = CPDFLineStyle.none.rawValue
  90. var endLineStyle: Int {
  91. get {
  92. return self._endLineStyle
  93. }
  94. set {
  95. if (newValue != self.endLineStyle) {
  96. self._endLineStyle = newValue
  97. self._notifyChangeAction(.endLineStyle)
  98. }
  99. }
  100. }
  101. private var _dashPattern: [CGFloat] = []
  102. var dashPattern: [CGFloat] {
  103. get {
  104. return self._dashPattern
  105. }
  106. set {
  107. if newValue != self._dashPattern && (newValue.isEmpty == false || self._dashPattern.isEmpty == false) {
  108. self._dashPattern = newValue
  109. self._notifyChangeAction(.dashPattern)
  110. }
  111. }
  112. }
  113. static let shared = KMLineInspector(windowNibName: "LineInspector")
  114. /*
  115. - (void)setAnnotationStyle:(PDFAnnotation *)annotation {
  116. NSString *type = [annotation type];
  117. if ([type isEqualToString:SKNFreeTextString] || [type isEqualToString:SKNCircleString] || [type isEqualToString:SKNSquareString] || [type isEqualToString:SKNLineString] || [type isEqualToString:SKNInkString]) {
  118. [self setLineWidth:[annotation border] ? [[annotation border] lineWidth] : 0.0];
  119. [self setDashPattern:[[annotation border] dashPattern]];
  120. [self setStyle:[annotation border] ? [[annotation border] style] : 0];
  121. }
  122. if ([type isEqualToString:SKNLineString]) {
  123. [self setStartLineStyle:[(PDFAnnotationLine *)annotation startLineStyle]];
  124. [self setEndLineStyle:[(PDFAnnotationLine *)annotation endLineStyle]];
  125. }
  126. }
  127. */
  128. override func windowDidLoad() {
  129. super.windowDidLoad()
  130. self.labelFields = [self.labelField1, self.labelField2, self.labelField3, self.labelField4, self.labelField5]
  131. self.style = CPDFBorderStyle.solid.rawValue
  132. self.lineWidth = 1.0
  133. self.dashPattern = []
  134. self.startLineStyle = CPDFLineStyle.none.rawValue
  135. self.endLineStyle = CPDFLineStyle.none.rawValue
  136. self._currentLineChangeAction = .no
  137. self.lineWell.canActivate = false
  138. // self.lineWell.bind(NSBindingName(rawValue: KMLineWell.widthKey), to: self, withKeyPath: LINEWIDTH_KEY)
  139. // self.lineWell.bind(NSBindingName(KMLineWell.styleKey), to: self, withKeyPath: STYLE_KEY)
  140. // self.lineWell.bind(NSBindingName(KMLineWell.dashPatternKey), to: self, withKeyPath: DASHPATTERN_KEY)
  141. // self.lineWell.bind(NSBindingName(KMLineWell.startLineStyleKey), to: self, withKeyPath: STARTLINESTYLE_KEY)
  142. // self.lineWell.bind(NSBindingName(KMLineWell.endLineStyleKey), to: self, withKeyPath: ENDLINESTYLE_KEY)
  143. self.styleButton.setHelp(KMLocalizedString("Solid line style", "Tool tip message"), for: CPDFBorderStyle.solid.rawValue)
  144. self.styleButton.setHelp(KMLocalizedString("Dashed line style", "Tool tip message"), for: CPDFBorderStyle.dashed.rawValue)
  145. self.styleButton.setHelp(KMLocalizedString("Beveled line style", "Tool tip message"), for: CPDFBorderStyle.beveled.rawValue)
  146. self.styleButton.setHelp(KMLocalizedString("Inset line style", "Tool tip message"), for: CPDFBorderStyle.inset.rawValue)
  147. self.styleButton.setHelp(KMLocalizedString("Underline line style", "Tool tip message"), for: CPDFBorderStyle.underline.rawValue)
  148. self.startLineStyleButton.setHelp(KMLocalizedString("No start line style", "Tool tip message"), for: CPDFLineStyle.none.rawValue)
  149. self.startLineStyleButton.setHelp(KMLocalizedString("Square start line style", "Tool tip message"), for: CPDFLineStyle.square.rawValue)
  150. self.startLineStyleButton.setHelp(KMLocalizedString("Circle start line style", "Tool tip message"), for: CPDFLineStyle.circle.rawValue)
  151. self.startLineStyleButton.setHelp(KMLocalizedString("Diamond start line style", "Tool tip message"), for: CPDFLineStyle.diamond.rawValue)
  152. self.startLineStyleButton.setHelp(KMLocalizedString("Open arrow start line style", "Tool tip message"), for: CPDFLineStyle.openArrow.rawValue)
  153. self.startLineStyleButton.setHelp(KMLocalizedString("Closed arrow start line style", "Tool tip message"), for: CPDFLineStyle.closedArrow.rawValue)
  154. self.endLineStyleButton.setHelp(KMLocalizedString("No end line style", "Tool tip message"), for: CPDFLineStyle.none.rawValue)
  155. self.endLineStyleButton.setHelp(KMLocalizedString("Square end line style", "Tool tip message"), for: CPDFLineStyle.square.rawValue)
  156. self.endLineStyleButton.setHelp(KMLocalizedString("Circle end line style", "Tool tip message"), for: CPDFLineStyle.circle.rawValue)
  157. self.endLineStyleButton.setHelp(KMLocalizedString("Diamond end line style", "Tool tip message"), for: CPDFLineStyle.diamond.rawValue)
  158. self.endLineStyleButton.setHelp(KMLocalizedString("Open arrow end line style", "Tool tip message"), for: CPDFLineStyle.openArrow.rawValue)
  159. self.endLineStyleButton.setHelp(KMLocalizedString("Closed arrow end line style", "Tool tip message"), for: CPDFLineStyle.closedArrow.rawValue)
  160. let dw = KMAutoSizeLabelFields(labelFields, [lineWidthSlider, lineWidthField, styleButton, dashPatternField, startLineStyleButton, endLineStyleButton], false)
  161. if (fabs(dw) > 0.0) {
  162. KMResizeWindow(self.window!, dw)
  163. }
  164. self.windowFrameAutosaveName = SKLineInspectorFrameAutosaveName
  165. var image: NSImage?
  166. var size = NSMakeSize(29.0, 12.0)
  167. image = NSImage.image(with: size, drawingHandler: { rect in
  168. let path = NSBezierPath(rect: NSMakeRect(6.0, 3.0, 17.0, 6.0))
  169. path.lineWidth = 2.0
  170. NSColor.black.setStroke()
  171. path.stroke()
  172. return true
  173. })
  174. self.styleButton.setImage(image, forSegment: CPDFBorderStyle.solid.rawValue)
  175. image = NSImage.image(with: size, drawingHandler: { dstRect in
  176. let path = NSBezierPath()
  177. path.move(to: NSMakePoint(6.0, 5.0))
  178. path.line(to: NSMakePoint(6.0, 3.0))
  179. path.line(to: NSMakePoint(9.0, 3.0))
  180. path.move(to: NSMakePoint(12.0, 3.0))
  181. path.line(to: NSMakePoint(17.0, 3.0))
  182. path.move(to: NSMakePoint(20.0, 3.0))
  183. path.line(to: NSMakePoint(23.0, 3.0))
  184. path.line(to: NSMakePoint(23.0, 5.0))
  185. path.move(to: NSMakePoint(23.0, 7.0))
  186. path.line(to: NSMakePoint(23.0, 9.0))
  187. path.line(to: NSMakePoint(20.0, 9.0))
  188. path.move(to: NSMakePoint(17.0, 9.0))
  189. path.line(to: NSMakePoint(12.0, 9.0))
  190. path.move(to: NSMakePoint(9.0, 9.0))
  191. path.line(to: NSMakePoint(6.0, 9.0))
  192. path.line(to: NSMakePoint(6.0, 7.0))
  193. path.lineWidth = 2.0
  194. NSColor.black.setStroke()
  195. path.stroke()
  196. return true
  197. })
  198. self.styleButton.setImage(image, forSegment: CPDFBorderStyle.dashed.rawValue)
  199. image = NSImage.image(with: size, drawingHandler: { dstRect in
  200. var path = NSBezierPath(rect: NSMakeRect(6.0, 3.0, 17.0, 6.0))
  201. path.lineWidth = 2.0
  202. NSColor(calibratedWhite: 0, alpha: 0.25).setStroke()
  203. path.stroke()
  204. path = NSBezierPath()
  205. path.move(to: NSMakePoint(7.0, 3.0))
  206. path.line(to: NSMakePoint(23.0, 3.0))
  207. path.line(to: NSMakePoint(23.0, 8.0))
  208. path.lineWidth = 2.0
  209. NSColor(calibratedWhite: 0, alpha: 0.35).set()
  210. path.stroke()
  211. path = NSBezierPath()
  212. path.move(to: NSMakePoint(5.0, 2.0))
  213. path.line(to: NSMakePoint(7.0, 4.0))
  214. path.line(to: NSMakePoint(7.0, 2.0))
  215. path.close()
  216. path.move(to: NSMakePoint(24.0, 10.0))
  217. path.line(to: NSMakePoint(22.0, 8.0))
  218. path.line(to: NSMakePoint(24.0, 8.0))
  219. path.close()
  220. path.fill()
  221. return true
  222. })
  223. self.styleButton.setImage(image, forSegment: CPDFBorderStyle.beveled.rawValue)
  224. image = NSImage.image(with: size, drawingHandler: { dstRect in
  225. var path = NSBezierPath(rect: NSMakeRect(6.0, 3.0, 17.0, 6.0))
  226. path.lineWidth = 2.0
  227. NSColor(calibratedWhite: 0, alpha: 0.25).setStroke()
  228. path.stroke()
  229. path = NSBezierPath()
  230. path.move(to: NSMakePoint(6.0, 4.0))
  231. path.line(to: NSMakePoint(6.0, 9.0))
  232. path.line(to: NSMakePoint(22.0, 9.0))
  233. path.lineWidth = 2.0
  234. NSColor(calibratedWhite: 0, alpha: 0.35).set()
  235. path.stroke()
  236. path = NSBezierPath()
  237. path.move(to: NSMakePoint(5.0, 2.0))
  238. path.line(to: NSMakePoint(7.0, 4.0))
  239. path.line(to: NSMakePoint(5.0, 4.0))
  240. path.close()
  241. path.move(to: NSMakePoint(24.0, 10.0))
  242. path.line(to: NSMakePoint(22.0, 8.0))
  243. path.line(to: NSMakePoint(22.0, 10.0))
  244. path.close()
  245. path.fill()
  246. return true
  247. })
  248. self.styleButton.setImage(image, forSegment: CPDFBorderStyle.inset.rawValue)
  249. image = NSImage.image(with: size, drawingHandler: { dstRect in
  250. let path = NSBezierPath()
  251. path.move(to: NSMakePoint(6.0, 3.0))
  252. path.line(to: NSMakePoint(23.0, 3.0))
  253. path.lineWidth = 2.0
  254. NSColor(calibratedWhite: 0, alpha: 0.5).setStroke()
  255. path.stroke()
  256. return true
  257. })
  258. self.styleButton.setImage(image, forSegment: CPDFBorderStyle.underline.rawValue)
  259. size = NSMakeSize(24.0, 12.0)
  260. image = NSImage.image(with: size, drawingHandler: { dstRect in
  261. let path = NSBezierPath()
  262. path.move(to: NSMakePoint(20.0, 6.0))
  263. path.line(to: NSMakePoint(8.0, 6.0))
  264. path.lineWidth = 2.0
  265. NSColor.black.setStroke()
  266. path.stroke()
  267. return true
  268. })
  269. self.startLineStyleButton.setImage(image, forSegment: CPDFLineStyle.none.rawValue)
  270. image = NSImage.image(with: size, drawingHandler: { dstRect in
  271. let path = NSBezierPath()
  272. path.move(to: NSMakePoint(4.0, 6.0))
  273. path.line(to: NSMakePoint(16.0, 6.0))
  274. path.lineWidth = 2.0
  275. NSColor.black.setStroke()
  276. path.stroke()
  277. return true
  278. })
  279. self.endLineStyleButton.setImage(image, forSegment: CPDFLineStyle.none.rawValue)
  280. image = NSImage.image(with: size, drawingHandler: { rect in
  281. let path = NSBezierPath()
  282. path.move(to: NSMakePoint(20.0, 6.0))
  283. path.line(to: NSMakePoint(8.0, 6.0))
  284. path.appendRect(NSMakeRect(5.0, 3.0, 6.0, 6.0))
  285. path.lineWidth = 2.0
  286. NSColor.black.setStroke()
  287. path.stroke()
  288. return true
  289. })
  290. self.startLineStyleButton.setImage(image, forSegment: CPDFLineStyle.square.rawValue)
  291. image = NSImage.image(with: size, drawingHandler: { dstRect in
  292. let path = NSBezierPath()
  293. path.move(to: NSMakePoint(4.0, 6.0))
  294. path.line(to: NSMakePoint(16.0, 6.0))
  295. path.appendRect(NSMakeRect(13.0, 3.0, 6.0, 6.0))
  296. path.lineWidth = 2.0
  297. NSColor.black.setStroke()
  298. path.stroke()
  299. return true
  300. })
  301. self.endLineStyleButton.setImage(image, forSegment: CPDFLineStyle.square.rawValue)
  302. image = NSImage.image(with: size, drawingHandler: { dstRect in
  303. let path = NSBezierPath()
  304. path.move(to: NSMakePoint(20.0, 6.0))
  305. path.line(to: NSMakePoint(8.0, 6.0))
  306. path.appendOval(in: NSMakeRect(5.0, 3.0, 6.0, 6.0))
  307. path.lineWidth = 2.0
  308. NSColor.black.setStroke()
  309. path.stroke()
  310. return true
  311. })
  312. self.startLineStyleButton.setImage(image, forSegment: CPDFLineStyle.circle.rawValue)
  313. image = NSImage.image(with: size, drawingHandler: { dstRect in
  314. let path = NSBezierPath()
  315. path.move(to: NSMakePoint(4.0, 6.0))
  316. path.line(to: NSMakePoint(16.0, 6.0))
  317. path.appendOval(in: NSMakeRect(13.0, 3.0, 6.0, 6.0))
  318. path.lineWidth = 2.0
  319. NSColor.black.setStroke()
  320. path.stroke()
  321. return true
  322. })
  323. self.endLineStyleButton.setImage(image, forSegment: CPDFLineStyle.circle.rawValue)
  324. image = NSImage.image(with: size, drawingHandler: { dstRect in
  325. let path = NSBezierPath()
  326. path.move(to: NSMakePoint(20.0, 6.0))
  327. path.line(to: NSMakePoint(8.0, 6.0))
  328. path.move(to: NSMakePoint(12.0, 6.0))
  329. path.line(to: NSMakePoint(8.0, 10.0))
  330. path.line(to: NSMakePoint(4.0, 6.0))
  331. path.line(to: NSMakePoint(8.0, 2.0))
  332. path.close()
  333. path.lineWidth = 2.0
  334. path.stroke()
  335. return true
  336. })
  337. self.startLineStyleButton.setImage(image, forSegment: CPDFLineStyle.diamond.rawValue)
  338. image = NSImage.image(with: size, drawingHandler: { dstRect in
  339. let path = NSBezierPath()
  340. path.move(to: NSMakePoint(4.0, 6.0))
  341. path.line(to: NSMakePoint(16.0, 6.0))
  342. path.move(to: NSMakePoint(12.0, 6.0))
  343. path.line(to: NSMakePoint(16.0, 10.0))
  344. path.line(to: NSMakePoint(20.0, 6.0))
  345. path.line(to: NSMakePoint(16.0, 2.0))
  346. path.close()
  347. path.lineWidth = 2.0
  348. path.stroke()
  349. return true
  350. })
  351. self.endLineStyleButton.setImage(image, forSegment: CPDFLineStyle.diamond.rawValue)
  352. image = NSImage.image(with: size, drawingHandler: { dstRect in
  353. let path = NSBezierPath()
  354. path.move(to: NSMakePoint(20.0, 6.0))
  355. path.line(to: NSMakePoint(8.0, 6.0))
  356. path.move(to: NSMakePoint(14.0, 3.0))
  357. path.line(to: NSMakePoint(8.0, 6.0))
  358. path.line(to: NSMakePoint(14.0, 9.0))
  359. path.lineWidth = 2.0
  360. NSColor.black.setStroke()
  361. path.stroke()
  362. return true
  363. })
  364. self.startLineStyleButton.setImage(image, forSegment: CPDFLineStyle.openArrow.rawValue)
  365. image = NSImage.image(with: size, drawingHandler: { dstRect in
  366. let path = NSBezierPath()
  367. path.move(to: NSMakePoint(4.0, 6.0))
  368. path.line(to: NSMakePoint(16.0, 6.0))
  369. path.move(to: NSMakePoint(10.0, 3.0))
  370. path.line(to: NSMakePoint(16.0, 6.0))
  371. path.line(to: NSMakePoint(10.0, 9.0))
  372. path.lineWidth = 2
  373. NSColor.black.setStroke()
  374. path.stroke()
  375. return true
  376. })
  377. self.endLineStyleButton.setImage(image, forSegment: CPDFLineStyle.openArrow.rawValue)
  378. image = NSImage.image(with: size, drawingHandler: { dstRect in
  379. let path = NSBezierPath()
  380. path.move(to: NSMakePoint(20.0, 6.0))
  381. path.line(to: NSMakePoint(8.0, 6.0))
  382. path.move(to: NSMakePoint(14.0, 3.0))
  383. path.line(to: NSMakePoint(8.0, 6.0))
  384. path.line(to: NSMakePoint(14.0, 9.0))
  385. path.close()
  386. path.lineWidth = 2
  387. NSColor.black.setStroke()
  388. path.stroke()
  389. return true
  390. })
  391. self.startLineStyleButton.setImage(image, forSegment: CPDFLineStyle.closedArrow.rawValue)
  392. image = NSImage.image(with: size, drawingHandler: { dstRect in
  393. let path = NSBezierPath()
  394. path.move(to: NSMakePoint(4.0, 6.0))
  395. path.line(to: NSMakePoint(16.0, 6.0))
  396. path.move(to: NSMakePoint(10.0, 3.0))
  397. path.line(to: NSMakePoint(16.0, 6.0))
  398. path.line(to: NSMakePoint(10.0, 9.0))
  399. path.close()
  400. path.lineWidth = 2
  401. NSColor.black.setStroke()
  402. path.stroke()
  403. return true
  404. })
  405. self.endLineStyleButton.setImage(image, forSegment: CPDFLineStyle.closedArrow.rawValue)
  406. }
  407. /*
  408. - (void)setNilValueForKey:(NSString *)key {
  409. if ([key isEqualToString:LINEWIDTH_KEY]) {
  410. [self setValue:[NSNumber numberWithDouble:0.0] forKey:key];
  411. } else if ([key isEqualToString:STYLE_KEY] || [key isEqualToString:STARTLINESTYLE_KEY] || [key isEqualToString:ENDLINESTYLE_KEY]) {
  412. [self setValue:[NSNumber numberWithInteger:0] forKey:key];
  413. } else {
  414. [super setNilValueForKey:key];
  415. }
  416. }
  417. */
  418. override func value(forUndefinedKey key: String) -> Any? {
  419. KMPrint("forUndefinedKey: \(key)")
  420. }
  421. }
  422. // MARK: - Private Methods
  423. extension KMLineInspector {
  424. private func _notifyChangeAction(_ action: KMLineChangeAction) {
  425. self._currentLineChangeAction = action
  426. let selector = NSSelectorFromString("changeLineAttribute:")
  427. let mainWindow = NSApp.mainWindow
  428. var responder = mainWindow?.firstResponder
  429. while (responder != nil && responder!.responds(to: selector) == false) {
  430. responder = responder!.nextResponder
  431. }
  432. responder?.perform(selector, with: self)
  433. let userInfo = [ACTION_KEY : NSNumber(value: action.rawValue)]
  434. NotificationCenter.default.post(name: NSNotification.Name(rawValue: SKLineInspectorLineAttributeDidChangeNotification), object: self, userInfo: userInfo)
  435. self._currentLineChangeAction = .no
  436. }
  437. }