mirror of
https://github.com/morgan9e/macos-stats
synced 2026-04-14 08:14:19 +09:00
- improve Battery widget on low resolution displays (#105)
- make Battery widget more similar to Big Sur
This commit is contained in:
@@ -29,16 +29,18 @@ public class BatterykWidget: Widget {
|
||||
public init(preview: Bool, title: String, config: NSDictionary?, store: UnsafePointer<Store>?) {
|
||||
let widgetTitle: String = title
|
||||
self.store = store
|
||||
|
||||
super.init(frame: CGRect(
|
||||
x: 0,
|
||||
x: Constants.Widget.margin.x,
|
||||
y: Constants.Widget.margin.y,
|
||||
width: 30,
|
||||
width: 30 + (2*Constants.Widget.margin.x),
|
||||
height: Constants.Widget.height - (2*Constants.Widget.margin.y)
|
||||
))
|
||||
|
||||
self.title = widgetTitle
|
||||
self.type = .battery
|
||||
self.preview = preview
|
||||
self.wantsLayer = true
|
||||
self.canDrawConcurrently = true
|
||||
|
||||
if self.store != nil {
|
||||
self.additional = store!.pointee.string(key: "\(self.title)_\(self.type.rawValue)_additional", defaultValue: self.additional)
|
||||
@@ -63,8 +65,10 @@ public class BatterykWidget: Widget {
|
||||
public override func draw(_ dirtyRect: NSRect) {
|
||||
super.draw(dirtyRect)
|
||||
|
||||
var width: CGFloat = 30
|
||||
var x: CGFloat = Constants.Widget.margin.x+1
|
||||
guard let ctx = NSGraphicsContext.current?.cgContext else { return }
|
||||
|
||||
var width: CGFloat = Constants.Widget.margin.x*2
|
||||
var x: CGFloat = 0
|
||||
let isShortTimeFormat: Bool = self.timeFormat == "short"
|
||||
|
||||
if !self.hideAdditionalWhenFull || (self.hideAdditionalWhenFull && self.percentage != 1) {
|
||||
@@ -74,74 +78,85 @@ public class BatterykWidget: Widget {
|
||||
value: "\(Int((self.percentage.rounded(toPlaces: 2)) * 100))%",
|
||||
x: x
|
||||
).rounded(.up)
|
||||
width += rowWidth + Constants.Widget.margin.x
|
||||
x += rowWidth + Constants.Widget.margin.x
|
||||
width += rowWidth + Constants.Widget.spacing
|
||||
x += rowWidth + Constants.Widget.spacing
|
||||
case "time":
|
||||
let rowWidth = self.drawOneRow(
|
||||
value: Double(self.time*60).printSecondsToHoursMinutesSeconds(short: isShortTimeFormat),
|
||||
x: x
|
||||
).rounded(.up)
|
||||
width += rowWidth + Constants.Widget.margin.x
|
||||
x += rowWidth + Constants.Widget.margin.x
|
||||
width += rowWidth + Constants.Widget.spacing
|
||||
x += rowWidth + Constants.Widget.spacing
|
||||
case "percentageAndTime":
|
||||
let rowWidth = self.drawTwoRows(
|
||||
first: "\(Int((self.percentage.rounded(toPlaces: 2)) * 100))%",
|
||||
second: Double(self.time*60).printSecondsToHoursMinutesSeconds(short: isShortTimeFormat),
|
||||
x: x
|
||||
).rounded(.up)
|
||||
width += rowWidth + Constants.Widget.margin.x
|
||||
x += rowWidth + Constants.Widget.margin.x
|
||||
width += rowWidth + Constants.Widget.spacing
|
||||
x += rowWidth + Constants.Widget.spacing
|
||||
case "timeAndPercentage":
|
||||
let rowWidth = self.drawTwoRows(
|
||||
first: Double(self.time*60).printSecondsToHoursMinutesSeconds(short: isShortTimeFormat),
|
||||
second: "\(Int((self.percentage.rounded(toPlaces: 2)) * 100))%",
|
||||
x: x
|
||||
).rounded(.up)
|
||||
width += rowWidth + Constants.Widget.margin.x
|
||||
x += rowWidth + Constants.Widget.margin.x
|
||||
width += rowWidth + Constants.Widget.spacing
|
||||
x += rowWidth + Constants.Widget.spacing
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
||||
let w: CGFloat = 28 - (Constants.Widget.margin.x*2) - 4
|
||||
let h: CGFloat = 11
|
||||
let y: CGFloat = (dirtyRect.size.height - h) / 2
|
||||
let batteryFrame = NSBezierPath(roundedRect: NSRect(x: x+1, y: y, width: w, height: h), xRadius: 1.5, yRadius: 1.5)
|
||||
let borderWidth: CGFloat = 1
|
||||
let batterySize: CGSize = CGSize(width: 22, height: 12)
|
||||
let offset: CGFloat = 0.5 // contant!
|
||||
width += batterySize.width + borderWidth*2 // add battery width
|
||||
|
||||
let bPX: CGFloat = x+w+1
|
||||
let bPY: CGFloat = (dirtyRect.size.height / 2) - 2
|
||||
let batteryPoint = NSBezierPath(roundedRect: NSRect(x: bPX, y: bPY, width: 2, height: 4), xRadius: 1, yRadius: 1)
|
||||
NSColor.textColor.set()
|
||||
batteryPoint.lineWidth = 1.1
|
||||
batteryPoint.stroke()
|
||||
let batteryFrame = NSBezierPath(roundedRect: NSRect(
|
||||
x: x + borderWidth + offset,
|
||||
y: ((dirtyRect.size.height - batterySize.height)/2) + offset,
|
||||
width: batterySize.width - borderWidth,
|
||||
height: batterySize.height - borderWidth
|
||||
), xRadius: 2, yRadius: 2)
|
||||
|
||||
NSColor.textColor.withAlphaComponent(0.5).set()
|
||||
batteryFrame.lineWidth = borderWidth
|
||||
batteryFrame.stroke()
|
||||
|
||||
let bPX: CGFloat = batteryFrame.bounds.origin.x + batteryFrame.bounds.width + 1
|
||||
let bPY: CGFloat = batteryFrame.bounds.origin.y + batteryFrame.bounds.height/2 - 2
|
||||
let batteryPoint = NSBezierPath(roundedRect: NSRect(x: bPX - 1, y: bPY, width: 3, height: 4), xRadius: 2, yRadius: 2)
|
||||
batteryPoint.fill()
|
||||
|
||||
batteryFrame.lineWidth = 1
|
||||
batteryFrame.stroke()
|
||||
|
||||
if !self.charging || !self.ACStatus {
|
||||
let maxWidth = w - 3
|
||||
let innerWidth: CGFloat = self.ACStatus ? maxWidth : maxWidth * CGFloat(self.percentage)
|
||||
let inner = NSBezierPath(roundedRect: NSRect(x: x+2.5, y: y+1.5, width: innerWidth, height: h-3), xRadius: 0.5, yRadius: 0.5)
|
||||
self.percentage.batteryColor(color: self.colorState).set()
|
||||
inner.lineWidth = 0
|
||||
inner.stroke()
|
||||
inner.close()
|
||||
inner.fill()
|
||||
} else if self.charging {
|
||||
let maxHeight = h - 3
|
||||
let height: CGFloat = maxHeight * CGFloat(self.percentage)
|
||||
let inner = NSBezierPath(roundedRect: NSRect(x: x+2.5, y: y+1.5, width: w-3, height: height), xRadius: 0.5, yRadius: 0.5)
|
||||
(self.percentage == 1 ? NSColor.textColor : NSColor.systemGreen).set()
|
||||
inner.lineWidth = 0
|
||||
inner.stroke()
|
||||
inner.close()
|
||||
inner.fill()
|
||||
}
|
||||
let batteryPointSeparator = NSBezierPath()
|
||||
batteryPointSeparator.move(to: CGPoint(x: bPX, y: batteryFrame.bounds.origin.y))
|
||||
batteryPointSeparator.line(to: CGPoint(x: bPX, y: batteryFrame.bounds.origin.y + batteryFrame.bounds.height))
|
||||
ctx.saveGState()
|
||||
ctx.setBlendMode(.destinationOut)
|
||||
NSColor.textColor.set()
|
||||
batteryPointSeparator.lineWidth = borderWidth
|
||||
batteryPointSeparator.stroke()
|
||||
ctx.restoreGState()
|
||||
width += 2 // add battery point width
|
||||
|
||||
let maxWidth = batterySize.width - offset*2 - borderWidth*2 - 1
|
||||
let innerWidth: CGFloat = self.ACStatus && !self.charging ? maxWidth : max(1, maxWidth * CGFloat(self.percentage))
|
||||
let innerOffset: CGFloat = -offset + borderWidth + 1
|
||||
let inner = NSBezierPath(roundedRect: NSRect(
|
||||
x: batteryFrame.bounds.origin.x + innerOffset,
|
||||
y: batteryFrame.bounds.origin.y + innerOffset,
|
||||
width: innerWidth,
|
||||
height: batterySize.height - offset*2 - borderWidth*2 - 1
|
||||
), xRadius: 1, yRadius: 1)
|
||||
self.percentage.batteryColor(color: self.colorState).set()
|
||||
inner.fill()
|
||||
|
||||
if self.ACStatus {
|
||||
let batteryCenter: CGPoint = CGPoint(x: x+1+(w/2), y: y+(h/2))
|
||||
let boltSize: CGSize = CGSize(width: 8, height: h+3+4)
|
||||
let batteryCenter: CGPoint = CGPoint(
|
||||
x: batteryFrame.bounds.origin.x + (batteryFrame.bounds.width/2),
|
||||
y: batteryFrame.bounds.origin.y + (batteryFrame.bounds.height/2)
|
||||
)
|
||||
let boltSize: CGSize = CGSize(width: 9, height: batterySize.height + 6)
|
||||
|
||||
let minX = batteryCenter.x - (boltSize.width/2)
|
||||
let maxX = batteryCenter.x + (boltSize.width/2)
|
||||
@@ -149,10 +164,10 @@ public class BatterykWidget: Widget {
|
||||
let maxY = batteryCenter.y + (boltSize.height/2)
|
||||
|
||||
let points: [CGPoint] = [
|
||||
CGPoint(x: batteryCenter.x-2, y: minY),
|
||||
CGPoint(x: batteryCenter.x-3, y: minY), // bottom
|
||||
CGPoint(x: maxX, y: batteryCenter.y+1.5),
|
||||
CGPoint(x: batteryCenter.x+1, y: batteryCenter.y+1.5),
|
||||
CGPoint(x: batteryCenter.x+2, y: maxY),
|
||||
CGPoint(x: batteryCenter.x+3, y: maxY), // top
|
||||
CGPoint(x: minX, y: batteryCenter.y-1.5),
|
||||
CGPoint(x: batteryCenter.x-1, y: batteryCenter.y-1.5),
|
||||
]
|
||||
@@ -167,12 +182,11 @@ public class BatterykWidget: Widget {
|
||||
NSColor.textColor.set()
|
||||
linePath.fill()
|
||||
|
||||
let ctx = NSGraphicsContext.current!.cgContext
|
||||
ctx.saveGState()
|
||||
ctx.setBlendMode(.destinationOut)
|
||||
|
||||
NSColor.orange.set()
|
||||
linePath.lineWidth = 1
|
||||
linePath.lineWidth = borderWidth
|
||||
linePath.stroke()
|
||||
|
||||
ctx.restoreGState()
|
||||
@@ -200,15 +214,15 @@ public class BatterykWidget: Widget {
|
||||
let style = NSMutableParagraphStyle()
|
||||
style.alignment = .center
|
||||
let attributes = [
|
||||
NSAttributedString.Key.font: NSFont.systemFont(ofSize: 9, weight: .light),
|
||||
NSAttributedString.Key.font: NSFont.systemFont(ofSize: 9, weight: .regular),
|
||||
NSAttributedString.Key.foregroundColor: NSColor.textColor,
|
||||
NSAttributedString.Key.paragraphStyle: style
|
||||
]
|
||||
let rowHeight: CGFloat = self.frame.height / 2
|
||||
|
||||
let rowWidth = max(
|
||||
first.widthOfString(usingFont: .systemFont(ofSize: 9, weight: .light)),
|
||||
second.widthOfString(usingFont: .systemFont(ofSize: 9, weight: .light))
|
||||
first.widthOfString(usingFont: .systemFont(ofSize: 9, weight: .regular)),
|
||||
second.widthOfString(usingFont: .systemFont(ofSize: 9, weight: .regular))
|
||||
)
|
||||
|
||||
var str = NSAttributedString.init(string: first, attributes: attributes)
|
||||
@@ -252,6 +266,8 @@ public class BatterykWidget: Widget {
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Settings
|
||||
|
||||
public override func settings(superview: NSView) {
|
||||
let rowHeight: CGFloat = 30
|
||||
let height: CGFloat = ((rowHeight + Constants.Settings.margin) * 3) + Constants.Settings.margin
|
||||
|
||||
@@ -97,8 +97,6 @@ public class LineChart: Widget {
|
||||
self.chart.points = list
|
||||
self.value = 0.38
|
||||
}
|
||||
|
||||
// self.addSubview(self.chart)
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) {
|
||||
@@ -234,7 +232,7 @@ public class LineChart: Widget {
|
||||
|
||||
self.value = value
|
||||
DispatchQueue.main.async(execute: {
|
||||
// self.chart.addValue(value)
|
||||
self.chart.addValue(value)
|
||||
self.display()
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user