KMMergeViewController.swift 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346
  1. //
  2. // KMMergeViewController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by tangchao on 2022/11/23.
  6. //
  7. import Cocoa
  8. import PDFKit
  9. import CoreGraphics
  10. class KMMergePage: CPDFPage {
  11. var drawingPage: CPDFPage!
  12. // override func draw(with box: PDFDisplayBox) {
  13. // super.draw(with: box)
  14. //
  15. // let context: CGContext = NSGraphicsContext.current?.graphicsPort as! CGContext
  16. // let pageSize = bounds(for: .cropBox).size
  17. //
  18. // drawPageWithContext(context: context, page: self.drawingPage, pageSize: pageSize)
  19. // }
  20. override func draw(with box: CPDFDisplayBox, to context: CGContext!) {
  21. super.draw(with: box, to: context)
  22. let pageSize = bounds(for: .cropBox).size
  23. drawPageWithContext(context: context, page: self.drawingPage, pageSize: pageSize)
  24. }
  25. func drawPageWithContext(context: CGContext, page: CPDFPage, pageSize: NSSize) {
  26. var originalSize = page.bounds(for: .cropBox).size
  27. /// 如果page的旋转角度为90,或者270,宽高交换
  28. if ((page.rotation % 180) != 0) {
  29. originalSize = NSSize(width: originalSize.height, height: originalSize.width)
  30. }
  31. let wRadio: CGFloat = pageSize.width/originalSize.width
  32. let hRadio: CGFloat = pageSize.height/originalSize.height
  33. let radio = min(wRadio, hRadio)
  34. context.saveGState()
  35. var xTransform: CGFloat = (pageSize.width-originalSize.width * radio) / 2
  36. var yTransform: CGFloat = (pageSize.height-originalSize.height * radio) / 2
  37. context.translateBy(x: xTransform, y: yTransform)
  38. context.scaleBy(x: radio, y: radio)
  39. page.draw(with: .cropBox, to: context)
  40. page.transform(context, for: .cropBox)
  41. // var contextRef: CGContextRef = context
  42. }
  43. }
  44. class KMMergeTestWindow: NSWindow {
  45. private var mergeController: KMMergeViewController!
  46. override init(contentRect: NSRect, styleMask style: NSWindow.StyleMask, backing backingStoreType: NSWindow.BackingStoreType, defer flag: Bool) {
  47. super.init(contentRect: contentRect, styleMask: style, backing: backingStoreType, defer: flag);
  48. isReleasedWhenClosed = false
  49. let controller: KMMergeViewController = KMMergeViewController()
  50. contentView?.addSubview(controller.view)
  51. controller.view.frame = CGRect(x: 0, y: 0, width: contentRect.size.width, height: contentRect.size.height)
  52. mergeController = controller
  53. }
  54. }
  55. protocol KMMergeViewController_collectionView_delegate : NSObjectProtocol {
  56. func collection_menu(for event: NSEvent) -> NSMenu?
  57. }
  58. class KMMergeViewController_collectionView: NSCollectionView {
  59. weak var myDelegate: KMMergeViewController_collectionView_delegate!
  60. override func menu(for event: NSEvent) -> NSMenu? {
  61. guard let myDelegate = self.myDelegate else {
  62. return super.menu(for: event)
  63. }
  64. return myDelegate.collection_menu(for: event)
  65. // return super.menu(for: event)
  66. }
  67. }
  68. class KMMergeViewController: NSViewController {
  69. @IBOutlet weak var titleBar: NSBox!
  70. @IBOutlet weak var contentBox: NSBox!
  71. private var titleBarView: KMMergeTitleBar?
  72. private var scrollView: NSScrollView?
  73. private var contentionView: KMMergeViewController_collectionView?
  74. private var zoomScale: CGFloat = 0
  75. private var zoomMinScale: CGFloat = 0.5
  76. private var zoomMaxScale: CGFloat = 8
  77. private lazy var dataArray: [KMMergeFileModel] = []
  78. private lazy var deleteArray: [Int] = []
  79. private var dragedIndexPaths: [IndexPath] = []
  80. private let localForDraggedTypes = NSPasteboard.PasteboardType(rawValue: "localForDraggedTypes")
  81. private var pageRangeWindowController: KMPageRangePickerWindowController!
  82. private var mergeSettingWindowController: KMMergeSettingWindowController!
  83. private var outPDFDocument = CPDFDocument()
  84. private var lockedFiles: [URL] = []
  85. override func viewDidLoad() {
  86. super.viewDidLoad()
  87. initDefaultValue()
  88. initSubViews()
  89. }
  90. /**
  91. * MARK: - 初始化值
  92. */
  93. func initDefaultValue() {
  94. titleBar.titlePosition = NSBox.TitlePosition.noTitle
  95. titleBar.contentViewMargins = NSSize.zero
  96. titleBar.boxType = NSBox.BoxType.custom
  97. titleBar.borderWidth = 0
  98. zoomScale = 0
  99. }
  100. func initSubViews() {
  101. let titleBarView_: KMMergeTitleBar = KMMergeTitleBar()
  102. titleBar.contentView?.addSubview(titleBarView_)
  103. titleBarView_.frame = NSMakeRect(0, 0, NSWidth(titleBar.bounds), NSHeight(titleBar.bounds))
  104. titleBarView_.autoresizingMask = NSView.AutoresizingMask(rawValue: 18)
  105. titleBarView_.delegate = self
  106. titleBarView_.wantsLayer = true
  107. titleBarView_.layer?.backgroundColor = NSColor.white.cgColor
  108. titleBarView = titleBarView_
  109. titleBarView?.setDeleteItemEnable(enable: false)
  110. titleBarView?.setPageRangeComboBoxHidden(isHidden: true)
  111. titleBarView_.itemClick = {
  112. [self] (itemIndex: KMMergeTitleBarButtonID) -> () in
  113. switch itemIndex {
  114. case .add:
  115. self.showAddMenu()
  116. break
  117. case .delete:
  118. for index in deleteArray {
  119. if index < dataArray.count {
  120. dataArray.remove(at: index)
  121. }
  122. }
  123. deleteArray.removeAll()
  124. self.titleBarView?.setDeleteItemEnable(enable: false)
  125. self.contentionView?.reloadData()
  126. break
  127. case .zoomOut:
  128. if zoomScale > zoomMaxScale {
  129. titleBarView?.setZoomItemEnable(zoomIn: false, enable: false)
  130. return
  131. }
  132. titleBarView?.setZoomItemEnable(zoomIn: true, enable: true)
  133. zoomScale += 0.5
  134. contentionView?.reloadData()
  135. break
  136. case .zoomIn:
  137. if zoomScale < zoomMinScale {
  138. titleBarView?.setZoomItemEnable(zoomIn: true, enable: false)
  139. return
  140. }
  141. titleBarView?.setZoomItemEnable(zoomIn: false, enable: true)
  142. zoomScale -= 0.5
  143. contentionView?.reloadData()
  144. break
  145. case .merge:
  146. if dataArray.count == 0 {
  147. let alert = NSAlert()
  148. alert.messageText = NSLocalizedString("没有文件", comment: "")
  149. alert.runModal()
  150. return
  151. }
  152. let windowController = KMMergeSettingWindowController.init(windowNibName: "KMMergeSettingWindowController")
  153. self.view.window?.beginSheet(windowController.window!)
  154. mergeSettingWindowController = windowController
  155. windowController.odd_even_mergeComboBox.isEnabled = dataArray.count == 2
  156. windowController.cancelClick = {
  157. [self] (window: NSWindow) -> () in
  158. self.view.window?.endSheet(window)
  159. }
  160. windowController.mergeClick = {
  161. [self] (windowController: NSWindowController) -> () in
  162. if mergeSettingWindowController.odd_even_mergeComboBox.state == .on { /// 奇偶数穿插合并
  163. let document = CPDFDocument()
  164. outPDFDocument = document
  165. mergeActionForOddEven()
  166. let panel = NSSavePanel()
  167. panel.nameFieldStringValue = "[新文件].pdf"
  168. let button = NSButton.init(checkboxWithTitle: "保存后打开文档", target: nil, action: nil)
  169. button.state = .on
  170. panel.accessoryView = button
  171. panel.isExtensionHidden = true
  172. let response = panel.runModal()
  173. if response == .OK {
  174. let url = panel.url
  175. let result = outPDFDocument!.write(to: panel.url!)
  176. if result {
  177. if button.state == .on { /// 开启文档
  178. } else {
  179. NSWorkspace.shared.openFile(url!.path)
  180. }
  181. }
  182. }
  183. } else { /// 正常合并
  184. let document = CPDFDocument()
  185. outPDFDocument = document
  186. mergeAction()
  187. let panel = NSSavePanel()
  188. panel.nameFieldStringValue = "[新文件].pdf"
  189. let button = NSButton.init(checkboxWithTitle: "保存后打开文档", target: nil, action: nil)
  190. button.state = .on
  191. panel.accessoryView = button
  192. panel.isExtensionHidden = true
  193. let response = panel.runModal()
  194. if response == .OK {
  195. let url = panel.url
  196. let result = document!.write(to: panel.url!)
  197. if result {
  198. if button.state == .on { /// 开启文档
  199. } else {
  200. NSWorkspace.shared.openFile(url!.path)
  201. }
  202. }
  203. }
  204. }
  205. self.view.window?.endSheet(windowController.window!)
  206. }
  207. break
  208. case .cancel:
  209. if dataArray.count == 0 {
  210. self.view.window?.close()
  211. } else {
  212. let alert = NSAlert()
  213. alert.messageText = NSLocalizedString("关闭将不会保存当前操作", comment: "")
  214. alert.addButton(withTitle: NSLocalizedString("关闭", comment: ""))
  215. alert.addButton(withTitle: NSLocalizedString("取消", comment: ""))
  216. let response = alert.runModal()
  217. if response == .alertFirstButtonReturn {
  218. self.view.window?.close()
  219. }
  220. }
  221. break
  222. }
  223. }
  224. titleBarView_.pageRangeClick = {
  225. [self] (index: Int, pageString: String) -> () in
  226. let model = self.titleBarView?.model
  227. if index == 0 {
  228. model?.pageRange = .all
  229. model?.updateChildPageRange(pageRange: .all)
  230. } else if index == 1 {
  231. model?.pageRange = .oddPages
  232. model?.updateChildPageRange(pageRange: .oddPages)
  233. } else if index == 2 {
  234. model?.pageRange = .evenPages
  235. model?.updateChildPageRange(pageRange: .evenPages)
  236. } else if index == 3 {
  237. if !isValidPagesString(pagesString: pageString) {
  238. let alert = NSAlert()
  239. alert.alertStyle = .warning
  240. alert.messageText = NSLocalizedString("Invalid page range or the page number is out of range. Please try again.", comment: "")
  241. alert.runModal()
  242. return
  243. }
  244. model?.pageRangeString = pageString
  245. model?.updateChildPageRange(pageRange: .custom)
  246. let pageNumbers = findSelectPage(fileModel: model!)
  247. for i in 0 ... (model?.pages.count)!-1 {
  248. let pageModel = model?.pages[i]
  249. if pageNumbers .contains(Int(pageModel!.pageID)+1) {
  250. pageModel!.selected = true
  251. } else {
  252. pageModel!.selected = false
  253. }
  254. }
  255. }
  256. self.contentionView?.reloadData()
  257. }
  258. let scrollView_ = NSScrollView()
  259. contentBox.contentView?.addSubview(scrollView_)
  260. scrollView_.frame = NSMakeRect(0, 0, NSWidth(contentBox.bounds), NSHeight(contentBox.bounds))
  261. scrollView_.autoresizingMask = NSView.AutoresizingMask(rawValue: 18)
  262. scrollView = scrollView_
  263. let layout = NSCollectionViewFlowLayout()
  264. layout.sectionInset = NSEdgeInsetsMake(20, 20, 20, 20)
  265. layout.minimumLineSpacing = 0
  266. layout.minimumInteritemSpacing = 2
  267. let contentionView_ = KMMergeViewController_collectionView()
  268. contentionView_.autoresizingMask = NSView.AutoresizingMask(rawValue: 18)
  269. contentionView_.collectionViewLayout = layout
  270. contentionView_.dataSource = self
  271. contentionView_.delegate = self
  272. contentionView_.register(KMMergeCollectionViewItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier(rawValue: "CellID"))
  273. contentionView_.register(KMMergeCollectionPageViewItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier(rawValue: "PageCellID"))
  274. contentionView_.registerForDraggedTypes([localForDraggedTypes])
  275. scrollView?.documentView = contentionView_
  276. contentionView = contentionView_
  277. contentionView?.isSelectable = true
  278. contentionView?.allowsMultipleSelection = true
  279. contentionView?.myDelegate = self
  280. contentionView?.reloadData()
  281. }
  282. func mergeActionForOddEven() {
  283. if (dataArray.count <= 1) {
  284. return
  285. }
  286. var rootPDFOutlineArray: [CPDFOutline] = []
  287. var pdfDocument = outPDFDocument
  288. var mergeOutline: Bool = true
  289. for fileModel in dataArray {
  290. if fileModel.pageRange != .all {
  291. mergeOutline = false
  292. }
  293. var pdfOutlineArray: [CPDFOutline] = []
  294. if (fileModel.document.outlineRoot != nil) {
  295. rootPDFOutlineArray.append(fileModel.document.outlineRoot())
  296. fetchAllChildren(outline: fileModel.document.outlineRoot(), containers: &pdfOutlineArray)
  297. pdfOutlineArray.removeObject(fileModel.document.outlineRoot())
  298. } else {
  299. var rootOutline = CPDFOutline()
  300. fileModel.document.setOutlineRoot(rootOutline)
  301. if fileModel.document.outlineRoot() != nil {
  302. rootPDFOutlineArray.append(fileModel.document.outlineRoot())
  303. }
  304. }
  305. for outline in pdfOutlineArray {
  306. /// 这段代码主要是调用他的getter方法;outline显示正确
  307. outline.destination?.page().document.dataRepresentation()
  308. }
  309. }
  310. let oddDocument = dataArray.first?.document
  311. let oddCount: Int = Int(oddDocument!.pageCount)
  312. let evenDocument = dataArray.last?.document!
  313. let evenCount: Int = Int(evenDocument!.pageCount)
  314. let count = min(oddCount-1, evenCount-1)
  315. for i in 0 ... count {
  316. pdfDocument!.insertPageObject((oddDocument?.page(at: UInt(i)))!, at: pdfDocument!.pageCount)
  317. pdfDocument!.insertPageObject((evenDocument?.page(at: UInt(i)))!, at: pdfDocument!.pageCount)
  318. }
  319. if oddCount > evenCount {
  320. for i in count ... oddCount-1 {
  321. pdfDocument!.insertPageObject((oddDocument?.page(at: UInt(i)))!, at: pdfDocument!.pageCount)
  322. }
  323. } else if oddCount < evenCount {
  324. for i in count ... evenCount-1 {
  325. pdfDocument!.insertPageObject((evenDocument?.page(at: UInt(i)))!, at: pdfDocument!.pageCount)
  326. }
  327. }
  328. if mergeOutline {
  329. pdfDocument?.setOutlineRoot(CPDFOutline())
  330. var index = 0
  331. for outlineRoot in rootPDFOutlineArray {
  332. if outlineRoot != nil && outlineRoot.numberOfChildren > 0 {
  333. for i in 0 ... outlineRoot.numberOfChildren-1 {
  334. pdfDocument!.outlineRoot().insertChild(outlineRoot.child(at: UInt(i)), at: UInt(index))
  335. index += 1
  336. }
  337. }
  338. }
  339. }
  340. handerReDraw()
  341. }
  342. func mergeAction() {
  343. if (dataArray.count <= 1) {
  344. // return
  345. }
  346. var rootPDFOutlineArray: [CPDFOutline] = []
  347. var pdfDocument = outPDFDocument
  348. var mergeOutline: Bool = true
  349. for fileModel in dataArray {
  350. if fileModel.pageRange != .all {
  351. mergeOutline = false
  352. }
  353. var pdfOutlineArray: [CPDFOutline] = []
  354. if (fileModel.document.outlineRoot() != nil) {
  355. rootPDFOutlineArray.append(fileModel.document.outlineRoot())
  356. fetchAllChildren(outline: fileModel.document.outlineRoot(), containers: &pdfOutlineArray)
  357. pdfOutlineArray.removeObject(fileModel.document.outlineRoot())
  358. } else {
  359. var rootOutline = CPDFOutline()
  360. fileModel.document.setOutlineRoot(rootOutline)
  361. if fileModel.document.outlineRoot() != nil {
  362. rootPDFOutlineArray.append(fileModel.document.outlineRoot())
  363. }
  364. }
  365. for outline in pdfOutlineArray {
  366. /// 这段代码主要是调用他的getter方法;outline显示正确
  367. outline.destination?.page().document.dataRepresentation()
  368. }
  369. if fileModel.pageRange == .all {
  370. for i in 0 ... fileModel.document.pageCount-1 {
  371. pdfDocument!.insertPageObject(fileModel.document.page(at: UInt(i))!, at: pdfDocument!.pageCount)
  372. }
  373. } else if fileModel.pageRange == .oddPages {
  374. for i in 0 ... fileModel.document.pageCount-1 {
  375. if i % 2 == 1 {
  376. continue
  377. }
  378. pdfDocument!.insertPageObject(fileModel.document.page(at: UInt(i))!, at: pdfDocument!.pageCount)
  379. }
  380. } else if fileModel.pageRange == .evenPages {
  381. for i in 0 ... fileModel.document.pageCount-1 {
  382. if i % 2 == 0 {
  383. continue
  384. }
  385. pdfDocument!.insertPageObject(fileModel.document.page(at: UInt(i))!, at: pdfDocument!.pageCount)
  386. }
  387. } else if fileModel.pageRange == .custom {
  388. let pageNumbers = self.findSelectPage(fileModel: fileModel)
  389. for i in pageNumbers {
  390. pdfDocument!.insertPageObject(fileModel.document.page(at: UInt(i-1))!, at: pdfDocument!.pageCount)
  391. }
  392. }
  393. }
  394. if mergeOutline {
  395. pdfDocument?.setOutlineRoot( CPDFOutline())
  396. var index = 0
  397. for outlineRoot in rootPDFOutlineArray {
  398. if outlineRoot != nil && outlineRoot.numberOfChildren > 0 {
  399. for i in 0 ... outlineRoot.numberOfChildren-1 {
  400. pdfDocument!.outlineRoot().insertChild(outlineRoot.child(at: UInt(i)), at: UInt(index))
  401. index += 1
  402. }
  403. }
  404. }
  405. }
  406. handerReDraw()
  407. }
  408. func handerReDraw() {
  409. if mergeSettingWindowController.selectedIndex == 0 { /// 原始尺寸
  410. } else {
  411. var pageSize = NSMakeSize(595, 841)
  412. if mergeSettingWindowController.selectedIndex == 1 { /// A4 595 x 841
  413. pageSize = NSMakeSize(595, 841)
  414. } else if mergeSettingWindowController.selectedIndex == 2 { /// A3 841 x 1190
  415. pageSize = NSMakeSize(841, 1190)
  416. } else if mergeSettingWindowController.selectedIndex == 3 { /// U.S.Letter 612 x 792
  417. pageSize = NSMakeSize(612, 792)
  418. } else if mergeSettingWindowController.selectedIndex == 4 { /// U.S.Legal 612 x 1108
  419. pageSize = NSMakeSize(612, 1108)
  420. } else if mergeSettingWindowController.selectedIndex == 5 { /// 自定义 595 x 841
  421. // pageSize = NSMakeSize(595, 841)
  422. pageSize.width = CGFloat(mergeSettingWindowController.customWidthTextField.floatValue)
  423. pageSize.height = CGFloat(mergeSettingWindowController.customHeightTextField.floatValue)
  424. }
  425. var pagesArray: [CPDFPage] = []
  426. let pageCount = outPDFDocument!.pageCount
  427. for _ in 0 ... pageCount-1 {
  428. pagesArray.append(outPDFDocument!.page(at: 0)!)
  429. outPDFDocument!.removePage(at: 0)
  430. }
  431. for i in 0 ... pageCount-1 {
  432. var page = KMMergePage()
  433. page.drawingPage = pagesArray[Int(i)]
  434. page.setBounds(NSMakeRect(0, 0, pageSize.width, pageSize.height), for: .cropBox)
  435. outPDFDocument!.insertPageObject(page, at: i)
  436. }
  437. /// 如果是自定义大小,删除所有的outline,因为合并出来的outline是无效的
  438. if mergeSettingWindowController.pageSizeComboBox.indexOfSelectedItem == 5 { /// 自定义 595 x 841
  439. let childCount: Int = Int(outPDFDocument!.outlineRoot().numberOfChildren)
  440. var array: [CPDFOutline] = []
  441. for i in 0 ... childCount-1 {
  442. array.append((outPDFDocument!.outlineRoot().child(at: UInt(i)))!)
  443. }
  444. for outline in array {
  445. outline.removeFromParent()
  446. }
  447. }
  448. }
  449. }
  450. func fetchAllChildren(outline: CPDFOutline, containers: inout [CPDFOutline]) {
  451. if !containers.contains(outline) {
  452. containers.append(outline)
  453. }
  454. if outline != nil && outline.numberOfChildren > 0 {
  455. for i in 0 ... (outline.numberOfChildren-1) {
  456. containers.append(outline.child(at: i)!)
  457. fetchAllChildren(outline: outline.child(at: i)!, containers: &containers)
  458. }
  459. }
  460. }
  461. func showAddMenu() {
  462. let menu: NSMenu = NSMenu()
  463. let addFileitem = menu.addItem(withTitle: NSLocalizedString("添加文件", comment: ""), action: #selector(itemAddFileAction), keyEquivalent: "")
  464. addFileitem.target = self
  465. let addFolderitem = menu.addItem(withTitle: NSLocalizedString("添加文件夹", comment: ""), action: #selector(itemAddFolderAction), keyEquivalent: "")
  466. addFolderitem.target = self
  467. let addOpenFileitem = menu.addItem(withTitle: NSLocalizedString("添加已打开文件", comment: ""), action: #selector(itemAddOpenFileAction), keyEquivalent: "")
  468. addOpenFileitem.target = self
  469. addOpenFileitem.action = nil
  470. let point: NSPoint = NSMakePoint(0, -10)
  471. menu.popUp(positioning: nil, at: point, in: titleBarView?.addItem)
  472. }
  473. @objc func itemAddFileAction() {
  474. let openPanel = NSOpenPanel()
  475. openPanel.title = NSLocalizedString("选择并合并文件。按下键盘上的命令按钮,逐次点击目标文件,即可选择多个文件", comment: "")
  476. openPanel.canChooseDirectories = false //是否允许选择目录
  477. openPanel.canChooseFiles = true //是否可以选择文件
  478. openPanel.allowsMultipleSelection = true //是否允许多选
  479. openPanel.allowedFileTypes = ["jpg","cur","bmp","jpeg","gif","png","tiff","tif",/*@"pic",*/"ico","icns","tga","psd","eps","hdr","jp2","jpc","pict","sgi","heic","pdf"]
  480. openPanel.beginSheetModal(for: view.window!, completionHandler: { result in
  481. if result != .OK {
  482. } else {
  483. for documentURL in openPanel.urls {
  484. self.addModel(documentURL: documentURL)
  485. }
  486. self.contentionView?.reloadData()
  487. self.dealLockedFiles()
  488. }
  489. })
  490. }
  491. @objc func itemAddFolderAction() {
  492. let openPanel = NSOpenPanel()
  493. openPanel.title = NSLocalizedString("选择并合并文件。按下键盘上的命令按钮,逐次点击目标文件,即可选择多个文件", comment: "")
  494. openPanel.canChooseDirectories = true
  495. openPanel.canChooseFiles = false
  496. openPanel.allowsMultipleSelection = true
  497. openPanel.beginSheetModal(for: view.window!, completionHandler: { [self] result in
  498. if result != .OK {
  499. } else {
  500. var result: [URL] = []
  501. for folderURL in openPanel.urls {
  502. findAllFiles(folder: folderURL, result: &result)
  503. }
  504. for documentURL in result {
  505. addModel(documentURL: documentURL)
  506. }
  507. self.contentionView?.reloadData()
  508. self.dealLockedFiles()
  509. }
  510. })
  511. }
  512. func findAllFiles(folder: URL, result: inout [URL]) {
  513. let fileManager = FileManager.default
  514. var isDirectory: ObjCBool = ObjCBool(false)
  515. fileManager.fileExists(atPath: folder.path, isDirectory: &isDirectory)
  516. if (!isDirectory.boolValue) {
  517. return
  518. }
  519. let contents = try?fileManager.contentsOfDirectory(at: folder, includingPropertiesForKeys: nil)
  520. if contents?.count == 0 {
  521. return
  522. }
  523. let array = ["jpg","cur","bmp","jpeg","gif","png","tiff","tif",/*@"pic",*/"ico","icns","tga","psd","eps","hdr","jp2","jpc","pict","sgi","heic","pdf"]
  524. for documentURL in contents! {
  525. var isDirectory: ObjCBool = ObjCBool(false)
  526. fileManager.fileExists(atPath: documentURL.path, isDirectory: &isDirectory)
  527. if (isDirectory.boolValue) {
  528. findAllFiles(folder: documentURL, result: &result)
  529. } else {
  530. if !array.contains(documentURL.pathExtension.lowercased()) {
  531. continue
  532. }
  533. result.append(documentURL)
  534. }
  535. }
  536. }
  537. @objc func itemAddOpenFileAction() {
  538. }
  539. func addModel(documentURL: URL) {
  540. let model: KMMergeFileModel = KMMergeFileModel();
  541. model.documentURL = documentURL
  542. if documentURL.pathExtension.lowercased() == "pdf" {
  543. model.document = CPDFDocument.init(url: documentURL)
  544. if model.document.isLocked {
  545. lockedFiles.append(documentURL)
  546. return
  547. }
  548. model.myDocument = CPDFDocument.init(url: documentURL)
  549. model.pageRange = .all
  550. model.page = model.document.page(at: 0)
  551. if model.document.pageCount > 1 {
  552. for i in 0 ... model.document.pageCount-1 {
  553. let pageModel = KMMergePageModel()
  554. pageModel.selected = true
  555. pageModel.pageID = Int(i)
  556. model.pages.append(pageModel)
  557. }
  558. } else {
  559. }
  560. } else {
  561. let doucument = CPDFDocument.init(url: documentURL)
  562. model.document = doucument
  563. model.page = doucument?.page(at: 0)
  564. model.document.insertPageObject(model.page, at: 0)
  565. }
  566. self.dataArray.append(model)
  567. }
  568. func replaceModel(documentURL: URL, index: Int) {
  569. if index >= 0 && index < dataArray.count {
  570. let model: KMMergeFileModel = KMMergeFileModel();
  571. model.documentURL = documentURL
  572. if documentURL.pathExtension.lowercased() == "pdf" {
  573. model.document = CPDFDocument.init(url: documentURL)
  574. model.myDocument = CPDFDocument.init(url: documentURL)
  575. model.pageRange = .all
  576. model.page = model.document.page(at: 0)
  577. if model.document.pageCount > 1 {
  578. for i in 0 ... model.document.pageCount {
  579. let pageModel = KMMergePageModel()
  580. pageModel.selected = true
  581. pageModel.pageID = Int(i)
  582. model.pages.append(pageModel)
  583. }
  584. } else {
  585. }
  586. } else {
  587. let doucument = CPDFDocument.init(url: documentURL)
  588. model.document = doucument
  589. model.page = doucument?.page(at: 0)
  590. model.document.insertPageObject(model.page, at: 0)
  591. }
  592. self.dataArray[index] = model
  593. }
  594. }
  595. func isValidPagesString(pagesString: String)-> Bool {
  596. var valid = false
  597. for ch in pagesString {
  598. if ch != "0" && ch != "1" && ch != "2" && ch != "3" && ch != "4" && ch != "5" && ch != "6" && ch != "7" && ch != "8" && ch != "9" && ch != "," && ch != "-" {
  599. valid = false
  600. break
  601. } else {
  602. valid = true
  603. }
  604. }
  605. return valid
  606. }
  607. func findSelectPage(fileModel: KMMergeFileModel) -> ([Int]) {
  608. if !isValidPagesString(pagesString: fileModel.pageRangeString) {
  609. return []
  610. }
  611. var result: [Int] = []
  612. let array = fileModel.pageRangeString.components(separatedBy: ",")
  613. for string in array {
  614. if string.isEmpty {
  615. return []
  616. } else {
  617. let pages = string .components(separatedBy: "-")
  618. if pages.count > 2 {
  619. return []
  620. } else if pages.count == 1 {
  621. let page = pages[0]
  622. if page.isEmpty || Int(page)! > fileModel.document.pageCount || Int(page)! == 0 {
  623. return []
  624. } else {
  625. var hasSame: Bool = false
  626. for i in result {
  627. if i == Int(page)! {
  628. hasSame = true
  629. return []
  630. }
  631. }
  632. if !hasSame {
  633. result.append(Int(page)!)
  634. }
  635. }
  636. } else if pages.count == 2 {
  637. let page1 = pages[0]
  638. let page2 = pages[1]
  639. if page1.isEmpty || page2.isEmpty || Int(page1)! >= Int(page2)! || Int(page2)! > fileModel.myDocument.pageCount || Int(page1)! == 0 {
  640. return []
  641. } else {
  642. var hasSame: Bool = false
  643. for i in Int(page1)! ... Int(page2)! {
  644. for j in result {
  645. if j == i {
  646. hasSame = true
  647. return []
  648. }
  649. }
  650. }
  651. if !hasSame {
  652. for i in Int(page1)! ... Int(page2)! {
  653. result.append(i)
  654. }
  655. }
  656. }
  657. }
  658. }
  659. }
  660. return result
  661. }
  662. func findFileModel(indexPath: IndexPath) -> (fileModel: KMMergeFileModel, pageIndex: Int) {
  663. var count: Int = 0
  664. var flagModel : KMMergeFileModel!
  665. var index: Int = NSNotFound
  666. for model in dataArray {
  667. if (flagModel != nil) {
  668. break
  669. }
  670. if model.open {
  671. for i in 0...(model.document.pageCount-1) {
  672. if count == indexPath.item {
  673. index = Int(i)
  674. flagModel = model
  675. break
  676. }
  677. count += 1
  678. }
  679. } else {
  680. if count == indexPath.item {
  681. flagModel = model
  682. break
  683. }
  684. count += 1
  685. }
  686. }
  687. return (flagModel, index)
  688. }
  689. func allItemIsExpanded() -> Bool {
  690. for fileModel in dataArray {
  691. if fileModel.canExpand() && !fileModel.open {
  692. return false
  693. }
  694. }
  695. return true
  696. }
  697. func allItemIsFolded() -> Bool {
  698. for fileModel in dataArray {
  699. if fileModel.open {
  700. return false
  701. }
  702. }
  703. return true
  704. }
  705. func dealLockedFiles() {
  706. if lockedFiles.count > 0 {
  707. let documentURL = lockedFiles.first
  708. let alert = NSAlert()
  709. alert.messageText = documentURL!.lastPathComponent.appending(", 已被保护")
  710. alert.addButton(withTitle: "输入密码")
  711. alert.addButton(withTitle: "关闭")
  712. let response = alert.runModal()
  713. if response == .alertFirstButtonReturn {
  714. let window = KMPasswordInputWindow.createWindow()
  715. window?.documentURL = documentURL!
  716. window?.type = .open
  717. window?.itemClick = { (_, index: Int, string: String) in
  718. if index == 1 {
  719. self.view.window?.endSheet(window!)
  720. self.lockedFiles.remove(at: 0)
  721. self.dealLockedFiles()
  722. } else {
  723. self.view.window?.endSheet(window!)
  724. let model = KMMergeFileModel()
  725. model.documentURL = documentURL
  726. model.document = CPDFDocument(url: documentURL!)
  727. model.document.unlock(withPassword: string)
  728. model.myDocument = CPDFDocument.init(url: documentURL)
  729. model.pageRange = .all
  730. model.page = model.document.page(at: 0)
  731. model.password = string
  732. if model.document.pageCount > 1 {
  733. for i in 0 ... model.document.pageCount-1 {
  734. let pageModel = KMMergePageModel()
  735. pageModel.selected = true
  736. pageModel.pageID = Int(i)
  737. model.pages.append(pageModel)
  738. }
  739. }
  740. self.dataArray.append(model)
  741. self.contentionView?.reloadData()
  742. self.lockedFiles.remove(at: 0)
  743. self.dealLockedFiles()
  744. }
  745. }
  746. self.view.window?.beginSheet(window!)
  747. } else {
  748. self.lockedFiles.remove(at: 0)
  749. self.dealLockedFiles()
  750. }
  751. }
  752. }
  753. /**
  754. * MARK: Menu Actions
  755. */
  756. @objc func expandAllMenuAction() {
  757. for fileModel in dataArray {
  758. if fileModel.canExpand() {
  759. fileModel.open = true
  760. }
  761. }
  762. self.contentionView?.reloadData()
  763. deleteArray.removeAll()
  764. titleBarView?.setDeleteItemEnable(enable: false)
  765. }
  766. @objc func foldAllMenuAction() {
  767. for fileModel in dataArray {
  768. fileModel.open = false
  769. }
  770. self.contentionView?.reloadData()
  771. }
  772. @objc func expandMenuAction(sender: NSMenuItem) {
  773. let index = sender.tag
  774. if index >= 0 && index < dataArray.count {
  775. let fileModel: KMMergeFileModel = dataArray[index]
  776. if fileModel.canExpand() {
  777. fileModel.open = true
  778. }
  779. self.contentionView?.reloadData()
  780. // if index < deleteArray.count {
  781. // deleteArray.remove(at: index)
  782. // }
  783. deleteArray.removeAll()
  784. if deleteArray.count > 0 {
  785. titleBarView?.setDeleteItemEnable(enable: true)
  786. } else {
  787. titleBarView?.setDeleteItemEnable(enable: false)
  788. }
  789. }
  790. }
  791. @objc func addMenuAction() {
  792. itemAddFileAction()
  793. }
  794. @objc func removeMenuAction(sender: NSMenuItem) {
  795. let index = sender.tag
  796. if index >= 0 && index < dataArray.count {
  797. dataArray.remove(at: index)
  798. self.contentionView?.reloadData()
  799. }
  800. }
  801. @objc func replaceMenuAction(sender: NSMenuItem) {
  802. let index = sender.tag
  803. if index >= 0 && index < dataArray.count {
  804. let openPanel = NSOpenPanel()
  805. openPanel.title = NSLocalizedString("选择并合并文件。按下键盘上的命令按钮,逐次点击目标文件,即可选择多个文件", comment: "")
  806. openPanel.canChooseDirectories = false
  807. openPanel.canChooseFiles = true
  808. openPanel.allowsMultipleSelection = false
  809. openPanel.allowedFileTypes = ["jpg","cur","bmp","jpeg","gif","png","tiff","tif",/*@"pic",*/"ico","icns","tga","psd","eps","hdr","jp2","jpc","pict","sgi","heic","pdf"]
  810. openPanel.beginSheetModal(for: view.window!, completionHandler: { result in
  811. if result != .OK {
  812. } else {
  813. for documentURL in openPanel.urls {
  814. self.replaceModel(documentURL: documentURL, index: index)
  815. }
  816. self.contentionView?.reloadData()
  817. }
  818. })
  819. }
  820. }
  821. }
  822. extension KMMergeViewController: KMMergeTitleBarDelegate {
  823. func titleBar(titleBar: KMMergeTitleBar, itemDidClick: KMMergeTitleBarButtonID) {
  824. KMPrint();
  825. }
  826. }
  827. extension KMMergeViewController: NSCollectionViewDataSource {
  828. func numberOfSections(in collectionView: NSCollectionView) -> Int {
  829. return 1
  830. }
  831. func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
  832. var count: Int = 0
  833. for model in dataArray {
  834. if model.open {
  835. count += Int(model.document.pageCount)
  836. } else {
  837. count += 1
  838. }
  839. }
  840. return count
  841. }
  842. func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
  843. var count: Int = 0
  844. var flagModel : KMMergeFileModel!
  845. var index: Int = NSNotFound
  846. for model in dataArray {
  847. if (flagModel != nil) {
  848. break
  849. }
  850. if model.open {
  851. for i in 0...(model.document.pageCount-1) {
  852. if count == indexPath.item {
  853. index = Int(i)
  854. flagModel = model
  855. break
  856. }
  857. count += 1
  858. }
  859. } else {
  860. if count == indexPath.item {
  861. flagModel = model
  862. break
  863. }
  864. count += 1
  865. }
  866. }
  867. if index == NSNotFound {
  868. let cellView: KMMergeCollectionViewItem = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "CellID"), for: indexPath) as! KMMergeCollectionViewItem
  869. cellView.model = flagModel
  870. cellView.doubleClick = {
  871. [self] (viewItem: AnyObject) -> () in
  872. let cellItemView: KMMergeCollectionViewItem = viewItem as! KMMergeCollectionViewItem
  873. let model = cellItemView.model
  874. if model.canExpand() {
  875. model.open = true
  876. self.titleBarView?.setPageRangeComboBoxHidden(isHidden: false)
  877. self.titleBarView?.model = model
  878. self.contentionView?.reloadData()
  879. // if deleteArray.contains(indexPath.item) {
  880. // deleteArray.removeObject(indexPath.item)
  881. // }
  882. deleteArray.removeAll()
  883. if deleteArray.count > 0 {
  884. titleBarView?.setDeleteItemEnable(enable: true)
  885. } else {
  886. titleBarView?.setDeleteItemEnable(enable: false)
  887. }
  888. }
  889. }
  890. cellView.pageRangeClick = {
  891. [self] (viewItem: AnyObject) -> () in
  892. let cellItemView: KMMergeCollectionViewItem = viewItem as! KMMergeCollectionViewItem
  893. let model = cellItemView.model
  894. let window = KMPageRangePickerWindowController.init(windowNibName: "KMPageRangePickerWindowController")
  895. window.fileModel = model
  896. self.view.window?.beginSheet(window.window!)
  897. pageRangeWindowController = window
  898. window.cancelClick = {
  899. [self] (window: NSWindow)->() in
  900. self.view.window?.endSheet(window)
  901. }
  902. window.confirmClick = {
  903. [self] (windowController: NSWindowController)->() in
  904. if pageRangeWindowController.selectIndex == 0 {
  905. model.pageRange = .all
  906. model.updateChildPageRange(pageRange: .all)
  907. } else if pageRangeWindowController.selectIndex == 1 {
  908. model.pageRange = .oddPages
  909. model.updateChildPageRange(pageRange: .oddPages)
  910. } else if pageRangeWindowController.selectIndex == 2 {
  911. model.pageRange = .evenPages
  912. model.updateChildPageRange(pageRange: .evenPages)
  913. } else if pageRangeWindowController.selectIndex == 3 {
  914. model.pageRange = .custom
  915. model.pageRangeString = pageRangeWindowController.customPagesTextField.stringValue
  916. model.updateChildPageRange(pageRange: .custom)
  917. let pageNumbers = findSelectPage(fileModel: model)
  918. for i in 0 ... (model.pages.count)-1 {
  919. let pageModel = model.pages[i]
  920. if pageNumbers .contains(Int(pageModel.pageID)+1) {
  921. pageModel.selected = true
  922. } else {
  923. pageModel.selected = false
  924. }
  925. }
  926. }
  927. self.contentionView?.reloadItems(at: [indexPath])
  928. self.view.window?.endSheet(windowController.window!)
  929. }
  930. }
  931. return cellView
  932. } else {
  933. let cellView: KMMergeCollectionPageViewItem = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "PageCellID"), for: indexPath) as! KMMergeCollectionPageViewItem
  934. let model = flagModel.pages[index]
  935. model.page = flagModel.document.page(at: UInt(index))
  936. cellView.fileModel = flagModel
  937. cellView.model = model
  938. cellView.flodClick = {
  939. [self] (viewItem: AnyObject) -> () in
  940. let cellItemView: KMMergeCollectionPageViewItem = viewItem as! KMMergeCollectionPageViewItem
  941. let model = cellItemView.fileModel
  942. model.open = false
  943. self.titleBarView?.setPageRangeComboBoxHidden(isHidden: true)
  944. self.contentionView?.reloadData()
  945. }
  946. cellView.selectedClick = {
  947. [self] (viewItem: AnyObject) -> () in
  948. let cellItemView: KMMergeCollectionPageViewItem = viewItem as! KMMergeCollectionPageViewItem
  949. let model = cellItemView.model
  950. model.selected = !model.selected
  951. self.titleBarView?.setPageRangeComboBoxHidden(isHidden: false)
  952. cellView.fileModel.updatePagePange()
  953. self.titleBarView?.model = cellView.fileModel
  954. self.contentionView?.reloadItems(at: [indexPath])
  955. }
  956. cellView.view.wantsLayer = true
  957. cellView.view.layer?.backgroundColor = NSColor.lightGray.cgColor
  958. return cellView
  959. }
  960. return NSCollectionViewItem()
  961. }
  962. }
  963. extension KMMergeViewController: NSCollectionViewDelegateFlowLayout {
  964. /**
  965. * MARK: item大小
  966. */
  967. func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> NSSize {
  968. return NSMakeSize(246 * (1 + zoomScale), 322 * (1 + zoomScale))
  969. }
  970. func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
  971. return 0.01
  972. }
  973. func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
  974. return -5
  975. }
  976. }
  977. extension KMMergeViewController: NSCollectionViewDelegate {
  978. func collectionView(_ collectionView: NSCollectionView, shouldSelectItemsAt indexPaths: Set<IndexPath>) -> Set<IndexPath> {
  979. return indexPaths
  980. }
  981. func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set<IndexPath>) {
  982. let index: IndexPath = indexPaths.first!
  983. var i = 0
  984. for model in dataArray {
  985. if i == index.item {
  986. model.selected = true
  987. } else {
  988. model.selected = false
  989. }
  990. i += 1
  991. }
  992. deleteArray.append(index.item)
  993. if collectionView.selectionIndexes.count > 0 {
  994. titleBarView?.setDeleteItemEnable(enable: true)
  995. } else {
  996. titleBarView?.setDeleteItemEnable(enable: false)
  997. }
  998. }
  999. func collectionView(_ collectionView: NSCollectionView, shouldDeselectItemsAt indexPaths: Set<IndexPath>) -> Set<IndexPath> {
  1000. return indexPaths
  1001. }
  1002. func collectionView(_ collectionView: NSCollectionView, didDeselectItemsAt indexPaths: Set<IndexPath>) {
  1003. let index: IndexPath = indexPaths.first!
  1004. deleteArray.removeObject(index.item)
  1005. if collectionView.selectionIndexes.count > 0 {
  1006. titleBarView?.setDeleteItemEnable(enable: true)
  1007. } else {
  1008. titleBarView?.setDeleteItemEnable(enable: false)
  1009. titleBarView?.setPageRangeComboBoxHidden(isHidden: true)
  1010. }
  1011. }
  1012. func collectionView(_ collectionView: NSCollectionView, canDragItemsAt indexPaths: Set<IndexPath>, with event: NSEvent) -> Bool {
  1013. for indexPath in indexPaths {
  1014. let pageIndex = findFileModel(indexPath: indexPath).pageIndex
  1015. if pageIndex != NSNotFound { /// 页面不用拖拽
  1016. return false
  1017. }
  1018. }
  1019. return true
  1020. }
  1021. func collectionView(_ collectionView: NSCollectionView, writeItemsAt indexPaths: Set<IndexPath>, to pasteboard: NSPasteboard) -> Bool {
  1022. let data: Data = try! NSKeyedArchiver.archivedData(withRootObject: indexPaths, requiringSecureCoding: true)
  1023. pasteboard.declareTypes([self.localForDraggedTypes], owner: self)
  1024. pasteboard.setData(data, forType: self.localForDraggedTypes)
  1025. dragedIndexPaths.removeAll()
  1026. for indexPath in indexPaths {
  1027. dragedIndexPaths.append(indexPath)
  1028. }
  1029. return true
  1030. }
  1031. func collectionView(_ collectionView: NSCollectionView, validateDrop draggingInfo: NSDraggingInfo, proposedIndexPath proposedDropIndexPath: AutoreleasingUnsafeMutablePointer<NSIndexPath>, dropOperation proposedDropOperation: UnsafeMutablePointer<NSCollectionView.DropOperation>) -> NSDragOperation {
  1032. let pboard = draggingInfo.draggingPasteboard
  1033. if (pboard.availableType(from: [localForDraggedTypes]) != nil) {
  1034. return .move
  1035. }
  1036. return NSDragOperation.generic
  1037. }
  1038. func collectionView(_ collectionView: NSCollectionView, acceptDrop draggingInfo: NSDraggingInfo, indexPath: IndexPath, dropOperation: NSCollectionView.DropOperation) -> Bool {
  1039. let pboard = draggingInfo.draggingPasteboard
  1040. if (pboard.availableType(from: [localForDraggedTypes]) != nil) {
  1041. // let indexPathsData: Data = pboard.data(forType: self.localForDraggedTypes)!
  1042. // let set = try!NSKeyedUnarchiver.unarchivedObject(ofClasses: Set<IndexPath.self>, from: indexPathsData)!
  1043. let dragIndex: Int = dragedIndexPaths.first!.item
  1044. let toIndex = max(0, indexPath.item-1)
  1045. if dragIndex < 0 || dragIndex > dataArray.count {
  1046. return false
  1047. }
  1048. if dragIndex == toIndex {
  1049. return false
  1050. }
  1051. /// 交互数据
  1052. let dragFileModel = dataArray[dragIndex]
  1053. dataArray.removeObject(dragFileModel)
  1054. dataArray.insert(dragFileModel, at: toIndex)
  1055. self.contentionView?.reloadData()
  1056. return true
  1057. }
  1058. return false
  1059. }
  1060. }
  1061. extension KMMergeViewController : KMMergeViewController_collectionView_delegate {
  1062. func collection_menu(for event: NSEvent) -> NSMenu? {
  1063. let point = event.locationInWindow
  1064. let rigthIndex = self.contentionView!.indexPathForItem(at: self.contentionView!.convert(point, from: nil))
  1065. if rigthIndex == nil { /// 空白处
  1066. let menu = NSMenu(title: "")
  1067. if dataArray.count == 0 {
  1068. } else {
  1069. if allItemIsExpanded() {
  1070. let foldAllItem = NSMenuItem(title: NSLocalizedString("折叠全部文件", comment: ""), action: #selector(foldAllMenuAction), keyEquivalent: "")
  1071. foldAllItem.target = self
  1072. menu.addItem(foldAllItem)
  1073. } else if allItemIsFolded() {
  1074. let expandAllItem = NSMenuItem(title: NSLocalizedString("展开全部文件", comment: ""), action: #selector(expandAllMenuAction), keyEquivalent: "")
  1075. expandAllItem.target = self
  1076. menu.addItem(expandAllItem)
  1077. } else {
  1078. let expandAllItem = NSMenuItem(title: NSLocalizedString("展开全部文件", comment: ""), action: #selector(expandAllMenuAction), keyEquivalent: "")
  1079. expandAllItem.target = self
  1080. menu.addItem(expandAllItem)
  1081. let foldAllItem = NSMenuItem(title: NSLocalizedString("折叠全部文件", comment: ""), action: #selector(foldAllMenuAction), keyEquivalent: "")
  1082. foldAllItem.target = self
  1083. menu.addItem(foldAllItem)
  1084. }
  1085. }
  1086. let addItem = NSMenuItem(title: NSLocalizedString("添加文件", comment: ""), action: #selector(addMenuAction), keyEquivalent: "")
  1087. addItem.target = self
  1088. menu.addItem(addItem)
  1089. return menu
  1090. }
  1091. let cellView = self.contentionView!.item(at: rigthIndex!)
  1092. if ((cellView?.isKind(of: KMMergeCollectionViewItem.self))! == true) {
  1093. let fileCellView: KMMergeCollectionViewItem = cellView! as! KMMergeCollectionViewItem
  1094. var index = 0
  1095. var indexTag = NSNotFound
  1096. for fileModel in dataArray {
  1097. if fileModel.isEqual(to: fileCellView.model) {
  1098. indexTag = index
  1099. break
  1100. }
  1101. index += 1
  1102. }
  1103. let menu = NSMenu(title: "")
  1104. let expandItem = NSMenuItem(title: NSLocalizedString("展开文件", comment: ""), action: #selector(expandMenuAction), keyEquivalent: "")
  1105. expandItem.target = self
  1106. expandItem.tag = indexTag
  1107. if fileCellView.model.canExpand() {
  1108. expandItem.action = #selector(expandMenuAction)
  1109. } else {
  1110. expandItem.action = nil
  1111. }
  1112. menu.addItem(expandItem)
  1113. let expandAllItem = NSMenuItem(title: NSLocalizedString("展开全部文件", comment: ""), action: #selector(expandAllMenuAction), keyEquivalent: "")
  1114. expandAllItem.target = self
  1115. menu.addItem(expandAllItem)
  1116. menu.addItem(NSMenuItem.separator())
  1117. let removeItem = NSMenuItem(title: NSLocalizedString("移除文件", comment: ""), action: #selector(removeMenuAction), keyEquivalent: "")
  1118. removeItem.target = self
  1119. removeItem.tag = indexTag
  1120. menu.addItem(removeItem)
  1121. menu.addItem(NSMenuItem.separator())
  1122. let replaceItem = NSMenuItem(title: NSLocalizedString("替换文件", comment: ""), action: #selector(replaceMenuAction), keyEquivalent: "")
  1123. replaceItem.target = self
  1124. replaceItem.tag = indexTag
  1125. menu.addItem(replaceItem)
  1126. let addItem = NSMenuItem(title: NSLocalizedString("添加文件", comment: ""), action: #selector(addMenuAction), keyEquivalent: "")
  1127. addItem.target = self
  1128. menu.addItem(addItem)
  1129. return menu
  1130. }
  1131. return nil
  1132. }
  1133. }