diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6932ad0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,131 @@ +# Created by .ignore support plugin (hsz.mobi) +### macOS template +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Xcode template +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 + +## Xcode Patch +*.xcodeproj/* +!*.xcodeproj/project.pbxproj +!*.xcodeproj/xcshareddata/ +!*.xcworkspace/contents.xcworkspacedata +/*.gcno + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + diff --git a/.idea/ToggleBluetooth.iml b/.idea/ToggleBluetooth.iml new file mode 100644 index 0000000..74121dc --- /dev/null +++ b/.idea/ToggleBluetooth.iml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..28a804d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..20f0779 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations/ToggleBluetooth.xml b/.idea/runConfigurations/ToggleBluetooth.xml new file mode 100644 index 0000000..26e9874 --- /dev/null +++ b/.idea/runConfigurations/ToggleBluetooth.xml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/xcode.xml b/.idea/xcode.xml new file mode 100644 index 0000000..5646f67 --- /dev/null +++ b/.idea/xcode.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/ToggleBluetooth.xcodeproj/project.pbxproj b/ToggleBluetooth.xcodeproj/project.pbxproj index 8bf7c88..29d4cb2 100644 --- a/ToggleBluetooth.xcodeproj/project.pbxproj +++ b/ToggleBluetooth.xcodeproj/project.pbxproj @@ -7,22 +7,24 @@ objects = { /* Begin PBXBuildFile section */ + AB47595E22AF276F00D859D8 /* ApplicationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB47595D22AF276F00D859D8 /* ApplicationController.swift */; }; AB5ECFFA22AC236500F2052D /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB5ECFF922AC236500F2052D /* AppDelegate.swift */; }; - AB5ECFFC22AC236500F2052D /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AB5ECFFB22AC236500F2052D /* ViewController.swift */; }; AB5ECFFE22AC236600F2052D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AB5ECFFD22AC236600F2052D /* Assets.xcassets */; }; - AB5ED00122AC236600F2052D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AB5ECFFF22AC236600F2052D /* Main.storyboard */; }; + AB8D7F7422AE0ECB00E6E7A1 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = AB8D7F7322AE0ECB00E6E7A1 /* MainMenu.xib */; }; + CA635506539ACBAF6E956479 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = CA635396E88C080E1257019A /* LICENSE */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + AB47595D22AF276F00D859D8 /* ApplicationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationController.swift; sourceTree = ""; }; AB5ECFF622AC236500F2052D /* ToggleBluetooth.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ToggleBluetooth.app; sourceTree = BUILT_PRODUCTS_DIR; }; AB5ECFF922AC236500F2052D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - AB5ECFFB22AC236500F2052D /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; AB5ECFFD22AC236600F2052D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - AB5ED00022AC236600F2052D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; AB5ED00222AC236600F2052D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; AB5ED00322AC236600F2052D /* ToggleBluetooth.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = ToggleBluetooth.entitlements; sourceTree = ""; }; AB5ED00B22AC36C500F2052D /* Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Header.h; sourceTree = ""; }; AB5ED00C22AC401100F2052D /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; + AB8D7F7322AE0ECB00E6E7A1 /* MainMenu.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainMenu.xib; sourceTree = ""; }; + CA635396E88C080E1257019A /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -41,6 +43,7 @@ children = ( AB5ECFF822AC236500F2052D /* ToggleBluetooth */, AB5ECFF722AC236500F2052D /* Products */, + CA635396E88C080E1257019A /* LICENSE */, ); sourceTree = ""; }; @@ -55,11 +58,11 @@ AB5ECFF822AC236500F2052D /* ToggleBluetooth */ = { isa = PBXGroup; children = ( + AB47595D22AF276F00D859D8 /* ApplicationController.swift */, + AB8D7F7322AE0ECB00E6E7A1 /* MainMenu.xib */, AB5ECFF922AC236500F2052D /* AppDelegate.swift */, AB5ED00B22AC36C500F2052D /* Header.h */, - AB5ECFFB22AC236500F2052D /* ViewController.swift */, AB5ECFFD22AC236600F2052D /* Assets.xcassets */, - AB5ECFFF22AC236600F2052D /* Main.storyboard */, AB5ED00222AC236600F2052D /* Info.plist */, AB5ED00C22AC401100F2052D /* README.md */, AB5ED00322AC236600F2052D /* ToggleBluetooth.entitlements */, @@ -130,8 +133,9 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + AB8D7F7422AE0ECB00E6E7A1 /* MainMenu.xib in Resources */, AB5ECFFE22AC236600F2052D /* Assets.xcassets in Resources */, - AB5ED00122AC236600F2052D /* Main.storyboard in Resources */, + CA635506539ACBAF6E956479 /* LICENSE in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -142,24 +146,13 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - AB5ECFFC22AC236500F2052D /* ViewController.swift in Sources */, + AB47595E22AF276F00D859D8 /* ApplicationController.swift in Sources */, AB5ECFFA22AC236500F2052D /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ -/* Begin PBXVariantGroup section */ - AB5ECFFF22AC236600F2052D /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - AB5ED00022AC236600F2052D /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - /* Begin XCBuildConfiguration section */ AB5ED00422AC236600F2052D /* Debug */ = { isa = XCBuildConfiguration; diff --git a/ToggleBluetooth.xcodeproj/xcshareddata/xcschemes/ToggleBluetooth.xcscheme b/ToggleBluetooth.xcodeproj/xcshareddata/xcschemes/ToggleBluetooth.xcscheme new file mode 100644 index 0000000..643409d --- /dev/null +++ b/ToggleBluetooth.xcodeproj/xcshareddata/xcschemes/ToggleBluetooth.xcscheme @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ToggleBluetooth.xcodeproj/xcuserdata/sn1p3r.xcuserdatad/xcschemes/xcschememanagement.plist b/ToggleBluetooth.xcodeproj/xcuserdata/sn1p3r.xcuserdatad/xcschemes/xcschememanagement.plist index 5cec63f..43b4271 100644 --- a/ToggleBluetooth.xcodeproj/xcuserdata/sn1p3r.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/ToggleBluetooth.xcodeproj/xcuserdata/sn1p3r.xcuserdatad/xcschemes/xcschememanagement.plist @@ -10,5 +10,13 @@ 0 + SuppressBuildableAutocreation + + AB5ECFF522AC236500F2052D + + primary + + + diff --git a/ToggleBluetooth/AppDelegate.swift b/ToggleBluetooth/AppDelegate.swift index e58e205..48c93cb 100644 --- a/ToggleBluetooth/AppDelegate.swift +++ b/ToggleBluetooth/AppDelegate.swift @@ -7,62 +7,16 @@ // import Cocoa -import CoreBluetooth -import IOBluetooth @NSApplicationMain class AppDelegate: NSObject, NSApplicationDelegate { - var statusItem: NSStatusItem? - func applicationDidFinishLaunching(_ aNotification: Notification) { // Insert code here to initialize your application - statusItem = NSStatusBar.system.statusItem(withLength: -1) - - guard let button = statusItem?.button else { - print("status bar item failed. try removing some menu bar items") - NSApp.terminate(nil) - return - } - - let buttonImage = NSImage(named: "bluetoothDisabled") - buttonImage?.isTemplate = true - - button.image = buttonImage - button.target = self - button.action = #selector(displayMenu) } func applicationWillTerminate(_ aNotification: Notification) { // Insert code here to tear down your application } - - @IBOutlet weak var appMenu: NSMenu! - @objc func displayMenu() { - guard let button = statusItem?.button else {return} - - let x = button.frame.origin.x - let y = button.frame.origin.y - 5 - let location = button.superview!.convert(NSMakePoint(x, y), to: nil) - let w = button.window! - let event = NSEvent.mouseEvent(with: .leftMouseUp, - location: location, - modifierFlags: NSEvent.ModifierFlags(rawValue: 0), - timestamp: 0, - windowNumber: w.windowNumber, - context: w.graphicsContext, - eventNumber: 0, - clickCount: 1, - pressure: 0)! - - NSMenu.popUpContextMenu(appMenu, with: event, for: button) - } - - @IBAction func toggleBluetooth(_ sender: Any) { - print("toggle clicked") - IOBluetoothPreferenceSetControllerPowerState(0) - IOBluetoothPreferenceSetControllerPowerState(1) - } } - diff --git a/ToggleBluetooth/ApplicationController.swift b/ToggleBluetooth/ApplicationController.swift new file mode 100644 index 0000000..b3a03ed --- /dev/null +++ b/ToggleBluetooth/ApplicationController.swift @@ -0,0 +1,69 @@ +// +// ApplicationController.swift +// ToggleBluetooth +// +// Created by Noah Kovacs on 6/10/19. +// Copyright © 2019 Noah Kovacs. All rights reserved. +// + +import Foundation +import Cocoa +import IOBluetooth + +final class ApplicationController: NSObject { + + @IBOutlet weak var applicationMenu: NSMenu! + + private var statusItem: NSStatusItem? + + override init() { + super.init() + + self.buildMenu() + } + + func buildMenu() { + statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) + + guard let button = statusItem?.button else { + print("status bar item failed. try removing some menu bar items") + NSApp.terminate(nil) + return + } + + let buttonImage = NSImage(named: "bluetoothDisabled") + buttonImage?.isTemplate = true + + button.image = buttonImage + button.target = self + button.action = #selector(displayMenu) + } + + @IBAction func toggleBluetooth(_ sender: Any) { + IOBluetoothPreferenceSetControllerPowerState(0) + sleep(5) + IOBluetoothPreferenceSetControllerPowerState(1) + } + + @objc func displayMenu() { + guard let button = statusItem?.button else {return} + + let x = button.frame.origin.x + let y = button.frame.origin.y - 5 + let location = button.superview!.convert(NSMakePoint(x, y), to: nil) + let w = button.window! + let event = NSEvent.mouseEvent(with: .leftMouseUp, + location: location, + modifierFlags: NSEvent.ModifierFlags(rawValue: 0), + timestamp: 0, + windowNumber: w.windowNumber, + context: w.graphicsContext, + eventNumber: 0, + clickCount: 1, + pressure: 0)! + +// NSMenu.popUpContextMenu(applicationMenu, with: event, for: button) + statusItem?.menu = applicationMenu + } + +} diff --git a/ToggleBluetooth/Base.lproj/Main.storyboard b/ToggleBluetooth/Base.lproj/Main.storyboard deleted file mode 100644 index 2bf95db..0000000 --- a/ToggleBluetooth/Base.lproj/Main.storyboard +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ToggleBluetooth/Info.plist b/ToggleBluetooth/Info.plist index 330d710..7bef052 100644 --- a/ToggleBluetooth/Info.plist +++ b/ToggleBluetooth/Info.plist @@ -26,8 +26,8 @@ NSHumanReadableCopyright Copyright © 2019 Noah Kovacs. All rights reserved. Icon Credits go to https://www.flaticon.com/authors/smashicons and https://www.flaticon.com/authors/roundicons and https://www.flaticon.com/authors/google - NSMainStoryboardFile - Main + NSMainNibFile + MainMenu NSPrincipalClass NSApplication diff --git a/ToggleBluetooth/MainMenu.xib b/ToggleBluetooth/MainMenu.xib new file mode 100644 index 0000000..b0be183 --- /dev/null +++ b/ToggleBluetooth/MainMenu.xib @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ToggleBluetooth/ViewController.swift b/ToggleBluetooth/ViewController.swift deleted file mode 100644 index 9b4caca..0000000 --- a/ToggleBluetooth/ViewController.swift +++ /dev/null @@ -1,27 +0,0 @@ -// -// ViewController.swift -// ToggleBluetooth -// -// Created by Noah Kovacs on 6/8/19. -// Copyright © 2019 Noah Kovacs. All rights reserved. -// - -import Cocoa - -class ViewController: NSViewController { - - override func viewDidLoad() { - super.viewDidLoad() - - // Do any additional setup after loading the view. - } - - override var representedObject: Any? { - didSet { - // Update the view, if already loaded. - } - } - - -} -