diff --git a/Box42.xcodeproj/project.pbxproj b/Box42.xcodeproj/project.pbxproj index c4c677f..6e15b5e 100644 --- a/Box42.xcodeproj/project.pbxproj +++ b/Box42.xcodeproj/project.pbxproj @@ -90,6 +90,8 @@ DE94570C2A9E69EB00B0B768 /* ScriptExcuteButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE94570B2A9E69EB00B0B768 /* ScriptExcuteButton.swift */; }; DE94570F2A9E69F200B0B768 /* ScriptDeleteButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE94570E2A9E69F200B0B768 /* ScriptDeleteButton.swift */; }; DE9457162A9E6D3000B0B768 /* ScriptQuickSlotButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9457112A9E6A0000B0B768 /* ScriptQuickSlotButton.swift */; }; + DE9457192A9EEEF000B0B768 /* ScriptCellManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE9457182A9EEEF000B0B768 /* ScriptCellManager.swift */; }; + DE94571C2A9EFB7800B0B768 /* Associated+NSButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE94571B2A9EFB7800B0B768 /* Associated+NSButton.swift */; }; DE97CA692A9A6364001073DE /* PixelConversion+CGFloat.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA682A9A6364001073DE /* PixelConversion+CGFloat.swift */; }; DE97CA792A9A6F6A001073DE /* QuickSlotHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA782A9A6F6A001073DE /* QuickSlotHeaderView.swift */; }; DE97CA7C2A9A7199001073DE /* QuickSlotGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE97CA7B2A9A7199001073DE /* QuickSlotGroupView.swift */; }; @@ -193,6 +195,8 @@ DE94570B2A9E69EB00B0B768 /* ScriptExcuteButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptExcuteButton.swift; sourceTree = ""; }; DE94570E2A9E69F200B0B768 /* ScriptDeleteButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptDeleteButton.swift; sourceTree = ""; }; DE9457112A9E6A0000B0B768 /* ScriptQuickSlotButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptQuickSlotButton.swift; sourceTree = ""; }; + DE9457182A9EEEF000B0B768 /* ScriptCellManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptCellManager.swift; sourceTree = ""; }; + DE94571B2A9EFB7800B0B768 /* Associated+NSButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Associated+NSButton.swift"; sourceTree = ""; }; DE97CA682A9A6364001073DE /* PixelConversion+CGFloat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PixelConversion+CGFloat.swift"; sourceTree = ""; }; DE97CA6E2A9A6EFC001073DE /* QuickSlotViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotViewModel.swift; sourceTree = ""; }; DE97CA712A9A6F0D001073DE /* QuickSlotButtonModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickSlotButtonModel.swift; sourceTree = ""; }; @@ -566,6 +570,7 @@ children = ( DE7886032A9C71CB00FE21DD /* ScriptsTableView.swift */, DE9456FF2A9E5B0900B0B768 /* ScriptCell.swift */, + DE9457182A9EEEF000B0B768 /* ScriptCellManager.swift */, ); path = Table; sourceTree = ""; @@ -687,6 +692,7 @@ DE24E63A2A8FE93900E29F5D /* NSImage.swift */, DE98E83A2A98DB6000F8744A /* RotateImage+NSImage.swift */, DE97CA682A9A6364001073DE /* PixelConversion+CGFloat.swift */, + DE94571B2A9EFB7800B0B768 /* Associated+NSButton.swift */, ); path = Extensions; sourceTree = ""; @@ -785,6 +791,7 @@ DE4408082A9240300091937A /* BoxFunctionButtonView.swift in Sources */, DE3FF3742A978AB8009C88EF /* WindowMaximizeButton.swift in Sources */, DE3FF3A32A97D2A6009C88EF /* DisplayURLTextfield.swift in Sources */, + DE9457192A9EEEF000B0B768 /* ScriptCellManager.swift in Sources */, DE9457002A9E5B0900B0B768 /* ScriptCell.swift in Sources */, DE7886042A9C71CB00FE21DD /* ScriptsTableView.swift in Sources */, DE97CA872A9A7407001073DE /* QuickSlotButtonModel.swift in Sources */, @@ -798,6 +805,7 @@ DE77BBF02A9E38C6006CC98B /* GetUserProfile.swift in Sources */, DEF749322A85657600D987C8 /* NSScreen.swift in Sources */, DE018BF02A509B2F00FF0AA3 /* MenubarViewController.swift in Sources */, + DE94571C2A9EFB7800B0B768 /* Associated+NSButton.swift in Sources */, DE6332E42A9BB8F800DCFAF6 /* QuickSlotButtonCollectionViewController.swift in Sources */, DE9457062A9E69C100B0B768 /* ScriptNameLabel.swift in Sources */, DE77BA512A82580400713683 /* MenubarViewModel.swift in Sources */, diff --git a/Box42/Extensions/Associated+NSButton.swift b/Box42/Extensions/Associated+NSButton.swift new file mode 100644 index 0000000..f6d610f --- /dev/null +++ b/Box42/Extensions/Associated+NSButton.swift @@ -0,0 +1,21 @@ +// +// Associated+NSButton.swift +// Box42 +// +// Created by Chanhee Kim on 8/30/23. +// + +import AppKit + +private var AssociatedObjectKey: UInt8 = 0 + +extension NSButton { + var associatedString: String? { + get { + return objc_getAssociatedObject(self, &AssociatedObjectKey) as? String + } + set(newValue) { + objc_setAssociatedObject(self, &AssociatedObjectKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } +} diff --git a/Box42/FunctionButton/BoxFunctionViewController.swift b/Box42/FunctionButton/BoxFunctionViewController.swift index 42e3396..ea2f9e0 100644 --- a/Box42/FunctionButton/BoxFunctionViewController.swift +++ b/Box42/FunctionButton/BoxFunctionViewController.swift @@ -28,6 +28,13 @@ class BoxFunctionViewController: NSViewController { } func pin() { + StateManager.shared.togglePin() + + if StateManager.shared.pin { + // image on + } else { + // image off + } print("pin") } diff --git a/Box42/QuickSlot/Controller/QuickSlotScriptsLogicController.swift b/Box42/QuickSlot/Controller/QuickSlotScriptsLogicController.swift index 41bc732..517a789 100644 --- a/Box42/QuickSlot/Controller/QuickSlotScriptsLogicController.swift +++ b/Box42/QuickSlot/Controller/QuickSlotScriptsLogicController.swift @@ -17,30 +17,23 @@ class ScriptsLogicController { @objc func handleButtonTapped(notification: NSNotification) { if let button = notification.object as? NSButton { - let buttonTitle = button.title - print("Button with title \(buttonTitle) was tapped") - - DispatchQueue.global(qos: .background).async { [weak self] in - if buttonTitle == QuickSlotUI.title.clean { - self?.executeCleanScript() - } - } + ExcuteScripts.executeShellScript(path: button.associatedString ?? "") } } - + private func executeCleanScript() { if let scriptPath = Bundle.main.path(forResource: "cleanCache", ofType: "sh") { let task = Process() task.launchPath = "/bin/sh" task.arguments = [scriptPath] - + let outputPipe = Pipe() task.standardOutput = outputPipe task.standardError = outputPipe - + task.launch() task.waitUntilExit() - + let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile() let output = String(data: outputData, encoding: .utf8) ?? "" diff --git a/Box42/QuickSlot/Model/QuickSlotButtonModel.swift b/Box42/QuickSlot/Model/QuickSlotButtonModel.swift index 2929b82..b965db8 100644 --- a/Box42/QuickSlot/Model/QuickSlotButtonModel.swift +++ b/Box42/QuickSlot/Model/QuickSlotButtonModel.swift @@ -11,9 +11,11 @@ import Foundation struct QuickSlotButtonModel { let id: UUID var title: String + var path: String? - init(id: UUID = UUID(), title: String = "Default") { + init(id: UUID = UUID(), title: String = "Default", path: String? = nil) { self.id = id self.title = title + self.path = path } } diff --git a/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.swift b/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.swift index 52b2697..c5d60bc 100644 --- a/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.swift +++ b/Box42/QuickSlot/View/ButtonCollectionView/QuickSlotButtonCollectionViewController.swift @@ -97,6 +97,7 @@ extension QuickSlotButtonCollectionViewController: NSCollectionViewDelegate, NSC btn.layer?.backgroundColor = NSColor.red.cgColor customItem.view.addSubview(btn) btn.frame = CGRect(x: 0, y: 0, width: QuickSlotUI.size.button, height: QuickSlotUI.size.button) + btn.associatedString = buttonModel.path } return item } diff --git a/Box42/Scripts/Model/Scripts.swift b/Box42/Scripts/Model/Scripts.swift index 7671c3d..2b74c13 100644 --- a/Box42/Scripts/Model/Scripts.swift +++ b/Box42/Scripts/Model/Scripts.swift @@ -15,10 +15,12 @@ struct Script: Codable { var id: UUID var name: String var description: String + var path: String - init(name: String, description: String) { + init(name: String, description: String, path: String) { self.id = UUID() self.name = name self.description = description + self.path = path } } diff --git a/Box42/Scripts/View/Table/ScriptCellManager.swift b/Box42/Scripts/View/Table/ScriptCellManager.swift new file mode 100644 index 0000000..b471493 --- /dev/null +++ b/Box42/Scripts/View/Table/ScriptCellManager.swift @@ -0,0 +1,109 @@ +// +// ScriptCellManager.swift +// Box42 +// +// Created by Chanhee Kim on 8/30/23. +// + +import AppKit +import SnapKit + +// MARK: - 다음 버전에 추가 예정 +class ScriptCellManager: NSTableCellView { + var nameLabel: NSTextField = NSTextField() + var descriptionLabel: NSTextField = NSTextField() + var excuteButton: ScriptExcuteButton = ScriptExcuteButton() + var deleteButton: ScriptDeleteButton = ScriptDeleteButton() + var quickSlotButton: ScriptQuickSlotButton = ScriptQuickSlotButton() + + var viewModel: ScriptViewModel? + var script: Script? + + override init(frame frameRect: NSRect) { + super.init(frame: frameRect) + setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setupUI() { + addSubview(nameLabel) + addSubview(descriptionLabel) + addSubview(quickSlotButton) + addSubview(excuteButton) + addSubview(deleteButton) + + nameLabel.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.left.equalToSuperview().offset(16) + make.width.lessThanOrEqualTo(200).priority(.high) // 최대 너비와 우선순위 설정 + } + + deleteButton.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.right.equalToSuperview().offset(-16) + make.width.equalTo(53) + make.height.equalTo(40) + } + + excuteButton.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.right.equalTo(deleteButton.snp.left).offset(-8) + make.width.equalTo(70) + make.height.equalTo(40) + } + + quickSlotButton.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.right.equalTo(excuteButton.snp.left).offset(-8) + make.width.equalTo(53) + make.height.equalTo(40) + } + + descriptionLabel.snp.makeConstraints { make in + make.centerY.equalToSuperview() + make.left.equalTo(nameLabel.snp.right).offset(8) + make.right.lessThanOrEqualTo(quickSlotButton.snp.left).offset(-8) + make.width.greaterThanOrEqualTo(100).priority(.low) // 최소 너비와 낮은 우선순위 설정 + } + } + + + + func configure(with script: Script, viewModel: ScriptViewModel?) { + self.script = script + self.viewModel = viewModel + nameLabel.stringValue = script.name + descriptionLabel.stringValue = script.description + + deleteButton.target = self + deleteButton.action = #selector(deleteButtonClicked) + + excuteButton.target = self + excuteButton.action = #selector(excuteButtonClicked) + + quickSlotButton.target = self + quickSlotButton.action = #selector(quickSlotButtonclicked) + + } + + @objc func deleteButtonClicked() { + if let id = script?.id { + viewModel?.deleteScript(id: id) + } + } + + @objc func excuteButtonClicked() { + if let id = script?.id { + viewModel?.excuteScript(id: id) + } + } + + @objc func quickSlotButtonclicked() { + if let id = script?.id { + viewModel?.quickSlotScript(id: id) + } + } +} diff --git a/Box42/Scripts/View/Table/ScriptsTableView.swift b/Box42/Scripts/View/Table/ScriptsTableView.swift index 44c155c..2d77ef0 100644 --- a/Box42/Scripts/View/Table/ScriptsTableView.swift +++ b/Box42/Scripts/View/Table/ScriptsTableView.swift @@ -30,28 +30,47 @@ class ScriptsTableView: NSTableView { self.delegate = self self.dataSource = self - let column1 = NSTableColumn(identifier: NSUserInterfaceItemIdentifier("Column1")) + let column1 = NSTableColumn(identifier: NSUserInterfaceItemIdentifier("Scripts")) column1.width = 100.0 - column1.title = "Column 1" + column1.title = "Scripts" self.addTableColumn(column1) } } extension ScriptsTableView: NSTableViewDelegate, NSTableViewDataSource { - + func getCellForRow(at row: Int) -> NSView { + guard let viewModel = viewModel else { + return NSView() + } + + if row < viewModel.scripts.count { + return getScriptCell(for: viewModel.scripts[row], viewModel: viewModel) + } else { + // MARK: - 다음 버전에 추가 예정 + return getScriptCellManager() + } + } + + private func getScriptCell(for script: Script, viewModel: ScriptViewModel) -> ScriptCell { + let cell = ScriptCell(frame: .zero) + cell.configure(with: script, viewModel: viewModel) + return cell + } + + private func getScriptCellManager() -> ScriptCellManager { + let scriptCellManger = ScriptCellManager(frame: .zero) + return scriptCellManger + } + func numberOfRows(in tableView: NSTableView) -> Int { - return viewModel?.scripts.count ?? 0 + return viewModel?.scripts.count ?? 0 // + 1 } func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { - let cell = ScriptCell(frame: .zero) // 또는 원하는 frame 값을 설정 - if let script = viewModel?.scripts[row] { - cell.configure(with: script, viewModel: viewModel) - } - return cell // 이 줄을 추가 + getCellForRow(at: row) } func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat { - return 44.0 // 셀 높이를 44로 설정 + return 44.0 } } diff --git a/Box42/Scripts/ViewModel/ScriptsViewModel.swift b/Box42/Scripts/ViewModel/ScriptsViewModel.swift index 75955fd..2d2db23 100644 --- a/Box42/Scripts/ViewModel/ScriptsViewModel.swift +++ b/Box42/Scripts/ViewModel/ScriptsViewModel.swift @@ -13,14 +13,18 @@ class ScriptViewModel: NSObject { override init() { self.scripts = [ - Script(name: "cleanCache", description: "Cleaning cache"), - Script(name: "brewInGoinfre", description: "Brew download in goinfre") + Script(name: "cleanCache", + description: "Cleaning cache", + path: Bundle.main.path(forResource: "cleanCache", ofType: "sh") ?? ""), + Script(name: "brewInGoinfre", + description: "Brew download in goinfre", + path: Bundle.main.path(forResource: "brewInGoinfre", ofType: "sh") ?? "") ] } // Create - func addScript(name: String, description: String) { - let newScript = Script(name: name, description: description) + func addScript(name: String, description: String, path: String) { + let newScript = Script(name: name, description: description, path: path) scripts.append(newScript) } @@ -47,7 +51,7 @@ class ScriptViewModel: NSObject { func quickSlotScript(id: UUID) { if let index = scripts.firstIndex(where: { $0.id == id }) { - let button = QuickSlotButtonModel(id: id, title: scripts[index].name) + let button = QuickSlotButtonModel(id: id, title: scripts[index].name, path: scripts[index].path) QuickSlotViewModel.shared.addButton(button) } }