// // KMSegmentedControl.swift // PDF Reader Pro // // Created by tangchao on 2023/11/16. // import Cocoa enum KMSegmenteDirection: Int { case vertical = 0 case horizontal = 1 } class KMSegmentedControl: NSControl { private var _segmentCount: UInt8 = 0 var segmentCount: UInt8 { get { return self._segmentCount } set { self._segmentCount = newValue self.setSegmentCount(self.segmentCount, with: 55) } } private var _selectedSegment: UInt8 = 0 var selectedSegment: UInt8 { get { return self._selectedSegment } set { self._selectedSegment = newValue if (self.block != nil) { self.block!(self.selectedSegment) } self.reloadData() } } var isBackgroundHighlighted = false var block: ((_ segmentCount: UInt8) -> Void)? private var _segments: [NSButton] = [] var segments: [NSButton] { get { return self._segments } } private var _contentView: NSView? var contentView: NSView? { get { return self._contentView } } var direction: KMSegmenteDirection = .horizontal { didSet { self.needsLayout = true } } var itemSize: NSSize = NSMakeSize(44, 44) override func updateLayer() { super.updateLayer() if #available(macOS 10.14, *) { // self.selectedSegment = self._selectedSegment } self.reloadData() } // MARK: - Public Methods func setSegmentCount(_ segmentCount: uint8, with width: Float) { self._segmentCount = segmentCount self.itemSize = NSMakeSize(width.cgFloat, width.cgFloat) let height = self.frame.size.height if (self.contentView?.superview != nil) { self.contentView?.removeFromSuperview() } self._contentView = NSView() let x = (self.frame.size.width - (Float(self.segmentCount) * width).cgFloat) / 2.0 let y = (self.frame.size.height-height)/2.0 self._contentView?.frame = NSMakeRect(x, 0, (Float(self.segmentCount)*width).cgFloat, height) self._contentView?.autoresizingMask = [.minXMargin, .maxXMargin, .maxYMargin, .height] self.addSubview(self.contentView!) self._segments.removeAll() for i in 0 ..< self.segmentCount { let button = KMCoverButton() button.wantsLayer = true button.bezelStyle = .regularSquare button.isBordered = false button.imageScaling = .scaleProportionallyDown button.imagePosition = .imageOnly // button.layer?.cornerRadius = 6.0 button.frame = NSMakeRect((Float(i)*width).cgFloat, 0, width.cgFloat, height) button.tag = Int(i) button.target = self button.action = #selector(_buttonAction) self.contentView?.addSubview(button) self._segments.append(button) button.coverAction = { [unowned self] cbtn, action in if self.selectedSegment == cbtn.tag { return } if action == .enter { if KMAppearance.isDarkMode() { cbtn.layer?.backgroundColor = NSColor(hex: "282A2D").cgColor } else { cbtn.layer?.backgroundColor = NSColor(hex: "DFE1E5").cgColor } } else if action == .exit { cbtn.layer?.backgroundColor = .clear } } } } override var isFlipped: Bool { return true } func setImage(_ image: NSImage, for segment: UInt8) { if (segment >= self.segments.count) { return } let button = self.segments[Int(segment)] button.image = image button.alternateImage = image } func setToolTip(_ toolTip: String, for segment: uint8) { if (segment >= self.segments.count) { return } let button = self.segments[Int(segment)] button.toolTip = toolTip } override func layout() { super.layout() let width = NSWidth(self.contentView?.bounds ?? .zero) let height = NSHeight(self.contentView?.bounds ?? .zero) let itemSize = self.itemSize var itemY: CGFloat = 0 for i in 0 ..< self.segments.count { let button = self.segments[i] if self.direction == .horizontal { button.frame = NSMakeRect((CGFloat(i)*itemSize.width), 0, itemSize.width, itemSize.height) } else { itemY = height - CGFloat(i)*itemSize.height - itemSize.height button.frame = NSMakeRect(0, itemY, itemSize.width, itemSize.height) } } } func reloadData() { let block = { self._reloadData() } if Thread.isMainThread { block() } else { Task { @MainActor in block() } } } } // MARK: - Private Methods extension KMSegmentedControl { @objc private func _buttonAction(_ sender: NSButton) { self.selectedSegment = UInt8(sender.tag) } private func _reloadData() { for (i, button) in self.segments.enumerated() { if (self.isBackgroundHighlighted) { if (i == self.selectedSegment) { if (KMAppearance.isDarkMode()) { button.layer?.backgroundColor = NSColor(red: 0.133, green: 0.478, blue: 1, alpha: 0.3).cgColor } else { button.layer?.backgroundColor = NSColor(red: 0.286, green: 0.510, blue: 0.902, alpha: 0.2).cgColor } if (i == 0) { button.image = NSImage(named: KMImageNameUXIconBtnSidebarListPre) } else if (i == 1) { button.image = NSImage(named: KMImageNameUXIconBtnSidebarPagePre) } } else { button.layer?.backgroundColor = .clear if (i == 0) { button.image = NSImage(named: KMImageNameUXIconBtnSidebarListNor) } else if (i == 1) { button.image = NSImage(named: KMImageNameUXIconBtnSidebarPageNor) } } } else { if (i == self.selectedSegment) { if (i == 0) { button.image = NSImage(named: KMImageNameUXIconSidetabbarThumbnailSel) } else if (i == 1) { button.image = NSImage(named: KMImageNameUXIconSidetabbarOutlineSel) } else if (i == 2) { button.image = NSImage(named: KMImageNameUXIconSidetabbarAnnotationSel) } else if (i == 3) { button.image = NSImage(named: KMImageNameUXIconSidetabbarSnapshotSel) } else if (i == 4) { button.image = NSImage(named: KMImageNameUXIconSidetabbarSearchSel) } if (KMAppearance.isDarkMode()) { button.layer?.backgroundColor = NSColor(red: 0.133, green: 0.478, blue: 1.000, alpha: 1).cgColor } else { button.layer?.backgroundColor = NSColor(red: 0.286, green: 0.510, blue: 0.902, alpha: 1).cgColor } } else { if (i == 0) { button.image = NSImage(named: KMImageNameUXIconSidetabbarThumbnailNor) } else if (i == 1) { button.image = NSImage(named: KMImageNameUXIconSidetabbarOutlineNor) } else if (i == 2) { button.image = NSImage(named: KMImageNameUXIconSidetabbarAnnotationNor) } else if (i == 3) { button.image = NSImage(named: KMImageNameUXIconSidetabbarSnapshotNor) } else if (i == 4) { button.image = NSImage(named: KMImageNameUXIconSidetabbarSearchNor) } button.wantsLayer = true if (KMAppearance.isDarkMode()) { button.layer?.backgroundColor = NSColor(red: 0.224, green: 0.235, blue: 0.243, alpha: 1).cgColor } else { button.layer?.backgroundColor = NSColor(red: 0.922, green: 0.925, blue: 0.941, alpha: 1).cgColor } } } } } /* - (NSImage *)image:(NSImage *)image withColor:(NSColor *)color { NSImage *newImage = [image copy]; [newImage lockFocus]; [color set]; NSRectFillUsingOperation(NSMakeRect(0, 0, image.size.width, image.size.height), NSCompositingOperationSourceAtop); [newImage unlockFocus]; return [newImage autorelease]; } */ }