feat: added an option to show the power state icon (lightning or power plug) near the battery widget (#2008)

This commit is contained in:
Serhiy Mytrovtsiy
2024-10-17 16:57:26 +02:00
parent 4472960368
commit 359db0f0d0

View File

@@ -18,6 +18,7 @@ public class BatteryWidget: WidgetWrapper {
private var colorState: Bool = false
private var hideAdditionalWhenFull: Bool = true
private var xlSizeState: Bool = false
private var chargerIconInside: Bool = true
private var _percentage: Double? = nil
private var _time: Int = 0
@@ -44,6 +45,7 @@ public class BatteryWidget: WidgetWrapper {
self.colorState = Store.shared.bool(key: "\(self.title)_\(self.type.rawValue)_color", defaultValue: self.colorState)
self.hideAdditionalWhenFull = Store.shared.bool(key: "\(self.title)_\(self.type.rawValue)_hideAdditionalWhenFull", defaultValue: self.hideAdditionalWhenFull)
self.xlSizeState = Store.shared.bool(key: "\(self.title)_\(self.type.rawValue)_xlSize", defaultValue: self.xlSizeState)
self.chargerIconInside = Store.shared.bool(key: "\(self.title)_\(self.type.rawValue)_chargerInside", defaultValue: self.chargerIconInside)
}
if preview {
@@ -76,7 +78,7 @@ public class BatteryWidget: WidgetWrapper {
optimizedCharging = self._optimizedCharging
}
var width: CGFloat = Constants.Widget.margin.x*2
var width: CGFloat = 0
var x: CGFloat = 0
let isShortTimeFormat: Bool = self.timeFormat == "short"
@@ -88,14 +90,14 @@ public class BatteryWidget: WidgetWrapper {
value = "\(Int((percentage.rounded(toPlaces: 2)) * 100))%"
}
let rowWidth = self.drawOneRow(value: value, x: x).rounded(.up)
width += rowWidth + Constants.Widget.spacing
width += rowWidth
x += rowWidth + Constants.Widget.spacing
case "time":
let rowWidth = self.drawOneRow(
value: Double(time*60).printSecondsToHoursMinutesSeconds(short: isShortTimeFormat),
x: x
).rounded(.up)
width += rowWidth + Constants.Widget.spacing
width += rowWidth
x += rowWidth + Constants.Widget.spacing
case "percentageAndTime":
var value = "n/a"
@@ -107,7 +109,7 @@ public class BatteryWidget: WidgetWrapper {
second: Double(time*60).printSecondsToHoursMinutesSeconds(short: isShortTimeFormat),
x: x
).rounded(.up)
width += rowWidth + Constants.Widget.spacing
width += rowWidth
x += rowWidth + Constants.Widget.spacing
case "timeAndPercentage":
var value = "n/a"
@@ -119,17 +121,37 @@ public class BatteryWidget: WidgetWrapper {
second: value,
x: x
).rounded(.up)
width += rowWidth + Constants.Widget.spacing
width += rowWidth
x += rowWidth + Constants.Widget.spacing
default: break
}
}
let borderWidth: CGFloat = 1
let batterySize: CGSize = self.xlSizeState ? CGSize(width: 26, height: 14) : CGSize(width: 22, height: 12)
if ACStatus && !self.chargerIconInside {
if x != 0 {
width += Constants.Widget.spacing
x += Constants.Widget.spacing
}
self.drawACIcon(
ctx: ctx,
center: CGPoint(x: x+3, y: self.frame.size.height/2),
height: 12,
charging: charging
)
width += 6
x += 6 + Constants.Widget.spacing
}
let borderWidth: CGFloat = 1
let batteryRadius: CGFloat = self.xlSizeState ? 3 : 2
let offset: CGFloat = 0.5 // contant!
width += batterySize.width + borderWidth*2 // add battery width
if x != 0 {
width += Constants.Widget.spacing
x += Constants.Widget.spacing
}
let batteryFrame = NSBezierPath(roundedRect: NSRect(
x: x + borderWidth + offset,
@@ -165,8 +187,9 @@ public class BatteryWidget: WidgetWrapper {
let innerRadius: CGFloat = self.xlSizeState ? 2 : 1
var colorState = self.colorState
let color = percentage.batteryColor(color: colorState)
let innerPercentage = self.additional == "innerPercentage" && (!ACStatus || !self.chargerIconInside)
if self.additional == "innerPercentage" && !ACStatus {
if innerPercentage {
colorState = false
let innerUnderground = NSBezierPath(roundedRect: NSRect(
x: batteryFrame.bounds.origin.x + innerOffset,
@@ -188,7 +211,7 @@ public class BatteryWidget: WidgetWrapper {
color.set()
inner.fill()
if self.additional == "innerPercentage" && !ACStatus {
if innerPercentage {
let fontSize: CGFloat = self.xlSizeState ? 9 : 8
let style = NSMutableParagraphStyle()
style.alignment = .center
@@ -223,84 +246,17 @@ public class BatteryWidget: WidgetWrapper {
NSAttributedString.init(string: "?", attributes: attributes).draw(with: rect)
}
if ACStatus {
if ACStatus && self.chargerIconInside {
let batteryCenter: CGPoint = CGPoint(
x: batteryFrame.bounds.origin.x + (batteryFrame.bounds.width/2),
y: batteryFrame.bounds.origin.y + (batteryFrame.bounds.height/2)
)
var points: [CGPoint] = []
if charging {
let iconSize: CGSize = CGSize(width: 9, height: batterySize.height + 6)
let min = CGPoint(
x: batteryCenter.x - (iconSize.width/2),
y: batteryCenter.y - (iconSize.height/2)
)
let max = CGPoint(
x: batteryCenter.x + (iconSize.width/2),
y: batteryCenter.y + (iconSize.height/2)
)
points = [
CGPoint(x: batteryCenter.x-3, y: min.y), // bottom
CGPoint(x: max.x, y: batteryCenter.y+1.5),
CGPoint(x: batteryCenter.x+1, y: batteryCenter.y+1.5),
CGPoint(x: batteryCenter.x+3, y: max.y), // top
CGPoint(x: min.x, y: batteryCenter.y-1.5),
CGPoint(x: batteryCenter.x-1, y: batteryCenter.y-1.5)
]
} else {
let iconSize: CGSize = CGSize(width: 9, height: batterySize.height + 2)
let minY = batteryCenter.y - (iconSize.height/2)
let maxY = batteryCenter.y + (iconSize.height/2)
points = [
CGPoint(x: batteryCenter.x-1.5, y: minY+0.5),
CGPoint(x: batteryCenter.x+1.5, y: minY+0.5),
CGPoint(x: batteryCenter.x+1.5, y: batteryCenter.y - 2.5),
CGPoint(x: batteryCenter.x+4, y: batteryCenter.y + 0.5),
CGPoint(x: batteryCenter.x+4, y: batteryCenter.y + 4.25),
// right
CGPoint(x: batteryCenter.x+2.75, y: batteryCenter.y + 4.25),
CGPoint(x: batteryCenter.x+2.75, y: maxY-0.25),
CGPoint(x: batteryCenter.x+0.25, y: maxY-0.25),
CGPoint(x: batteryCenter.x+0.25, y: batteryCenter.y + 4.25),
// left
CGPoint(x: batteryCenter.x-0.25, y: batteryCenter.y + 4.25),
CGPoint(x: batteryCenter.x-0.25, y: maxY-0.25),
CGPoint(x: batteryCenter.x-2.75, y: maxY-0.25),
CGPoint(x: batteryCenter.x-2.75, y: batteryCenter.y + 4.25),
CGPoint(x: batteryCenter.x-4, y: batteryCenter.y + 4.25),
CGPoint(x: batteryCenter.x-4, y: batteryCenter.y + 0.5),
CGPoint(x: batteryCenter.x-1.5, y: batteryCenter.y - 2.5),
CGPoint(x: batteryCenter.x-1.5, y: minY+0.5)
]
}
let linePath = NSBezierPath()
linePath.move(to: CGPoint(x: points[0].x, y: points[0].y))
for i in 1..<points.count {
linePath.line(to: CGPoint(x: points[i].x, y: points[i].y))
}
linePath.line(to: CGPoint(x: points[0].x, y: points[0].y))
NSColor.textColor.set()
linePath.fill()
ctx.saveGState()
ctx.setBlendMode(.destinationOut)
NSColor.orange.set()
linePath.lineWidth = borderWidth
linePath.stroke()
ctx.restoreGState()
self.drawACIcon(
ctx: ctx,
center: batteryCenter,
height: 12,
charging: charging
)
}
self.setWidth(width)
@@ -345,6 +301,82 @@ public class BatteryWidget: WidgetWrapper {
return rowWidth
}
private func drawACIcon(ctx: CGContext, center batteryCenter: CGPoint, height: CGFloat, charging: Bool) {
var points: [CGPoint] = []
if charging {
let iconSize: CGSize = CGSize(width: 9, height: height + 6)
let min = CGPoint(
x: batteryCenter.x - (iconSize.width/2),
y: batteryCenter.y - (iconSize.height/2)
)
let max = CGPoint(
x: batteryCenter.x + (iconSize.width/2),
y: batteryCenter.y + (iconSize.height/2)
)
points = [
CGPoint(x: batteryCenter.x-3, y: min.y), // bottom
CGPoint(x: max.x, y: batteryCenter.y+1.5),
CGPoint(x: batteryCenter.x+1, y: batteryCenter.y+1.5),
CGPoint(x: batteryCenter.x+3, y: max.y), // top
CGPoint(x: min.x, y: batteryCenter.y-1.5),
CGPoint(x: batteryCenter.x-1, y: batteryCenter.y-1.5)
]
} else {
let iconSize: CGSize = CGSize(width: 9, height: height + 2)
let minY = batteryCenter.y - (iconSize.height/2)
let maxY = batteryCenter.y + (iconSize.height/2)
points = [
CGPoint(x: batteryCenter.x-1.5, y: minY+0.5),
CGPoint(x: batteryCenter.x+1.5, y: minY+0.5),
CGPoint(x: batteryCenter.x+1.5, y: batteryCenter.y - 2.5),
CGPoint(x: batteryCenter.x+4, y: batteryCenter.y + 0.5),
CGPoint(x: batteryCenter.x+4, y: batteryCenter.y + 4.25),
// right
CGPoint(x: batteryCenter.x+2.75, y: batteryCenter.y + 4.25),
CGPoint(x: batteryCenter.x+2.75, y: maxY-0.25),
CGPoint(x: batteryCenter.x+0.25, y: maxY-0.25),
CGPoint(x: batteryCenter.x+0.25, y: batteryCenter.y + 4.25),
// left
CGPoint(x: batteryCenter.x-0.25, y: batteryCenter.y + 4.25),
CGPoint(x: batteryCenter.x-0.25, y: maxY-0.25),
CGPoint(x: batteryCenter.x-2.75, y: maxY-0.25),
CGPoint(x: batteryCenter.x-2.75, y: batteryCenter.y + 4.25),
CGPoint(x: batteryCenter.x-4, y: batteryCenter.y + 4.25),
CGPoint(x: batteryCenter.x-4, y: batteryCenter.y + 0.5),
CGPoint(x: batteryCenter.x-1.5, y: batteryCenter.y - 2.5),
CGPoint(x: batteryCenter.x-1.5, y: minY+0.5)
]
}
let linePath = NSBezierPath()
linePath.move(to: CGPoint(x: points[0].x, y: points[0].y))
for i in 1..<points.count {
linePath.line(to: CGPoint(x: points[i].x, y: points[i].y))
}
linePath.line(to: CGPoint(x: points[0].x, y: points[0].y))
NSColor.textColor.set()
linePath.fill()
ctx.saveGState()
ctx.setBlendMode(.destinationOut)
NSColor.textColor.set()
linePath.lineWidth = 1
linePath.stroke()
ctx.restoreGState()
}
public func setValue(percentage: Double? = nil, ACStatus: Bool? = nil, isCharging: Bool? = nil, optimizedCharging: Bool? = nil, time: Int? = nil) {
var updated: Bool = false
let timeFormat: String = Store.shared.string(key: "\(self.title)_timeFormat", defaultValue: self.timeFormat)
@@ -408,6 +440,10 @@ public class BatteryWidget: WidgetWrapper {
PreferencesRow(localizedString("XL size"), component: switchView(
action: #selector(self.toggleXLSize),
state: self.xlSizeState
)),
PreferencesRow(localizedString("Charger state inside the battery"), component: switchView(
action: #selector(self.toggleChargerIconInside),
state: self.chargerIconInside
))
]))
@@ -438,6 +474,12 @@ public class BatteryWidget: WidgetWrapper {
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_xlSize", value: self.xlSizeState)
self.display()
}
@objc private func toggleChargerIconInside(_ sender: NSControl) {
self.chargerIconInside = controlState(sender)
Store.shared.set(key: "\(self.title)_\(self.type.rawValue)_chargerInside", value: self.chargerIconInside)
self.display()
}
}
public class BatteryDetailsWidget: WidgetWrapper {