mirror of
https://github.com/Toxblh/MTMR.git
synced 2026-10-31 10:28:36 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cd75be6c26 | ||
|
|
7646c6e89d | ||
|
|
9c970aff63 | ||
|
|
49d7333d5e | ||
|
|
cd69bc341c | ||
|
|
453895f395 | ||
|
|
12796d6387 | ||
|
|
f65e72faed | ||
|
|
df535b2893 | ||
|
|
574ca0fb84 | ||
|
|
4a03ba79ec | ||
|
|
907b79965d | ||
|
|
fbec803d47 | ||
|
|
3f9574245a | ||
|
|
2bf6b90b04 | ||
|
|
9d596c6adc | ||
|
|
175e9edb8c | ||
|
|
8e58bb179a | ||
|
|
d37d9607d3 | ||
|
|
6b553c4d0d | ||
|
|
788927edb3 | ||
|
|
9013779f71 | ||
|
|
a85507c544 | ||
|
|
59aa113995 | ||
|
|
9c5a19925b | ||
|
|
2aa602d77d | ||
|
|
a1b3f13902 | ||
|
|
60384561d2 | ||
|
|
77938340d6 | ||
|
|
93d2f496d0 | ||
|
|
0808f0617a | ||
|
|
966a924183 | ||
|
|
a648402d04 | ||
|
|
207af6468e | ||
|
|
6609a7c806 | ||
|
|
479190d12b | ||
|
|
5ed1790601 | ||
|
|
b95f5af95f | ||
|
|
c76027ca9d | ||
|
|
55dc551516 | ||
|
|
cf5d8bf546 | ||
|
|
8031108fc9 | ||
|
|
d1a577868b | ||
|
|
5f02bb2962 | ||
|
|
cc1332dd02 | ||
|
|
a0dbfca828 | ||
|
|
76bdf12745 | ||
|
|
e1268d0d65 | ||
|
|
9c1e5f5032 | ||
|
|
88cde9256a | ||
|
|
d974f92e3d | ||
|
|
4b8ef1cd96 | ||
|
|
e65c57dbaa | ||
|
|
babc8451e0 | ||
|
|
7698ea1c8e | ||
|
|
aa95d1a1bd | ||
|
|
3fe6c22068 | ||
|
|
5ab19ee27b | ||
|
|
ae4b0aa870 | ||
|
|
1e2043ebda | ||
|
|
409b8d8b46 | ||
|
|
8bccbf3834 | ||
|
|
1b5ae00493 | ||
|
|
22c315d631 |
@@ -36,7 +36,7 @@ class AppleScriptTouchBarItem: CustomButtonTouchBarItem {
|
||||
|
||||
func refreshAndSchedule() {
|
||||
#if DEBUG
|
||||
print("refresh happened")
|
||||
print("refresh happened (interval \(self.interval)), self \(self.identifier.rawValue))")
|
||||
#endif
|
||||
let scriptResult = self.execute()
|
||||
DispatchQueue.main.async {
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
import Cocoa
|
||||
|
||||
class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegate {
|
||||
private let tapClosure: () -> ()?
|
||||
private let longTapClosure: () -> ()?
|
||||
private let tapClosure: (() -> ())?
|
||||
private let longTapClosure: (() -> ())?
|
||||
private(set) var button: NSButton!
|
||||
|
||||
private var singleClick: NSClickGestureRecognizer!
|
||||
@@ -21,8 +21,10 @@ class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegat
|
||||
self.longTapClosure = callbackLong
|
||||
|
||||
super.init(identifier: identifier)
|
||||
button = NSButton(title: title, target: self, action: nil)
|
||||
button.bezelColor = bezelColor
|
||||
button = NSButton(title: title, target: nil, action: nil)
|
||||
button.cell = CustomButtonCell()
|
||||
button.isBordered = true
|
||||
button.bezelStyle = .rounded
|
||||
button.title = title
|
||||
self.view = button
|
||||
|
||||
@@ -55,7 +57,7 @@ class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegat
|
||||
switch gr.state {
|
||||
case .ended:
|
||||
hf.tap(strong: 2)
|
||||
self.tapClosure()
|
||||
self.tapClosure?()
|
||||
break
|
||||
default:
|
||||
break
|
||||
@@ -66,12 +68,12 @@ class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegat
|
||||
let hf: HapticFeedback = HapticFeedback()
|
||||
switch gr.state {
|
||||
case .began:
|
||||
if self.longTapClosure != nil {
|
||||
if let closure = self.longTapClosure {
|
||||
hf.tap(strong: 2)
|
||||
self.tapClosure()
|
||||
} else {
|
||||
closure()
|
||||
} else if let closure = self.tapClosure {
|
||||
hf.tap(strong: 6)
|
||||
self.longTapClosure()
|
||||
closure()
|
||||
print("long click")
|
||||
}
|
||||
break
|
||||
@@ -82,3 +84,38 @@ class CustomButtonTouchBarItem: NSCustomTouchBarItem, NSGestureRecognizerDelegat
|
||||
}
|
||||
}
|
||||
|
||||
class CustomButtonCell: NSButtonCell {
|
||||
|
||||
init() {
|
||||
super.init(textCell: "")
|
||||
}
|
||||
|
||||
override func highlight(_ flag: Bool, withFrame cellFrame: NSRect, in controlView: NSView) {
|
||||
super.highlight(flag, withFrame: cellFrame, in: controlView)
|
||||
if !self.isBordered {
|
||||
self.setTitle(self.title, withColor: flag ? .lightGray : .white)
|
||||
}
|
||||
}
|
||||
|
||||
required init(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
override var title: String! {
|
||||
get {
|
||||
return self.attributedTitle.string
|
||||
}
|
||||
|
||||
set (newTitle) {
|
||||
setTitle(newTitle, withColor: .white)
|
||||
}
|
||||
}
|
||||
|
||||
func setTitle(_ title: String, withColor color: NSColor) {
|
||||
let attrTitle = NSMutableAttributedString(string: title as String, attributes: [.foregroundColor: color, .font: NSFont.systemFont(ofSize: 15, weight: .regular), .baselineOffset: 1])
|
||||
attrTitle.setAlignment(.center, range: NSRange(location: 0, length: title.count))
|
||||
|
||||
self.attributedTitle = attrTitle
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,19 +49,19 @@ class CustomSliderCell: NSSliderCell {
|
||||
override func drawBar(inside aRect: NSRect, flipped: Bool) {
|
||||
_barRect = aRect
|
||||
|
||||
var rect = aRect
|
||||
rect.size.height = CGFloat(4)
|
||||
let barRadius = CGFloat(2)
|
||||
let value = CGFloat((self.doubleValue - self.minValue) / (self.maxValue - self.minValue))
|
||||
let finalWidth = CGFloat(value * (self.controlView!.frame.size.width - 12))
|
||||
|
||||
var bgRect = aRect
|
||||
bgRect.size.height = CGFloat(4)
|
||||
|
||||
var leftRect = rect
|
||||
leftRect.size.width = finalWidth
|
||||
let bg = NSBezierPath(roundedRect: rect, xRadius: barRadius, yRadius: barRadius)
|
||||
let bg = NSBezierPath(roundedRect: bgRect, xRadius: barRadius, yRadius: barRadius)
|
||||
NSColor.lightGray.setFill()
|
||||
bg.fill()
|
||||
|
||||
let active = NSBezierPath(roundedRect: leftRect, xRadius: barRadius, yRadius: barRadius)
|
||||
var activeRect = bgRect
|
||||
|
||||
activeRect.size.width = CGFloat((Double(bgRect.size.width) / (self.maxValue - self.minValue)) * self.doubleValue)
|
||||
let active = NSBezierPath(roundedRect: activeRect, xRadius: barRadius, yRadius: barRadius)
|
||||
NSColor.darkGray.setFill()
|
||||
active.fill()
|
||||
}
|
||||
|
||||
+6
-2
@@ -17,7 +17,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>0.12</string>
|
||||
<string>0.14</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
@@ -26,8 +26,12 @@
|
||||
<true/>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2018 Anton Palgunov. All rights reserved.</string>
|
||||
<key>NSLocationAlwaysUsageDescription</key>
|
||||
<string>Weather widget need your location for correct work</string>
|
||||
<key>NSLocationUsageDescription</key>
|
||||
<string>...</string>
|
||||
<string>Weather widget need your location for correct work</string>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>Weather widget need your location for correct work</string>
|
||||
<key>NSMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
|
||||
+11
-3
@@ -3,9 +3,7 @@ import AppKit
|
||||
|
||||
extension Data {
|
||||
func barItemDefinitions() -> [BarItemDefinition]? {
|
||||
// TODO: Need improve a speed, very low loading JSON with comments ~20sec
|
||||
// return try? JSONDecoder().decode([BarItemDefinition].self, from: self.utf8string!.stripComments().data(using: .utf8)!
|
||||
return try? JSONDecoder().decode([BarItemDefinition].self, from: self)
|
||||
return try? JSONDecoder().decode([BarItemDefinition].self, from: self.utf8string!.stripComments().data(using: .utf8)!)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,6 +388,8 @@ enum GeneralParameter {
|
||||
case width(_: CGFloat)
|
||||
case image(source: SourceProtocol)
|
||||
case align(_: Align)
|
||||
case bordered(_: Bool)
|
||||
case background(_:NSColor)
|
||||
}
|
||||
|
||||
struct GeneralParameters: Decodable {
|
||||
@@ -399,6 +399,8 @@ struct GeneralParameters: Decodable {
|
||||
case width
|
||||
case image
|
||||
case align
|
||||
case bordered
|
||||
case background
|
||||
}
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
@@ -411,6 +413,12 @@ struct GeneralParameters: Decodable {
|
||||
}
|
||||
let align = try container.decodeIfPresent(Align.self, forKey: .align) ?? .center
|
||||
result[.align] = .align(align)
|
||||
if let borderedFlag = try container.decodeIfPresent(Bool.self, forKey: .bordered) {
|
||||
result[.bordered] = .bordered(borderedFlag)
|
||||
}
|
||||
if let backgroundColor = try container.decodeIfPresent(String.self, forKey: .background)?.hexColor {
|
||||
result[.background] = .background(backgroundColor)
|
||||
}
|
||||
parameters = result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ class ScrollViewItem: NSCustomTouchBarItem {
|
||||
stackView.orientation = .horizontal
|
||||
let scrollView = NSScrollView(frame: CGRect(origin: .zero, size: stackView.fittingSize))
|
||||
scrollView.documentView = stackView
|
||||
// scrollView.documentView?.bounds.origin = CGPoint(x: 0.0, y: -2.5)
|
||||
self.view = scrollView
|
||||
}
|
||||
|
||||
|
||||
+19
-64
@@ -12,73 +12,28 @@ extension String {
|
||||
func trim() -> String {
|
||||
return self.trimmingCharacters(in: NSCharacterSet.whitespaces)
|
||||
}
|
||||
|
||||
func substring(from: Int, to: Int) -> String {
|
||||
let start = index(startIndex, offsetBy: from)
|
||||
let end = index(start, offsetBy: to - from)
|
||||
return String(self[start ..< end])
|
||||
}
|
||||
|
||||
func substring(range: NSRange) -> String {
|
||||
return substring(from: range.lowerBound, to: range.upperBound)
|
||||
}
|
||||
|
||||
func indexDistance(of character: Character) -> Int? {
|
||||
guard let index = index(of: character) else { return nil }
|
||||
return distance(from: startIndex, to: index)
|
||||
}
|
||||
|
||||
func stripComments() -> String {
|
||||
let str = self
|
||||
let singleComment = 1;
|
||||
let multiComment = 2;
|
||||
var insideString = false
|
||||
var insideComment = 0
|
||||
var offset = 0
|
||||
var ret = ""
|
||||
|
||||
for var i in 0..<str.count - 1 {
|
||||
let currentChar = Array(str)[i]
|
||||
let nextChar = Array(str)[i+1]
|
||||
|
||||
if (insideComment == 0 && currentChar == "\"") {
|
||||
let escaped = Array(str)[i - 1] == "\\" && Array(str)[i - 2] != "\\"
|
||||
if (!escaped) {
|
||||
insideString = !insideString
|
||||
}
|
||||
}
|
||||
|
||||
if (insideString) {
|
||||
let jumpStr = String(str[str.index(startIndex, offsetBy: i)..<str.endIndex])
|
||||
i += (jumpStr.indexDistance(of: "\""))!
|
||||
continue
|
||||
}
|
||||
|
||||
if (insideComment == 0 && String(currentChar) + String(nextChar) == "//") {
|
||||
ret += str.substring(from: offset, to: i)
|
||||
offset = i
|
||||
insideComment = singleComment
|
||||
i += 1
|
||||
} else if (insideComment == singleComment && String(currentChar) + String(nextChar) == "\r\n") {
|
||||
i += 1
|
||||
insideComment = 0
|
||||
offset = i
|
||||
} else if (insideComment == singleComment && currentChar == "\n") {
|
||||
insideComment = 0
|
||||
offset = i
|
||||
} else if (insideComment == 0 && String(currentChar) + String(nextChar) == "/*") {
|
||||
ret += str.substring(from: offset, to: i)
|
||||
offset = i
|
||||
insideComment = multiComment
|
||||
i += 1
|
||||
} else if (insideComment == multiComment && String(currentChar) + String(nextChar) == "*/") {
|
||||
i += 1
|
||||
insideComment = 0
|
||||
offset = i + 1
|
||||
}
|
||||
// ((\s|,)\/\*[\s\S]*?\*\/)|(( |, ")\/\/.*)
|
||||
return self.replacingOccurrences(of: "((\\s|,)\\/\\*[\\s\\S]*?\\*\\/)|(( |, \\\")\\/\\/.*)", with: "", options: .regularExpression)
|
||||
}
|
||||
|
||||
var hexColor: NSColor? {
|
||||
let hex = trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
|
||||
var int = UInt32()
|
||||
Scanner(string: hex).scanHexInt32(&int)
|
||||
let a, r, g, b: UInt32
|
||||
switch hex.count {
|
||||
case 3: // RGB (12-bit)
|
||||
(r, g, b, a) = ((int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17, 255)
|
||||
case 6: // RGB (24-bit)
|
||||
(r, g, b, a) = (int >> 16, int >> 8 & 0xFF, int & 0xFF, 255)
|
||||
case 8: // ARGB (32-bit)
|
||||
(r, g, b, a) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
return ret + str.substring(from: offset, to: str.count)
|
||||
return NSColor(red: CGFloat(r) / 255, green: CGFloat(g) / 255, blue: CGFloat(b) / 255, alpha: CGFloat(a) / 255)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
||||
|
||||
static let shared = TouchBarController()
|
||||
|
||||
let touchBar = NSTouchBar()
|
||||
var touchBar: NSTouchBar!
|
||||
|
||||
var itemDefinitions: [NSTouchBarItem.Identifier: BarItemDefinition] = [:]
|
||||
var items: [NSTouchBarItem.Identifier: NSTouchBarItem] = [:]
|
||||
@@ -69,6 +69,10 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
||||
}
|
||||
|
||||
func createAndUpdatePreset(jsonItems: [BarItemDefinition]? = nil) {
|
||||
if let oldBar = self.touchBar {
|
||||
NSTouchBar.minimizeSystemModalFunctionBar(oldBar)
|
||||
}
|
||||
self.touchBar = NSTouchBar()
|
||||
var jsonItems = jsonItems
|
||||
self.itemDefinitions = [:]
|
||||
self.items = [:]
|
||||
@@ -110,8 +114,11 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
||||
}
|
||||
|
||||
func loadItemDefinitions(jsonItems: [BarItemDefinition]) {
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.dateFormat = "HH-mm-ss"
|
||||
let time = dateFormatter.string(from: Date())
|
||||
for item in jsonItems {
|
||||
let identifierString = item.type.identifierBase.appending(UUID().uuidString)
|
||||
let identifierString = item.type.identifierBase.appending(time + "--" + UUID().uuidString)
|
||||
let identifier = NSTouchBarItem.Identifier(identifierString)
|
||||
itemDefinitions[identifier] = item
|
||||
if item.align == .left {
|
||||
@@ -204,12 +211,31 @@ class TouchBarController: NSObject, NSTouchBarDelegate {
|
||||
if case .width(let value)? = item.additionalParameters[.width], let widthBarItem = barItem as? CanSetWidth {
|
||||
widthBarItem.setWidth(value: value)
|
||||
}
|
||||
if case .bordered(let bordered)? = item.additionalParameters[.bordered], let item = barItem as? CustomButtonTouchBarItem {
|
||||
item.button.isBordered = bordered
|
||||
item.button.bezelStyle = bordered ? .rounded : .inline
|
||||
}
|
||||
if case .background(let color)? = item.additionalParameters[.background], let item = barItem as? CustomButtonTouchBarItem {
|
||||
if item.button.cell?.isBordered == false {
|
||||
let newCell = NSButtonCell()
|
||||
newCell.title = item.button.title
|
||||
item.button.cell = newCell
|
||||
item.button.cell?.isBordered = true
|
||||
}
|
||||
item.button.bezelColor = color
|
||||
(item.button.cell as? NSButtonCell)?.backgroundColor = color
|
||||
}
|
||||
if case .image(let source)? = item.additionalParameters[.image], let item = barItem as? CustomButtonTouchBarItem {
|
||||
let button = item.button!
|
||||
button.image = source.image
|
||||
button.imageScaling = .scaleProportionallyDown
|
||||
button.imagePosition = .imageLeading
|
||||
|
||||
if (button.title == "") {
|
||||
button.imagePosition = .imageOnly
|
||||
}
|
||||
|
||||
button.imageHugsTitle = true
|
||||
button.bezelColor = .clear
|
||||
button.image = source.image
|
||||
}
|
||||
return barItem
|
||||
}
|
||||
|
||||
@@ -12,6 +12,12 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub
|
||||
private var scrubber: NSScrubber!
|
||||
|
||||
private let hf: HapticFeedback = HapticFeedback()
|
||||
|
||||
private var timer: Timer!
|
||||
private var ticks: Int = 0
|
||||
private let minTicks: Int = 5
|
||||
private let maxTicks: Int = 20
|
||||
private var lastSelected: Int = 0
|
||||
|
||||
private var persistentAppIdentifiers: [String] = []
|
||||
private var runningAppsIdentifiers: [String] = []
|
||||
@@ -25,8 +31,6 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub
|
||||
|
||||
private var applications: [DockItem] = []
|
||||
|
||||
private var timeAtPress: NSDate?
|
||||
|
||||
override init(identifier: NSTouchBarItem.Identifier) {
|
||||
super.init(identifier: identifier)
|
||||
|
||||
@@ -35,7 +39,7 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub
|
||||
scrubber.dataSource = self
|
||||
scrubber.mode = .free // .fixed
|
||||
let layout = NSScrubberFlowLayout();
|
||||
layout.itemSize = NSSize(width: 44, height: 30)
|
||||
layout.itemSize = NSSize(width: 36, height: 32)
|
||||
layout.itemSpacing = 2
|
||||
scrubber.scrubberLayout = layout
|
||||
scrubber.selectionBackgroundStyle = .roundedBackground
|
||||
@@ -94,6 +98,7 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub
|
||||
|
||||
if let icon = app.icon {
|
||||
item.image = icon
|
||||
item.image.size = NSSize(width: 26, height: 26)
|
||||
}
|
||||
|
||||
item.removeFromSuperview()
|
||||
@@ -105,59 +110,82 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub
|
||||
} else {
|
||||
dotView.layer?.backgroundColor = NSColor.black.cgColor
|
||||
}
|
||||
dotView.layer?.cornerRadius = 2
|
||||
dotView.setFrameOrigin(NSPoint(x: 20, y: 0))
|
||||
dotView.frame.size = NSSize(width: 4, height: 4)
|
||||
dotView.layer?.cornerRadius = 1.5
|
||||
dotView.setFrameOrigin(NSPoint(x: 17, y: 1))
|
||||
dotView.frame.size = NSSize(width: 3, height: 3)
|
||||
item.addSubview(dotView)
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
public func didBeginInteracting(with scrubber: NSScrubber) {
|
||||
timeAtPress = NSDate()
|
||||
stopTimer()
|
||||
self.ticks = 0
|
||||
self.timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(checkTimer), userInfo: nil, repeats: true)
|
||||
}
|
||||
|
||||
@objc private func checkTimer() {
|
||||
self.ticks += 1
|
||||
|
||||
if (self.ticks == minTicks) {
|
||||
hf.tap(strong: 2)
|
||||
}
|
||||
|
||||
if (self.ticks > maxTicks) {
|
||||
stopTimer()
|
||||
hf.tap(strong: 6)
|
||||
}
|
||||
}
|
||||
|
||||
private func stopTimer() {
|
||||
self.timer?.invalidate()
|
||||
self.timer = nil
|
||||
self.lastSelected = 0
|
||||
}
|
||||
|
||||
public func didCancelInteracting(with scrubber: NSScrubber) {
|
||||
timeAtPress = nil
|
||||
stopTimer()
|
||||
}
|
||||
|
||||
|
||||
public func didFinishInteracting(with scrubber: NSScrubber) {
|
||||
let timePressed = NSDate().timeIntervalSince(timeAtPress! as Date)
|
||||
if (timePressed > 0.5 && scrubber.selectedIndex > 0) {
|
||||
self.longPress(with: scrubber)
|
||||
stopTimer()
|
||||
|
||||
if (ticks == 0) {
|
||||
return
|
||||
}
|
||||
|
||||
hf.tap(strong: 6)
|
||||
if (self.ticks >= minTicks && scrubber.selectedIndex > 0) {
|
||||
self.longPress(selected: scrubber.selectedIndex)
|
||||
return
|
||||
}
|
||||
|
||||
let bundleIdentifier = applications[scrubber.selectedIndex].bundleIdentifier
|
||||
if bundleIdentifier!.contains("file://") {
|
||||
NSWorkspace.shared.openFile(bundleIdentifier!.replacingOccurrences(of: "file://", with: ""))
|
||||
} else {
|
||||
NSWorkspace.shared.launchApplication(withBundleIdentifier: bundleIdentifier!, options: [.default], additionalEventParamDescriptor: nil, launchIdentifier: nil)
|
||||
hf.tap(strong: 6)
|
||||
}
|
||||
updateRunningApplication()
|
||||
|
||||
// NB: if you can't open app which on another space, try to check mark
|
||||
// "When switching to an application, switch to a Space with open windows for the application"
|
||||
// in Mission control settings
|
||||
}
|
||||
|
||||
private func longPress(with scrubber: NSScrubber) {
|
||||
let timePressed = NSDate().timeIntervalSince(timeAtPress! as Date)
|
||||
private func longPress(selected: Int) {
|
||||
let bundleIdentifier = applications[selected].bundleIdentifier
|
||||
|
||||
let bundleIdentifier = applications[scrubber.selectedIndex].bundleIdentifier
|
||||
|
||||
if (timePressed > 2.0) {
|
||||
if let processIdentifier = applications[scrubber.selectedIndex].pid {
|
||||
hf.tap(strong: 6)
|
||||
NSRunningApplication(processIdentifier: processIdentifier)?.forceTerminate()
|
||||
if (self.ticks > maxTicks) {
|
||||
if let processIdentifier = applications[selected].pid {
|
||||
if !(NSRunningApplication(processIdentifier: processIdentifier)?.terminate())! {
|
||||
NSRunningApplication(processIdentifier: processIdentifier)?.forceTerminate()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
hf.tap(strong: 6)
|
||||
if let index = self.persistentAppIdentifiers.index(of: bundleIdentifier!) {
|
||||
self.persistentAppIdentifiers.remove(at: index)
|
||||
updateRunningApplication()
|
||||
} else {
|
||||
self.persistentAppIdentifiers.append(bundleIdentifier!)
|
||||
}
|
||||
@@ -165,6 +193,8 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub
|
||||
UserDefaults.standard.set(self.persistentAppIdentifiers, forKey: "com.toxblh.mtmr.dock.persistent")
|
||||
UserDefaults.standard.synchronize()
|
||||
}
|
||||
self.ticks = 0
|
||||
updateRunningApplication()
|
||||
}
|
||||
|
||||
private func launchedApplications() -> [DockItem] {
|
||||
@@ -201,7 +231,7 @@ class AppScrubberTouchBarItem: NSCustomTouchBarItem, NSScrubberDelegate, NSScrub
|
||||
public func getDockPersistentAppsList() -> [DockItem] {
|
||||
var returnable: [DockItem] = []
|
||||
|
||||
for (index, bundleIdentifier) in persistentAppIdentifiers.enumerated() {
|
||||
for bundleIdentifier in persistentAppIdentifiers {
|
||||
if !self.runningAppsIdentifiers.contains(bundleIdentifier) {
|
||||
let dockItem = DockItem(bundleIdentifier: bundleIdentifier, icon: getIcon(forBundleIdentifier: bundleIdentifier))
|
||||
returnable.append(dockItem)
|
||||
|
||||
@@ -35,13 +35,12 @@ class BatteryInfo: NSObject {
|
||||
var ACPower: String = ""
|
||||
var timeRemaining: String = ""
|
||||
|
||||
var button: NSButton?
|
||||
var button: NSButton
|
||||
var loop:CFRunLoopSource?
|
||||
|
||||
init(button: NSButton) {
|
||||
super.init()
|
||||
|
||||
self.button = button
|
||||
super.init()
|
||||
self.start()
|
||||
}
|
||||
|
||||
@@ -108,13 +107,11 @@ class BatteryInfo: NSObject {
|
||||
|
||||
func getFormattedTime(time: Int) -> String {
|
||||
if (time > 0) {
|
||||
let timeFormatted = NSString(format: " (%d:%02d)", time / 60, time % 60) as String
|
||||
let timeFormatted = NSString(format: " %d:%02d", time / 60, time % 60) as String
|
||||
return timeFormatted
|
||||
} else if (time == 0) {
|
||||
return ""
|
||||
}
|
||||
|
||||
return " (?)"
|
||||
return ""
|
||||
}
|
||||
|
||||
public func updateInfo() {
|
||||
@@ -122,14 +119,27 @@ class BatteryInfo: NSObject {
|
||||
self.getPSInfo()
|
||||
|
||||
if ACPower == "AC Power" {
|
||||
title += "⚡️"
|
||||
if current < 100 {
|
||||
title += "⚡️"
|
||||
}
|
||||
timeRemaining = getFormattedTime(time: timeToFull)
|
||||
} else {
|
||||
timeRemaining = getFormattedTime(time: timeToEmpty)
|
||||
}
|
||||
|
||||
title += String(current) + "%" + timeRemaining
|
||||
button?.title = title
|
||||
title += String(current) + "%"
|
||||
|
||||
var color = NSColor.white
|
||||
if current <= 10 && ACPower != "AC Power" {
|
||||
color = NSColor.red
|
||||
}
|
||||
|
||||
let regularFont = button.attributedTitle.attribute(.font, at: 0, effectiveRange: nil) as? NSFont ?? NSFont.systemFont(ofSize: 15)
|
||||
let newTitle = NSMutableAttributedString(string: title as String, attributes: [.foregroundColor: color, .font: regularFont, .baselineOffset: 1])
|
||||
let newTitleSecond = NSMutableAttributedString(string: timeRemaining as String, attributes: [NSAttributedStringKey.foregroundColor: color, NSAttributedStringKey.font: NSFont.systemFont(ofSize: 8, weight: .regular), NSAttributedStringKey.baselineOffset: 7])
|
||||
newTitle.append(newTitleSecond)
|
||||
newTitle.setAlignment(.center, range: NSRange(location: 0, length: title.count))
|
||||
button.attributedTitle = newTitle
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import Cocoa
|
||||
import CoreLocation
|
||||
|
||||
class CurrencyBarItem: CustomButtonTouchBarItem {
|
||||
private let activity = NSBackgroundActivityScheduler(identifier: "com.toxblh.mtmr.currency.updatecheck")
|
||||
private let activity: NSBackgroundActivityScheduler
|
||||
private var prefix: String
|
||||
private var from: String
|
||||
private var to: String
|
||||
@@ -37,6 +37,7 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
|
||||
]
|
||||
|
||||
init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, from: String, to: String, onTap: @escaping () -> (), onLongTap: @escaping () -> ()) {
|
||||
activity = NSBackgroundActivityScheduler(identifier: "\(identifier.rawValue).updatecheck")
|
||||
activity.interval = interval
|
||||
self.from = from
|
||||
self.to = to
|
||||
@@ -71,7 +72,6 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
|
||||
if error == nil {
|
||||
do {
|
||||
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String : AnyObject]
|
||||
// print(json)
|
||||
var value: Float32!
|
||||
|
||||
if let data_array = json["data"] as? [String : AnyObject] {
|
||||
@@ -107,14 +107,11 @@ class CurrencyBarItem: CustomButtonTouchBarItem {
|
||||
}
|
||||
self.oldValue = value
|
||||
|
||||
button.title = String(format: "%@%.2f", self.prefix, value)
|
||||
|
||||
let textRange = NSRange(location: 0, length: button.title.count)
|
||||
let newTitle = NSMutableAttributedString(string: button.title)
|
||||
newTitle.addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: textRange)
|
||||
newTitle.addAttribute(NSAttributedStringKey.font, value: button.font!, range: textRange)
|
||||
newTitle.setAlignment(.center, range: textRange)
|
||||
let title = String(format: "%@%.2f", self.prefix, value)
|
||||
|
||||
let regularFont = button.attributedTitle.attribute(.font, at: 0, effectiveRange: nil) as? NSFont ?? NSFont.systemFont(ofSize: 15)
|
||||
let newTitle = NSMutableAttributedString(string: title as String, attributes: [.foregroundColor: color, .font: regularFont])
|
||||
newTitle.setAlignment(.center, range: NSRange(location: 0, length: title.count))
|
||||
button.attributedTitle = newTitle
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import Cocoa
|
||||
class InputSourceBarItem: CustomButtonTouchBarItem {
|
||||
|
||||
fileprivate var notificationCenter: CFNotificationCenter
|
||||
let buttonSize = NSSize(width: 21, height: 21)
|
||||
|
||||
init(identifier: NSTouchBarItem.Identifier, onTap: @escaping () -> (), onLongTap: @escaping () -> ()) {
|
||||
notificationCenter = CFNotificationCenterGetDistributedCenter();
|
||||
@@ -19,12 +20,25 @@ class InputSourceBarItem: CustomButtonTouchBarItem {
|
||||
observeIputSourceChangedNotification();
|
||||
textInputSourceDidChange()
|
||||
|
||||
self.button.cell?.action = #selector(switchInputSource)
|
||||
self.button.action = #selector(switchInputSource)
|
||||
|
||||
self.button.frame.size = buttonSize
|
||||
self.button.bounds.size = buttonSize
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
deinit {
|
||||
CFNotificationCenterRemoveEveryObserver(notificationCenter, UnsafeRawPointer(Unmanaged.passUnretained(self).toOpaque()));
|
||||
}
|
||||
|
||||
@objc override func handleGestureSingle(gr: NSClickGestureRecognizer) {
|
||||
super.handleGestureSingle(gr: gr)
|
||||
switchInputSource()
|
||||
}
|
||||
|
||||
@objc public func textInputSourceDidChange() {
|
||||
let currentSource = TISCopyCurrentKeyboardInputSource().takeUnretainedValue()
|
||||
@@ -42,7 +56,8 @@ class InputSourceBarItem: CustomButtonTouchBarItem {
|
||||
}
|
||||
|
||||
if (iconImage != nil) {
|
||||
self.button.image = iconImage
|
||||
self.button.cell?.image = iconImage
|
||||
self.button.cell?.image?.size = buttonSize
|
||||
} else {
|
||||
self.button.title = currentSource.name
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ class TimeTouchBarItem: CustomButtonTouchBarItem {
|
||||
super.init(identifier: identifier, title: " ", onTap: onTap, onLongTap: onLongTap)
|
||||
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
|
||||
self.view = button
|
||||
button.bezelColor = .clear
|
||||
updateTime()
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import Cocoa
|
||||
import CoreLocation
|
||||
|
||||
class WeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate {
|
||||
private let activity = NSBackgroundActivityScheduler(identifier: "com.toxblh.mtmr.weather.updatecheck")
|
||||
private let activity: NSBackgroundActivityScheduler
|
||||
private var units: String
|
||||
private var api_key: String
|
||||
private var units_str = "°F"
|
||||
@@ -23,6 +23,7 @@ class WeatherBarItem: CustomButtonTouchBarItem, CLLocationManagerDelegate {
|
||||
private var manager:CLLocationManager!
|
||||
|
||||
init(identifier: NSTouchBarItem.Identifier, interval: TimeInterval, units: String, api_key: String, icon_type: String? = "text", onTap: @escaping () -> (), onLongTap: @escaping () -> ()) {
|
||||
activity = NSBackgroundActivityScheduler(identifier: "\(identifier.rawValue).updatecheck")
|
||||
activity.interval = interval
|
||||
self.units = units
|
||||
self.api_key = api_key
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
{ "type": "volumeDown", "width": 34, "align": "right" },
|
||||
{ "type": "volume", "width": 60, "align": "right" },
|
||||
{ "type": "volumeUp", "width": 34, "align": "right" },
|
||||
{ "type": "inputsource", "align": "right" },
|
||||
{ "type": "battery", "align": "right" },
|
||||
{ "type": "timeButton", "align": "right" }
|
||||
]
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
# My TouchBar. My rules
|
||||
[](https://github.com/Toxblh/MTMR/releases)
|
||||
[](https://github.com/Toxblh/MTMR/blob/master/LICENSE) [](https://github.com/Toxblh/MTMR/releases/latest) 
|
||||
|
||||
<p align="center">
|
||||
<img src="Resources/TouchBar-v0.8.1.png">
|
||||
@@ -34,7 +35,7 @@ My the idea is to create the program like a platform for plugins for customizati
|
||||
- [ ] System for autoupdate (maybe https://sparkle-project.org/)
|
||||
|
||||
Settings:
|
||||
- [ ] Intarface for plugins and export like presets
|
||||
- [ ] Interface for plugins and export like presets
|
||||
- [ ] Startup at login
|
||||
- [ ] Show on/off in Dock
|
||||
- [ ] Show on/off in StatusBar
|
||||
@@ -45,9 +46,8 @@ Maybe:
|
||||
|
||||
|
||||
## Installation
|
||||
1. Download last release [Releases](https://github.com/Toxblh/MTMR/releases)
|
||||
3. Open MTMR
|
||||
4. Open preset `open ~/Library/Application\ Support/MTMR/items.json` and customize it. Restart MTMR to apply changes.
|
||||
- Download last [release](https://github.com/Toxblh/MTMR/releases)
|
||||
- Or via Homebrew `brew cask install mtmr`
|
||||
|
||||
## Preset
|
||||
|
||||
@@ -68,6 +68,7 @@ File for customize your preset for MTMR: `open ~/Library/Application\ Support/MT
|
||||
- battery
|
||||
- currency
|
||||
- weather
|
||||
- inputsource
|
||||
|
||||
> Media Keys
|
||||
- previous
|
||||
@@ -167,7 +168,7 @@ File for customize your preset for MTMR: `open ~/Library/Application\ Support/MT
|
||||
"url": "https://google.com",
|
||||
```
|
||||
|
||||
## Additional paramaters:
|
||||
## Additional parameters:
|
||||
|
||||
- `width` allow to restrict how much room a particular button will take
|
||||
```json
|
||||
|
||||
Reference in New Issue
Block a user