KMNQuickToolWindowController.swift 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. //
  2. // KMNQuickToolWindowController.swift
  3. // PDF Reader Pro
  4. //
  5. // Created by 丁林圭 on 2024/10/10.
  6. //
  7. import Cocoa
  8. import KMComponentLibrary
  9. //MARK: - KMNQuickToolWindowDelegate
  10. protocol KMNQuickToolWindowDelegate: AnyObject {
  11. func quickToolWindowControllerUpdate()
  12. }
  13. //MARK: - KMNQuickToolWindowController
  14. class KMNQuickToolWindowController: KMNBaseWindowController, NSCollectionViewDelegate, NSCollectionViewDataSource,NSCollectionViewDelegateFlowLayout {
  15. weak open var delegate: KMNQuickToolWindowDelegate?
  16. @IBOutlet var viewBackBox: NSBox!
  17. @IBOutlet var titleLabel: NSTextField!
  18. @IBOutlet var titleBox: NSBox!
  19. @IBOutlet var titleSubLabel: NSTextField!
  20. @IBOutlet var showBox: NSBox!
  21. @IBOutlet var showCollectionView: NSCollectionView!
  22. @IBOutlet var cancelButton: ComponentButton!
  23. @IBOutlet var applyButton: ComponentButton!
  24. @IBOutlet var cancelWidthButton:NSLayoutConstraint!
  25. @IBOutlet var applyWidthButton:NSLayoutConstraint!
  26. var quickToolsItemMutableArray: [Int] = []
  27. var draggedItemIndexPath: IndexPath?
  28. var changeIndexPaths: Set<IndexPath> = []
  29. lazy var showDates: [KMNHomeQuickToolMode] = {
  30. var fullDatas: [KMNHomeQuickToolMode] = []
  31. for itemRaw in KMNHomeQuickToolManager.defaultManager.fullToolsItemMutableArray {
  32. let toolMode = KMNHomeQuickToolMode.toolModeData(type: HomeQuickToolType(rawValue: itemRaw) ?? .Batch)
  33. fullDatas.append(toolMode)
  34. }
  35. return fullDatas
  36. }()
  37. override func windowDidLoad() {
  38. super.windowDidLoad()
  39. quickToolsItemMutableArray = KMNHomeQuickToolManager.defaultManager.quickToolsItemMutableArray
  40. updateButtonState()
  41. showCollectionView.delegate = self
  42. showCollectionView.dataSource = self
  43. showCollectionView.isSelectable = true //支持拖拽需设置未True
  44. showCollectionView.register(KMNQuickToolCollectionViewItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier(rawValue: "KMNQuickToolShowCollectionViewItem"))
  45. showCollectionView.registerForDraggedTypes([.string])
  46. showCollectionView.setDraggingSourceOperationMask(.every, forLocal: false)
  47. showCollectionView.setDraggingSourceOperationMask(.every, forLocal: true)
  48. }
  49. func reloadData() {
  50. showCollectionView.reloadData()
  51. }
  52. override func initContentView() {
  53. titleLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-m-medium")
  54. titleSubLabel.font = ComponentLibrary.shared.getFontFromKey ("mac/body-xs-regular")
  55. applyButton.properties = ComponentButtonProperty(type: .primary,
  56. size: .s,
  57. state: .normal,
  58. buttonText: KMLocalizedString("Apply"))
  59. applyButton.setTarget(self, action: #selector(applyButtonClicked(_ :)))
  60. applyButton.keyEquivalent = KMKeyEquivalent.enter
  61. cancelButton.properties = ComponentButtonProperty(type: .default_tertiary,
  62. size: .s,
  63. state: .normal,
  64. buttonText: KMLocalizedString("Cancel"))
  65. cancelButton.setTarget(self, action: #selector(cancelButtonClicked(_ :)))
  66. cancelButton.keyEquivalent = KMKeyEquivalent.esc.string()
  67. }
  68. override func updateUIThemeColor() {
  69. window?.contentView?.wantsLayer = true
  70. window?.contentView?.layer?.backgroundColor = ComponentLibrary.shared.getComponentColorFromKey("colorBg/popup").cgColor
  71. titleLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/1")
  72. titleBox.fillColor = ComponentLibrary.shared.getComponentColorFromKey("colorFill/3-default")
  73. titleBox.borderColor = ComponentLibrary.shared.getComponentColorFromKey("colorBorder/3-default")
  74. titleSubLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2")
  75. cancelButton.reloadData()
  76. applyButton.reloadData()
  77. }
  78. override func updateUILanguage() {
  79. titleSubLabel.stringValue = KMLocalizedString("Select a maximum of 8 tools. You can drag and drop to reorder the tools display.")
  80. titleLabel.stringValue = KMLocalizedString("Manage Quick Tools")
  81. showCollectionView.reloadData()
  82. cancelButton.properties.buttonText = KMLocalizedString("Cancel")
  83. applyButton.properties.buttonText = KMLocalizedString("Apply")
  84. cancelButton.reloadData()
  85. applyButton.reloadData()
  86. cancelWidthButton.constant = cancelButton.properties.propertyInfo.viewWidth
  87. applyWidthButton.constant = applyButton.properties.propertyInfo.viewWidth
  88. }
  89. private func updateButtonState() {
  90. if self.quickToolsItemMutableArray.count < 1 {
  91. if applyButton.properties.isDisabled == false {
  92. applyButton.properties.isDisabled = true
  93. applyButton.reloadData()
  94. }
  95. } else {
  96. if applyButton.properties.isDisabled == true {
  97. applyButton.properties.isDisabled = false
  98. applyButton.reloadData()
  99. }
  100. }
  101. }
  102. private func updateCellOpacity(at location: NSPoint, opacity: CGFloat) {
  103. let pointInCollectionView = showCollectionView.convert(location, from: nil)
  104. if let indexPath = showCollectionView.indexPathForItem(at: pointInCollectionView) {
  105. if let item = showCollectionView.item(at: indexPath) as? KMNQuickToolCollectionViewItem {
  106. item.view.alphaValue = opacity
  107. }
  108. }
  109. }
  110. private func resetCellOpacity() {
  111. for item in showCollectionView.visibleItems() {
  112. item.view.alphaValue = 1.0
  113. }
  114. }
  115. //MARK: - Action
  116. @objc func cancelButtonClicked(_ sender: NSView) {
  117. own_closeEndSheet()
  118. }
  119. @objc func applyButtonClicked(_ sender: NSView) {
  120. var seleteDatas:[Int] = []
  121. var fullDatas:[Int] = []
  122. for i in 0 ... showDates.count-1 {
  123. let indexPath = NSIndexPath(forItem: i, inSection: 0)
  124. if let cell = showCollectionView.item(at: indexPath as IndexPath) as? KMNQuickToolCollectionViewItem {
  125. if cell.itemCardView.properties.isSelected == true {
  126. seleteDatas.append(cell.quickToolModel.quickToolType.rawValue)
  127. }
  128. fullDatas.append(cell.quickToolModel.quickToolType.rawValue)
  129. }
  130. }
  131. KMNHomeQuickToolManager.defaultManager.quickToolsItemMutableArray = seleteDatas
  132. KMNHomeQuickToolManager.defaultManager.fullToolsItemMutableArray = fullDatas
  133. self.delegate?.quickToolWindowControllerUpdate()
  134. own_closeEndSheet()
  135. }
  136. //MARK: - NSCollectionViewDataSource
  137. func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
  138. return showDates.count
  139. }
  140. func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
  141. let item: KMNQuickToolCollectionViewItem = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "KMNQuickToolShowCollectionViewItem"), for: indexPath) as! KMNQuickToolCollectionViewItem
  142. item.quickToolModel = showDates[indexPath.item]
  143. item.isNewState = item.quickToolModel.isNewState
  144. if(quickToolsItemMutableArray.contains(item.quickToolModel.quickToolType.rawValue)) {
  145. item.isShowState = true
  146. } else {
  147. item.isShowState = false
  148. }
  149. item.clickCallBack = {[weak self] isSelecton in
  150. guard let weakSelf = self else { return }
  151. if(isSelecton) {
  152. if(weakSelf.quickToolsItemMutableArray.count < 8) {
  153. weakSelf.quickToolsItemMutableArray.append(item.quickToolModel.quickToolType.rawValue)
  154. } else {
  155. item.isShowState = false
  156. let contextString = KMLocalizedString("You can select up to 8 tools. Please cancel and select.")
  157. let superView = weakSelf.window?.contentView ?? NSView()
  158. _ = KMNCustomAlertView.alertView(message: contextString, type: .normal_custom, fromView: superView, point:CGPointMake(superView.frame.origin.x + superView.frame.size.width/2, superView.frame.origin.y + superView.frame.size.height/2))
  159. }
  160. } else {
  161. weakSelf.quickToolsItemMutableArray.removeObject(item.quickToolModel.quickToolType.rawValue)
  162. }
  163. weakSelf.updateButtonState()
  164. }
  165. return item
  166. }
  167. // MARK: - NSCollectionViewDelegateFlowLayout
  168. func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> NSSize {
  169. return CGSize(width: 204.0, height: 56.0)
  170. }
  171. func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
  172. return 4
  173. }
  174. func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
  175. return 4
  176. }
  177. public func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, insetForSectionAt section: Int) -> NSEdgeInsets {
  178. return NSEdgeInsetsMake(0, 8, 0, 0)
  179. }
  180. //MARK: - NSCollectionViewDelegate
  181. func collectionView(_ collectionView: NSCollectionView, canDragItemsAt indexPaths: Set<IndexPath>, with event: NSEvent) -> Bool {
  182. return true
  183. }
  184. func collectionView(_ collectionView: NSCollectionView, pasteboardWriterForItemAt indexPath: IndexPath) -> NSPasteboardWriting? {
  185. return String(indexPath.item) as NSPasteboardWriting
  186. }
  187. func collectionView(_ collectionView: NSCollectionView, validateDrop draggingInfo: NSDraggingInfo, proposedIndexPath proposedDropIndexPath: AutoreleasingUnsafeMutablePointer<NSIndexPath>, dropOperation proposedDropOperation: UnsafeMutablePointer<NSCollectionView.DropOperation>) -> NSDragOperation {
  188. resetCellOpacity()
  189. updateCellOpacity(at: draggingInfo.draggingLocation, opacity: 0.5)
  190. return .move
  191. }
  192. func collectionView(_ collectionView: NSCollectionView, draggingSession session: NSDraggingSession, willBeginAt screenPoint: NSPoint, forItemsAt indexPaths: Set<IndexPath>) {
  193. draggedItemIndexPath = indexPaths.first
  194. }
  195. func collectionView(_ collectionView: NSCollectionView, acceptDrop draggingInfo: NSDraggingInfo, indexPath: IndexPath, dropOperation: NSCollectionView.DropOperation) -> Bool {
  196. let result = false
  197. let toItemIndex = indexPath.item
  198. guard let fromItemIndex = draggedItemIndexPath?.item else {
  199. return result
  200. }
  201. // 确保索引有效
  202. if fromItemIndex < 0 || fromItemIndex >= showDates.count || toItemIndex < 0 || toItemIndex > showDates.count {
  203. return result // 无效索引
  204. }
  205. var indexPaths: Set<IndexPath> = []
  206. if dropOperation == .before {
  207. let num = showDates[fromItemIndex]
  208. showDates.insert(num, at: toItemIndex)
  209. if toItemIndex > fromItemIndex { // 向后移动
  210. showDates.remove(at: fromItemIndex)
  211. } else {
  212. showDates.remove(at: fromItemIndex + 1)
  213. }
  214. for i in min(fromItemIndex, toItemIndex)..<(max(fromItemIndex, toItemIndex)+1) {
  215. indexPaths.insert(IndexPath(item: i, section: 0))
  216. }
  217. showCollectionView.reloadItems(at: indexPaths)
  218. } else {
  219. let fromIndexPath = IndexPath(item: fromItemIndex, section: 0)
  220. indexPaths = [indexPath, fromIndexPath]
  221. showDates.swapAt(fromItemIndex, toItemIndex)
  222. showCollectionView.reloadItems(at: indexPaths)
  223. }
  224. changeIndexPaths = [indexPath]
  225. return true
  226. }
  227. func collectionView(_ collectionView: NSCollectionView, draggingSession session: NSDraggingSession, endedAt screenPoint: NSPoint, dragOperation operation: NSDragOperation) {
  228. for targetIndexPath in changeIndexPaths {
  229. let targetItem = collectionView.item(at: targetIndexPath)
  230. targetItem?.view.shakeAnimation()
  231. }
  232. changeIndexPaths = []
  233. resetCellOpacity()
  234. }
  235. }