diff --git a/README.md b/README.md index af396c50..3b2a063e 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,11 @@ You can download latest version [here](https://github.com/exelban/stats/releases ## What's new +### v1.2.4 + - fixed bug when widgets display not properly (or not shows at all) + - initialized bar chart widget + - fixed few bugs + ### v1.2.3 - new icon - small code refactoring diff --git a/Stats.xcodeproj/project.pbxproj b/Stats.xcodeproj/project.pbxproj index ed486c80..c75ad661 100755 --- a/Stats.xcodeproj/project.pbxproj +++ b/Stats.xcodeproj/project.pbxproj @@ -32,6 +32,7 @@ 9A7B8F6B22A2C3A700DEB352 /* Disk.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A7B8F6A22A2C3A700DEB352 /* Disk.swift */; }; 9A7B8F6D22A2C3D600DEB352 /* MemoryReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A7B8F6C22A2C3D600DEB352 /* MemoryReader.swift */; }; 9A7B8F6F22A2C57000DEB352 /* DiskReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A7B8F6E22A2C57000DEB352 /* DiskReader.swift */; }; + 9A9696EC22D526D900F967A5 /* BarChart.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9A9696EB22D526D900F967A5 /* BarChart.swift */; }; 9AFA402522AE49A200FE90BC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9AFA402422AE49A200FE90BC /* Assets.xcassets */; }; 9AFA402822AE49A200FE90BC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9AFA402622AE49A200FE90BC /* Main.storyboard */; }; 9AFA402F22AE49AE00FE90BC /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9AFA402E22AE49AE00FE90BC /* AppDelegate.swift */; }; @@ -82,6 +83,7 @@ 9A7B8F6A22A2C3A700DEB352 /* Disk.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Disk.swift; sourceTree = ""; }; 9A7B8F6C22A2C3D600DEB352 /* MemoryReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MemoryReader.swift; sourceTree = ""; }; 9A7B8F6E22A2C57000DEB352 /* DiskReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiskReader.swift; sourceTree = ""; }; + 9A9696EB22D526D900F967A5 /* BarChart.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BarChart.swift; sourceTree = ""; }; 9A998CD722A199920087ADE7 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 9A998CD922A199970087ADE7 /* ServiceManagement.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ServiceManagement.framework; path = System/Library/Frameworks/ServiceManagement.framework; sourceTree = SDKROOT; }; 9AFA401E22AE49A100FE90BC /* StatsLauncher.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = StatsLauncher.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -206,6 +208,7 @@ 9A74D59622B44498004FE1FA /* Mini.swift */, 9A58D1B322C179B200405315 /* NetworkView.swift */, 9A79B36922D3BEE600BF1C3A /* Widget.swift */, + 9A9696EB22D526D900F967A5 /* BarChart.swift */, ); path = Widgets; sourceTree = ""; @@ -385,6 +388,7 @@ 9A5B1CBF229E78F0008B9D3C /* Observable.swift in Sources */, 9A7B8F6B22A2C3A700DEB352 /* Disk.swift in Sources */, 9A1410F9229E721100D29793 /* AppDelegate.swift in Sources */, + 9A9696EC22D526D900F967A5 /* BarChart.swift in Sources */, 9A74D59722B44498004FE1FA /* Mini.swift in Sources */, 9A5B1CC5229E7B40008B9D3C /* Extensions.swift in Sources */, 9A79B36A22D3BEE600BF1C3A /* Widget.swift in Sources */, diff --git a/Stats/Modules/Battery/Battery.swift b/Stats/Modules/Battery/Battery.swift index 7ead5e5f..297f83c7 100644 --- a/Stats/Modules/Battery/Battery.swift +++ b/Stats/Modules/Battery/Battery.swift @@ -17,6 +17,7 @@ class Battery: Module { var active: Observable var available: Observable var color: Observable + var label: Observable var reader: Reader = BatteryReader() let defaults = UserDefaults.standard @@ -28,6 +29,7 @@ class Battery: Module { self.active = Observable(defaults.object(forKey: name) != nil ? defaults.bool(forKey: name) : true) self.percentageView = Observable(defaults.object(forKey: "\(self.name)_percentage") != nil ? defaults.bool(forKey: "\(self.name)_percentage") : false) self.color = Observable(defaults.object(forKey: "\(name)_color") != nil ? defaults.bool(forKey: "\(name)_color") : false) + self.label = Observable(defaults.object(forKey: "\(name)_label") != nil ? defaults.bool(forKey: "\(name)_label") : false) self.view = BatteryView(frame: NSMakeRect(0, 0, MODULE_WIDTH, MODULE_HEIGHT)) initMenu() initWidget() diff --git a/Stats/Modules/CPU/CPU.swift b/Stats/Modules/CPU/CPU.swift index 9e307a62..26e680b1 100644 --- a/Stats/Modules/CPU/CPU.swift +++ b/Stats/Modules/CPU/CPU.swift @@ -17,6 +17,7 @@ class CPU: Module { var active: Observable var available: Observable var color: Observable + var label: Observable var reader: Reader = CPUReader() let defaults = UserDefaults.standard @@ -27,16 +28,9 @@ class CPU: Module { self.active = Observable(defaults.object(forKey: name) != nil ? defaults.bool(forKey: name) : true) self.widgetType = defaults.object(forKey: "\(name)_widget") != nil ? defaults.float(forKey: "\(name)_widget") : Widgets.Mini self.color = Observable(defaults.object(forKey: "\(name)_color") != nil ? defaults.bool(forKey: "\(name)_color") : false) + self.label = Observable(defaults.object(forKey: "\(name)_label") != nil ? defaults.bool(forKey: "\(name)_label") : false) initMenu() initWidget() - - let labelStatus = defaults.bool(forKey: "\(name)_label") || defaults.object(forKey: "\(name)_label") == nil ? true : false - guard let chartView: Chart = self.view as? Chart else { - return - } - self.active << false - chartView.toggleLabel(value: labelStatus) - self.active << true } func initMenu() { @@ -62,6 +56,10 @@ class CPU: Module { chartWithValue.state = self.widgetType == Widgets.ChartWithValue ? NSControl.StateValue.on : NSControl.StateValue.off chartWithValue.target = self + let barChart = NSMenuItem(title: "Bar chart", action: #selector(toggleWidget), keyEquivalent: "") + barChart.state = self.widgetType == Widgets.BarChart ? NSControl.StateValue.on : NSControl.StateValue.off + barChart.target = self + let color = NSMenuItem(title: "Color", action: #selector(toggleColor), keyEquivalent: "") color.state = defaults.bool(forKey: "\(name)_color") ? NSControl.StateValue.on : NSControl.StateValue.off color.target = self @@ -73,6 +71,7 @@ class CPU: Module { submenu.addItem(mini) submenu.addItem(chart) submenu.addItem(chartWithValue) +// submenu.addItem(barChart) submenu.addItem(NSMenuItem.separator()) @@ -107,6 +106,8 @@ class CPU: Module { widgetCode = Widgets.Chart case "Chart with value": widgetCode = Widgets.ChartWithValue + case "Bar chart": + widgetCode = Widgets.BarChart default: break } @@ -116,7 +117,7 @@ class CPU: Module { } for item in self.submenu.items { - if item.title == "Mini" || item.title == "Chart" || item.title == "Chart with value" { + if item.title == "Mini" || item.title == "Chart" || item.title == "Chart with value" || item.title == "Bar chart" { item.state = NSControl.StateValue.off } } @@ -125,7 +126,7 @@ class CPU: Module { self.defaults.set(widgetCode, forKey: "\(name)_widget") self.widgetType = widgetCode self.active << false - initWidget(color: defaults.object(forKey: "\(name)_color") != nil ? defaults.bool(forKey: "\(name)_color") : false) + initWidget() self.active << true } @@ -138,12 +139,8 @@ class CPU: Module { @objc func toggleLabel(_ sender: NSMenuItem) { sender.state = sender.state == NSControl.StateValue.on ? NSControl.StateValue.off : NSControl.StateValue.on self.defaults.set(sender.state == NSControl.StateValue.on, forKey: "\(name)_label") - - guard let chartView: Chart = self.view as? Chart else { - return - } self.active << false - chartView.toggleLabel(value: sender.state == NSControl.StateValue.on) + self.label << (sender.state == NSControl.StateValue.on) self.active << true } } diff --git a/Stats/Modules/Disk/Disk.swift b/Stats/Modules/Disk/Disk.swift index a8580c64..c0b85ea3 100644 --- a/Stats/Modules/Disk/Disk.swift +++ b/Stats/Modules/Disk/Disk.swift @@ -20,6 +20,7 @@ class Disk: Module { var active: Observable var available: Observable var color: Observable + var label: Observable var reader: Reader = DiskReader() @@ -30,6 +31,7 @@ class Disk: Module { self.active = Observable(defaults.object(forKey: name) != nil ? defaults.bool(forKey: name) : true) self.widgetType = defaults.object(forKey: "\(name)_widget") != nil ? defaults.float(forKey: "\(name)_widget") : Widgets.Mini self.color = Observable(defaults.object(forKey: "\(name)_color") != nil ? defaults.bool(forKey: "\(name)_color") : false) + self.label = Observable(defaults.object(forKey: "\(name)_label") != nil ? defaults.bool(forKey: "\(name)_label") : false) self.initMenu() self.initWidget() diff --git a/Stats/Modules/Memory/Memory.swift b/Stats/Modules/Memory/Memory.swift index 7d883e81..d88b7c61 100644 --- a/Stats/Modules/Memory/Memory.swift +++ b/Stats/Modules/Memory/Memory.swift @@ -17,6 +17,7 @@ class Memory: Module { var active: Observable var available: Observable var color: Observable + var label: Observable var reader: Reader = MemoryReader() var widgetType: WidgetType @@ -29,16 +30,9 @@ class Memory: Module { self.active = Observable(defaults.object(forKey: name) != nil ? defaults.bool(forKey: name) : true) self.widgetType = defaults.object(forKey: "\(name)_widget") != nil ? defaults.float(forKey: "\(name)_widget") : Widgets.Mini self.color = Observable(defaults.object(forKey: "\(name)_color") != nil ? defaults.bool(forKey: "\(name)_color") : false) + self.label = Observable(defaults.object(forKey: "\(name)_label") != nil ? defaults.bool(forKey: "\(name)_label") : false) initMenu() initWidget() - - let labelStatus = defaults.bool(forKey: "\(name)_label") || defaults.object(forKey: "\(name)_label") == nil ? true : false - guard let chartView: Chart = self.view as? Chart else { - return - } - self.active << false - chartView.toggleLabel(value: labelStatus) - self.active << true } func initMenu() { @@ -110,6 +104,8 @@ class Memory: Module { widgetCode = Widgets.Chart case "Chart with value": widgetCode = Widgets.ChartWithValue + case "Bar chart": + widgetCode = Widgets.BarChart default: break } @@ -141,12 +137,8 @@ class Memory: Module { @objc func toggleLabel(_ sender: NSMenuItem) { sender.state = sender.state == NSControl.StateValue.on ? NSControl.StateValue.off : NSControl.StateValue.on self.defaults.set(sender.state == NSControl.StateValue.on, forKey: "\(name)_label") - - guard let chartView: Chart = self.view as? Chart else { - return - } self.active << false - chartView.toggleLabel(value: sender.state == NSControl.StateValue.on) + self.label << (sender.state == NSControl.StateValue.on) self.active << true } } diff --git a/Stats/Modules/Module.swift b/Stats/Modules/Module.swift index 759a9136..78ce928c 100644 --- a/Stats/Modules/Module.swift +++ b/Stats/Modules/Module.swift @@ -18,7 +18,8 @@ protocol Module: class { var active: Observable { get } var available: Observable { get } - var color: Observable { get set } + var color: Observable { get } + var label: Observable { get } var reader: Reader { get } @@ -27,7 +28,7 @@ protocol Module: class { } extension Module { - func initWidget(color: Bool = false) { + func initWidget(label: Bool = false) { var widget: Widget = Mini(frame: NSMakeRect(0, 0, MODULE_WIDTH, MODULE_HEIGHT)) switch self.widgetType { @@ -47,12 +48,15 @@ extension Module { widget = NetworkDotsTextView(frame: NSMakeRect(0, 0, MODULE_WIDTH, MODULE_HEIGHT)) case Widgets.NetworkArrowsWithText: widget = NetworkArrowsTextView(frame: NSMakeRect(0, 0, MODULE_WIDTH, MODULE_HEIGHT)) + case Widgets.BarChart: + widget = BarChart(frame: NSMakeRect(0, 0, MODULE_WIDTH + 10, MODULE_HEIGHT)) default: widget = Mini(frame: NSMakeRect(0, 0, MODULE_WIDTH, MODULE_HEIGHT)) } widget.label = self.shortName widget.color(state: self.color.value) + widget.label(state: self.label.value) self.view = widget as! NSView } @@ -81,11 +85,19 @@ extension Module { widget.color(state: value) widget.redraw() } + + self.label.subscribe(observer: self) { (value, _) in + guard let widget = self.view as? Widget else { + return + } + widget.label(state: value) + } } func stop() { self.reader.stop() self.reader.value.unsubscribe(observer: self) self.color.unsubscribe(observer: self) + self.label.unsubscribe(observer: self) } } diff --git a/Stats/Modules/Network/Network.swift b/Stats/Modules/Network/Network.swift index 3ed2cf33..a71cd53c 100644 --- a/Stats/Modules/Network/Network.swift +++ b/Stats/Modules/Network/Network.swift @@ -17,6 +17,7 @@ class Network: Module { var active: Observable var available: Observable var color: Observable + var label: Observable var reader: Reader = NetworkReader() var widgetType: WidgetType = 2.0 @@ -27,6 +28,7 @@ class Network: Module { self.active = Observable(defaults.object(forKey: name) != nil ? defaults.bool(forKey: name) : true) self.widgetType = defaults.object(forKey: "\(name)_widget") != nil ? defaults.float(forKey: "\(name)_widget") : Widgets.NetworkDots self.color = Observable(defaults.object(forKey: "\(name)_color") != nil ? defaults.bool(forKey: "\(name)_color") : false) + self.label = Observable(defaults.object(forKey: "\(name)_label") != nil ? defaults.bool(forKey: "\(name)_label") : false) initMenu() initWidget() } diff --git a/Stats/Supporting Files/Info.plist b/Stats/Supporting Files/Info.plist index ad08de2e..8fe65cd5 100755 --- a/Stats/Supporting Files/Info.plist +++ b/Stats/Supporting Files/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.2.3 + 1.2.4 CFBundleVersion - 8 + 1 LSApplicationCategoryType public.app-category.utilities LSMinimumSystemVersion diff --git a/Stats/Widgets/BarChart.swift b/Stats/Widgets/BarChart.swift new file mode 100644 index 00000000..5938a9b4 --- /dev/null +++ b/Stats/Widgets/BarChart.swift @@ -0,0 +1,123 @@ +// +// BarChart.swift +// Stats +// +// Created by Serhiy Mytrovtsiy on 09.07.2019. +// Copyright © 2019 Serhiy Mytrovtsiy. All rights reserved. +// + +import Cocoa + +class BarChart: NSView, Widget { + var size: CGFloat = MODULE_WIDTH + 10 + + var labelPadding: CGFloat = 12.0 + var labelEnabled: Bool = false + var label: String = "" + var color: Bool = false + + var partitions: [Double] { + didSet { + self.redraw() + } + } + + override init(frame: NSRect) { + self.partitions = Array(repeating: 0.0, count: 1) + super.init(frame: frame) + self.wantsLayer = true + self.addSubview(NSView()) + + if self.labelEnabled { + self.frame = CGRect(x: self.frame.origin.x, y: self.frame.origin.y, width: self.frame.size.width + labelPadding, height: self.frame.size.height) + } + } + + required init?(coder decoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func draw(_ dirtyRect: NSRect) { + super.draw(dirtyRect) + + let gradientColor: NSColor = NSColor(red: (26/255.0), green: (126/255.0), blue: (252/255.0), alpha: 0.8) + + let width = self.frame.size.width - (MODULE_MARGIN * 2) + let height = self.frame.size.height - (MODULE_MARGIN * 2) + 1 + + var x = MODULE_MARGIN + if labelEnabled { + x = x + labelPadding + } + + let partitionMargin: CGFloat = 0.5 + let partitionsWidth: CGFloat = width - (partitionMargin * 2) - x + var partitionWidth: CGFloat = partitionsWidth + if partitions.count > 1 { + partitionWidth = (partitionsWidth - (partitionMargin * (CGFloat(partitions.count) - 1))) / CGFloat(partitions.count) + } + + for i in 0..