// // KMNQuickToolWindowController.swift // PDF Reader Pro // // Created by 丁林圭 on 2024/10/10. // import Cocoa import KMComponentLibrary //MARK: - KMNQuickToolWindowDelegate protocol KMNQuickToolWindowDelegate: AnyObject { func quickToolWindowControllerUpdate() } //MARK: - KMNQuickToolWindowController class KMNQuickToolWindowController: KMNBaseWindowController, NSCollectionViewDelegate, NSCollectionViewDataSource,NSCollectionViewDelegateFlowLayout { weak open var delegate: KMNQuickToolWindowDelegate? @IBOutlet var viewBackBox: NSBox! @IBOutlet var titleLabel: NSTextField! @IBOutlet var titleBox: NSBox! @IBOutlet var titleSubLabel: NSTextField! @IBOutlet var showBox: NSBox! @IBOutlet var showCollectionView: NSCollectionView! @IBOutlet var cancelButton: ComponentButton! @IBOutlet var applyButton: ComponentButton! @IBOutlet var cancelWidthButton:NSLayoutConstraint! @IBOutlet var applyWidthButton:NSLayoutConstraint! var quickToolsItemMutableArray: [Int] = [] var draggedItemIndexPath: IndexPath? var changeIndexPaths: Set = [] lazy var showDates: [KMNHomeQuickToolMode] = { var fullDatas: [KMNHomeQuickToolMode] = [] for itemRaw in KMNHomeQuickToolManager.defaultManager.fullToolsItemMutableArray { let toolMode = KMNHomeQuickToolMode.toolModeData(type: HomeQuickToolType(rawValue: itemRaw) ?? .Batch) fullDatas.append(toolMode) } return fullDatas }() override func windowDidLoad() { super.windowDidLoad() quickToolsItemMutableArray = KMNHomeQuickToolManager.defaultManager.quickToolsItemMutableArray updateButtonState() showCollectionView.delegate = self showCollectionView.dataSource = self showCollectionView.isSelectable = true //支持拖拽需设置未True showCollectionView.register(KMNQuickToolCollectionViewItem.self, forItemWithIdentifier: NSUserInterfaceItemIdentifier(rawValue: "KMNQuickToolShowCollectionViewItem")) showCollectionView.registerForDraggedTypes([.string]) showCollectionView.setDraggingSourceOperationMask(.every, forLocal: false) showCollectionView.setDraggingSourceOperationMask(.every, forLocal: true) } func reloadData() { showCollectionView.reloadData() } override func initContentView() { titleLabel.font = ComponentLibrary.shared.getFontFromKey("mac/body-m-medium") titleSubLabel.font = ComponentLibrary.shared.getFontFromKey ("mac/body-xs-regular") applyButton.properties = ComponentButtonProperty(type: .primary, size: .s, state: .normal, buttonText: KMLocalizedString("Apply")) applyButton.setTarget(self, action: #selector(applyButtonClicked(_ :))) cancelButton.properties = ComponentButtonProperty(type: .default_tertiary, size: .s, state: .normal, buttonText: KMLocalizedString("Cancel")) cancelButton.setTarget(self, action: #selector(cancelButtonClicked(_ :))) } override func updateUIThemeColor() { window?.contentView?.wantsLayer = true window?.contentView?.layer?.backgroundColor = ComponentLibrary.shared.getComponentColorFromKey("colorBorder/popUp").cgColor titleLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/1") titleBox.fillColor = ComponentLibrary.shared.getComponentColorFromKey("colorFill/3-default") titleBox.borderColor = ComponentLibrary.shared.getComponentColorFromKey("colorBorder/3-default") titleSubLabel.textColor = ComponentLibrary.shared.getComponentColorFromKey("colorText/2") cancelButton.reloadData() applyButton.reloadData() } override func updateUILanguage() { titleSubLabel.stringValue = KMLocalizedString("Select a maximum of 8 tools. You can drag and drop to reorder the tools display.") titleLabel.stringValue = KMLocalizedString("Manage Quick Tools") showCollectionView.reloadData() cancelButton.properties.buttonText = KMLocalizedString("Cancel") applyButton.properties.buttonText = KMLocalizedString("Apply") cancelWidthButton.constant = cancelButton.properties.propertyInfo.viewWidth applyWidthButton.constant = applyButton.properties.propertyInfo.viewWidth } private func updateButtonState() { if self.quickToolsItemMutableArray.count < 1 { if applyButton.properties.isDisabled == false { applyButton.properties.isDisabled = true applyButton.reloadData() } } else { if applyButton.properties.isDisabled == true { applyButton.properties.isDisabled = false applyButton.reloadData() } } } private func updateCellOpacity(at location: NSPoint, opacity: CGFloat) { let pointInCollectionView = showCollectionView.convert(location, from: nil) if let indexPath = showCollectionView.indexPathForItem(at: pointInCollectionView) { if let item = showCollectionView.item(at: indexPath) as? KMNQuickToolCollectionViewItem { item.view.alphaValue = opacity } } } private func resetCellOpacity() { for item in showCollectionView.visibleItems() { item.view.alphaValue = 1.0 } } //MARK: - Action @objc func cancelButtonClicked(_ sender: NSView) { own_closeEndSheet() } @objc func applyButtonClicked(_ sender: NSView) { var seleteDatas:[Int] = [] var fullDatas:[Int] = [] for i in 0 ... showDates.count-1 { let indexPath = NSIndexPath(forItem: i, inSection: 0) if let cell = showCollectionView.item(at: indexPath as IndexPath) as? KMNQuickToolCollectionViewItem { if cell.itemCardView.properties.isSelected == true { seleteDatas.append(cell.quickToolModel.quickToolType.rawValue) } fullDatas.append(cell.quickToolModel.quickToolType.rawValue) } } KMNHomeQuickToolManager.defaultManager.quickToolsItemMutableArray = seleteDatas KMNHomeQuickToolManager.defaultManager.fullToolsItemMutableArray = fullDatas self.delegate?.quickToolWindowControllerUpdate() own_closeEndSheet() } //MARK: - NSCollectionViewDataSource func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int { return showDates.count } func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem { let item: KMNQuickToolCollectionViewItem = collectionView.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "KMNQuickToolShowCollectionViewItem"), for: indexPath) as! KMNQuickToolCollectionViewItem item.quickToolModel = showDates[indexPath.item] item.isNewState = item.quickToolModel.isNewState if(quickToolsItemMutableArray.contains(item.quickToolModel.quickToolType.rawValue)) { item.isShowState = true } else { item.isShowState = false } item.clickCallBack = {[weak self] isSelecton in guard let weakSelf = self else { return } if(isSelecton) { if(weakSelf.quickToolsItemMutableArray.count < 8) { weakSelf.quickToolsItemMutableArray.append(item.quickToolModel.quickToolType.rawValue) } else { item.isShowState = false let contextString = KMLocalizedString("You can select up to 8 tools. Please cancel and select.") let superView = weakSelf.window?.contentView ?? NSView() _ = 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)) } } else { weakSelf.quickToolsItemMutableArray.removeObject(item.quickToolModel.quickToolType.rawValue) } weakSelf.updateButtonState() } return item } // MARK: - NSCollectionViewDelegateFlowLayout func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> NSSize { return CGSize(width: 204.0, height: 56.0) } func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { return 4 } func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { return 4 } public func collectionView(_ collectionView: NSCollectionView, layout collectionViewLayout: NSCollectionViewLayout, insetForSectionAt section: Int) -> NSEdgeInsets { return NSEdgeInsetsMake(0, 8, 0, 0) } //MARK: - NSCollectionViewDelegate func collectionView(_ collectionView: NSCollectionView, canDragItemsAt indexPaths: Set, with event: NSEvent) -> Bool { return true } func collectionView(_ collectionView: NSCollectionView, pasteboardWriterForItemAt indexPath: IndexPath) -> NSPasteboardWriting? { return String(indexPath.item) as NSPasteboardWriting } func collectionView(_ collectionView: NSCollectionView, validateDrop draggingInfo: NSDraggingInfo, proposedIndexPath proposedDropIndexPath: AutoreleasingUnsafeMutablePointer, dropOperation proposedDropOperation: UnsafeMutablePointer) -> NSDragOperation { resetCellOpacity() updateCellOpacity(at: draggingInfo.draggingLocation, opacity: 0.5) return .move } func collectionView(_ collectionView: NSCollectionView, draggingSession session: NSDraggingSession, willBeginAt screenPoint: NSPoint, forItemsAt indexPaths: Set) { draggedItemIndexPath = indexPaths.first } func collectionView(_ collectionView: NSCollectionView, acceptDrop draggingInfo: NSDraggingInfo, indexPath: IndexPath, dropOperation: NSCollectionView.DropOperation) -> Bool { let result = false let toItemIndex = indexPath.item guard let fromItemIndex = draggedItemIndexPath?.item else { return result } // 确保索引有效 if fromItemIndex < 0 || fromItemIndex >= showDates.count || toItemIndex < 0 || toItemIndex > showDates.count { return result // 无效索引 } var indexPaths: Set = [] if dropOperation == .before { let num = showDates[fromItemIndex] showDates.insert(num, at: toItemIndex) if toItemIndex > fromItemIndex { // 向后移动 showDates.remove(at: fromItemIndex) } else { showDates.remove(at: fromItemIndex + 1) } for i in min(fromItemIndex, toItemIndex)..<(max(fromItemIndex, toItemIndex)+1) { indexPaths.insert(IndexPath(item: i, section: 0)) } showCollectionView.reloadItems(at: indexPaths) } else { let fromIndexPath = IndexPath(item: fromItemIndex, section: 0) indexPaths = [indexPath, fromIndexPath] showDates.swapAt(fromItemIndex, toItemIndex) showCollectionView.reloadItems(at: indexPaths) } changeIndexPaths = [indexPath] return true } func collectionView(_ collectionView: NSCollectionView, draggingSession session: NSDraggingSession, endedAt screenPoint: NSPoint, dragOperation operation: NSDragOperation) { for targetIndexPath in changeIndexPaths { let targetItem = collectionView.item(at: targetIndexPath) targetItem?.view.shakeAnimation() } changeIndexPaths = [] resetCellOpacity() } }