diff --git a/bin/init.lua b/bin/init.lua index 4e8e4a8..67f2b3a 100755 --- a/bin/init.lua +++ b/bin/init.lua @@ -24,16 +24,6 @@ return { end, }, - battery = { - watch = function(timeout, callback, widget) - awful.widget.watch(script_dir .. "battery", timeout, callback, widget) - end, - - status = function(callback) - awful.spawn.easy_async(script_dir .. "battery", callback) - end, - }, - rofi = { launcher = function() awful.spawn("rofi -show drun -theme \"" .. bin_dir .. "/rofi/launcher.rasi\"") diff --git a/classes/battery/arc_widget.lua b/classes/battery/arc_widget.lua new file mode 100644 index 0000000..3a3376d --- /dev/null +++ b/classes/battery/arc_widget.lua @@ -0,0 +1,158 @@ +local P = {} + +function P:set_value(value) + -- Set widget value. (0 - 100) + self.arc.value = value + + --[[ + if batpec > 60 then + self.progressbar.color = beautiful.color.battery.good + elseif batpec > 40 then + self.progressbar.color = beautiful.color.battery.low + elseif batpec <= 40 then + self.progressbar.color = beautiful.color.battery.danger + end + + if (self.state == "discharging") then + self.rotator.direction = "east" + else + self.rotator.direction = "west" + end + + if (self.state == "charging") and (value > 90) then + self.progressbar.border_color = beautiful.color.battery.good + elseif (self.state == "discharging") and (value <= 25) then + self.progressbar.border_color = beautiful.color.battery.danger + else + self.rogressbar.border_color = beautiful.color.bar.active + end + --]] + + -- Set current battery icon + if (self.state == "charging") then + if value > 80 then self.icon.image = beautiful.icons.battery.charging.full + elseif value > 60 then self.icon.image = beautiful.icons.battery.charging.good + elseif value > 40 then self.icon.image = beautiful.icons.battery.charging.low + elseif value > 20 then self.icon.image = beautiful.icons.battery.charging.caution + elseif value <= 20 then self.icon.image = beautiful.icons.battery.charging.empty end + elseif (self.state == "discharging") then + if value > 80 then self.icon.image = beautiful.icons.battery.full + elseif value > 60 then self.icon.image = beautiful.icons.battery.good + elseif value > 40 then self.icon.image = beautiful.icons.battery.low + elseif value > 20 then self.icon.image = beautiful.icons.battery.caution + elseif value <= 20 then self.icon.image = beautiful.icons.battery.empty end + else + self.icon.image = beautiful.icons.battery.missing + end +end + +function P:set_state(state) + if (state == "discharging") then + self.state = "discharging" + elseif (state == "charging") then + self.state = "charging" + elseif (state == "error") then + self.state = "error" + else + error("Invalid state " .. state) + end +end + +function P:set_tooltip(text) + -- Set widget value. (0 - 100) + self.tooltip.text = text +end + +function P:new() + widget = { + state = "error" + } + setmetatable(widget, self) + self.__index = self + + widget.icon = wibox.widget { + image = beautiful.icons.battery.missing, + resize = true, + widget = wibox.widget.imagebox, + } + + --[[ + widget.progressbar = wibox.widget { + max_value = 100, + widget = wibox.widget.progressbar, + paddings = beautiful.dpi(2), + color = beautiful.color.bar.active, + background_color = beautiful.color.transparent, + border_color = beautiful.color.bar.active, + border_width = beautiful.dpi(1), + margins = beautiful.dpi(3) + } + + widget.rotator = wibox.widget { + widget.progressbar, + forced_width = beautiful.dpi(15), + direction = "east", + layout = wibox.container.rotate, + } + --]] + + widget.arc = wibox.widget { + { + widget.icon, + top = beautiful.dpi(1), + bottom = beautiful.dpi(1), + layout = wibox.container.margin, + }, + max_value = 100, + thickness = beautiful.dpi(4), + start_angle = 4.71238898, -- 2pi*3/4 + --forced_height = beautiful.dpi(16), + --forced_width = beautiful.dpi(16), + colors = {"#27D4CC", "#00446B"}, + bg = "#FFFFFF30", + paddings = beautiful.dpi(2), + widget = wibox.container.arcchart + } + + + widget.widget = wibox.widget { + { + { -- Right space + widget = wibox.widget.separator, + color = beautiful.color.transparent, + forced_width = beautiful.dpi(3) + }, + { + widget.arc, + top = beautiful.dpi(2), + bottom = beautiful.dpi(2), + layout = wibox.container.margin, + }, + { -- Left space + widget = wibox.widget.separator, + color = beautiful.color.transparent, + forced_width = beautiful.dpi(3) + }, + + layout = wibox.layout.align.horizontal, + }, + layout = wibox.container.background, + } + + widget.tooltip = awful.tooltip { + objects = { widget.widget }, + text = "" + } + + widget.widget:connect_signal("mouse::enter", function(result) + widget.widget.bg = beautiful.color.bar.hover_bg + end) + + widget.widget:connect_signal("mouse::leave", function(result) + widget.widget.bg = beautiful.color.transparent + end) + + return widget +end + +return P diff --git a/classes/battery/battery.lua b/classes/battery/battery.lua new file mode 100644 index 0000000..646a0fe --- /dev/null +++ b/classes/battery/battery.lua @@ -0,0 +1,120 @@ +local widget_types = { + arc = require("classes/battery/arc_widget"), + prog = require("classes/battery/prog_widget") +} + +local P = {} + + +--- +-- Internal methods +--- +function P:_get_status() + awful.spawn.easy_async( + script_dir .. "battery", + function(stdout, stderr, exitreason, exitcode) + + local bat = string.match(stdout, "(%d?%d?%d)%%") + bat = tonumber(string.format("% 3d", bat)) + local discharging = string.match(stdout, "discharging") or false + + self._ready = true + self.battery_percent = bat + self.charging = not discharging + self:_update_widget() + self:_check_notification() + end + ) + return true +end + + + +function P:_update_widget() + if (not self._ready) then + self.widget:set_state("error") + self.widget:set_value(100); + self.widget:set_tooltip("Battery error"); + return + end + + if (self.charging) then + self.widget:set_state("charging") + else + self.widget:set_state("discharging") + end + + self.widget:set_value(self.battery_percent); + self.widget:set_tooltip("Battery " .. math.floor(self.battery_percent) .. "%"); +end + +function P:_check_notification() + if not self.charging then + for i=1, #self.warnings do + v = self.warnings[i] + if (self.battery_percent <= v) and (not self._warning_log[i]) then + self._warning_log[i] = true + + naughty.notify({ + title = "Low power", + text = "Battery is at " .. tostring(self.battery_percent) .. "%", + icon = beautiful.icons.battery.caution, + + timeout = 5, + ignore_suspend = true, + + border_color = beautiful.color.battery.danger, + preset = beautiful.notification_templates.bottom_right + }) + break + end + end + else + for i=1, #self.warnings do + if (self.battery_percent >= self.warnings[i]) then + self._warning_log[i] = false + end + end + end +end + +--- +-- Create new +--- +function P:new(args) + -- Arguments + b = { + update_interval = args.update_interal or 5, + widget_type = args.widget_type or "arc", + warnings = {5, 10, 25, 50}, -- Percentages to warn at (must be in order) + _warning_log = {}, + + _ready = false, -- is all the information in this class up-to-date? + -- if this is false, ui will show an error and most methods will + -- do nothing. Updated in _get_status() + } + + -- Initialize warning log + for i=1, #b.warnings do + b._warning_log[i] = false + end + + b.widget = widget_types[b.widget_type]:new() + + setmetatable(b, self) + self.__index = self + + -- This timer keeps mute and volume status up-to-date. + b.timer = gears.timer { + timeout = b.update_interval, + call_now = true, + autostart = true, + callback = function() + b:_get_status() + end + } + + return b +end + +return P diff --git a/classes/battery/init.lua b/classes/battery/init.lua new file mode 100644 index 0000000..c136706 --- /dev/null +++ b/classes/battery/init.lua @@ -0,0 +1,7 @@ +local P = require("classes/battery/battery") + +local F = function(args) + return P:new(args) +end + +return F diff --git a/classes/battery/prog_widget.lua b/classes/battery/prog_widget.lua new file mode 100644 index 0000000..9a58ac5 --- /dev/null +++ b/classes/battery/prog_widget.lua @@ -0,0 +1,113 @@ +local P = {} + +function P:set_value(value) + -- Set widget value. (0 - 100) + self.progressbar.value = value + + if value > 60 then + self.progressbar.color = beautiful.color.battery.good + elseif value > 40 then + self.progressbar.color = beautiful.color.battery.low + elseif value <= 40 then + self.progressbar.color = beautiful.color.battery.danger + end + + if (self.state == "discharging") then + self.rotator.direction = "east" + else + self.rotator.direction = "west" + end + + if (self.state == "charging") and (value > 90) then + self.progressbar.border_color = beautiful.color.battery.good + elseif (self.state == "discharging") and (value <= 25) then + self.progressbar.border_color = beautiful.color.battery.danger + else + self.progressbar.border_color = beautiful.color.bar.active + end + +end + +function P:set_state(state) + if (state == "discharging") then + self.state = "discharging" + elseif (state == "charging") then + self.state = "charging" + elseif (state == "error") then + self.state = "error" + else + error("Invalid state " .. state) + end +end + +function P:set_tooltip(text) + -- Set widget value. (0 - 100) + self.tooltip.text = text +end + +function P:new() + widget = { + state = "error" + } + setmetatable(widget, self) + self.__index = self + + widget.progressbar = wibox.widget { + max_value = 100, + widget = wibox.widget.progressbar, + paddings = beautiful.dpi(2), + color = beautiful.color.bar.active, + background_color = beautiful.color.transparent, + border_color = beautiful.color.bar.active, + border_width = beautiful.dpi(1), + margins = beautiful.dpi(3) + } + + widget.rotator = wibox.widget { + widget.progressbar, + forced_width = beautiful.dpi(15), + direction = "east", + layout = wibox.container.rotate, + } + + widget.widget = wibox.widget { + { + { -- Right space + widget = wibox.widget.separator, + color = beautiful.color.transparent, + forced_width = beautiful.dpi(3) + }, + { + widget.rotator, + top = beautiful.dpi(2), + bottom = beautiful.dpi(2), + layout = wibox.container.margin, + }, + { -- Left space + widget = wibox.widget.separator, + color = beautiful.color.transparent, + forced_width = beautiful.dpi(3) + }, + + layout = wibox.layout.align.horizontal, + }, + layout = wibox.container.background, + } + + widget.tooltip = awful.tooltip { + objects = { widget.widget }, + text = "" + } + + widget.widget:connect_signal("mouse::enter", function(result) + widget.widget.bg = beautiful.color.bar.hover_bg + end) + + widget.widget:connect_signal("mouse::leave", function(result) + widget.widget.bg = beautiful.color.transparent + end) + + return widget +end + +return P diff --git a/classes/init.lua b/classes/init.lua index 5fd2607..0886da5 100644 --- a/classes/init.lua +++ b/classes/init.lua @@ -1,4 +1,5 @@ return { Backlight = require("classes/backlight"), - Volume = require("classes/volume") + Volume = require("classes/volume"), + Battery = require("classes/battery"), } diff --git a/desktop/init.lua b/desktop/init.lua index b869115..75e6a91 100755 --- a/desktop/init.lua +++ b/desktop/init.lua @@ -46,10 +46,6 @@ local desktop = { } } - -if conf.battery_enabled then - desktop.widgets.battery = require("desktop.widgets.battery") -end if conf.mpc_enabled then desktop.widgets.mpc = require("desktop.widgets.mpc") end @@ -178,7 +174,7 @@ awful.screen.connect_for_each_screen( desktop.widgets.textclock, desktop.widgets.space(8), - desktop.widgets.battery, + batt.widget.widget, bck.widget.widget, vol.widget.widget, desktop.widgets.space(8), diff --git a/desktop/widgets/battery.lua b/desktop/widgets/battery.lua deleted file mode 100755 index feae5f5..0000000 --- a/desktop/widgets/battery.lua +++ /dev/null @@ -1,214 +0,0 @@ -local battery = {} - --- Percentages to warn at --- (must be in order least -> greatest) -battery.warnings = { - 5, 10, 25, 50 -} - -battery.warninglog = {} - -for i=1, #battery.warnings do - battery.warninglog[i] = false -end - -battery.image_path = beautiful.icons.battery.missing -battery.icon = wibox.widget { - image = beautiful.icons.battery.missing, - resize = true, - widget = wibox.widget.imagebox, -} - - -battery.progressbar = wibox.widget { - max_value = 100, - widget = wibox.widget.progressbar, - paddings = beautiful.dpi(2), - color = beautiful.color.bar.active, - background_color = beautiful.color.transparent, - border_color = beautiful.color.bar.active, - border_width = beautiful.dpi(1), - margins = beautiful.dpi(3) -} - -battery.arc = wibox.widget { - { - battery.icon, - top = beautiful.dpi(1), - bottom = beautiful.dpi(1), - layout = wibox.container.margin, - }, - max_value = 100, - thickness = beautiful.dpi(4), - start_angle = 4.71238898, -- 2pi*3/4 - --forced_height = beautiful.dpi(16), - --forced_width = beautiful.dpi(16), - colors = {"#27D4CC", "#00446B"}, - bg = "#FFFFFF30", - paddings = beautiful.dpi(2), - widget = wibox.container.arcchart -} - - -battery.rotator = wibox.widget { - battery.progressbar, - forced_width = beautiful.dpi(15), - direction = "east", - layout = wibox.container.rotate, -} - - -battery.widget = wibox.widget { - { - { -- Right space - widget = wibox.widget.separator, - color = beautiful.color.transparent, - forced_width = beautiful.dpi(3) - }, - { - battery.arc, - top = beautiful.dpi(2), - bottom = beautiful.dpi(2), - layout = wibox.container.margin, - }, - { -- Left space - widget = wibox.widget.separator, - color = beautiful.color.transparent, - forced_width = beautiful.dpi(3) - }, - - layout = wibox.layout.align.horizontal, - }, - layout = wibox.container.background, -} - -battery.widget:connect_signal("mouse::enter", function(result) - battery.widget.bg = beautiful.color.bar.hover_bg -end) - -battery.widget:connect_signal("mouse::leave", function(result) - battery.widget.bg = beautiful.color.transparent -end) - -battery.update = function(stdout) - local batpec = string.match(stdout, "(%d?%d?%d)%%") - batpec = tonumber(string.format("% 3d", batpec)) - - local discharging = string.match(stdout, "discharging") or false - - -- Handle low power notifications - if discharging then - for i=1, #battery.warnings do - v = battery.warnings[i] - if (batpec <= v) and (not battery.warninglog[i]) then - battery.warninglog[i] = true - - naughty.notify({ - title = "Low power", - text = "Battery is at " .. tostring(batpec) .. "%", - icon = beautiful.icons.battery.caution, - - timeout = 5, - ignore_suspend = true, - - border_color = beautiful.color.battery.danger, - preset = beautiful.notification_templates.bottom_right - }) - break - end - end - else - for i=1, #battery.warnings do - if (batpec >= battery.warnings[i]) then - battery.warninglog[i] = false - end - end - end - - - battery.progressbar.value = batpec - battery.arc.value = batpec - - if batpec > 60 then - battery.progressbar.color = beautiful.color.battery.good - elseif batpec > 40 then - battery.progressbar.color = beautiful.color.battery.low - elseif batpec <= 40 then - battery.progressbar.color = beautiful.color.battery.danger - end - - - battery.image_path = beautiful.icons.battery.missing - -- Set current battery icon - if (not discharging) then - if batpec > 80 then battery.image_path = beautiful.icons.battery.charging.full - elseif batpec > 60 then battery.image_path = beautiful.icons.battery.charging.good - elseif batpec > 40 then battery.image_path = beautiful.icons.battery.charging.low - elseif batpec > 20 then battery.image_path = beautiful.icons.battery.charging.caution - elseif batpec <= 20 then battery.image_path = beautiful.icons.battery.charging.empty end - else - if batpec > 80 then battery.image_path = beautiful.icons.battery.full - elseif batpec > 60 then battery.image_path = beautiful.icons.battery.good - elseif batpec > 40 then battery.image_path = beautiful.icons.battery.low - elseif batpec > 20 then battery.image_path = beautiful.icons.battery.caution - elseif batpec <= 20 then battery.image_path = beautiful.icons.battery.empty end - end - battery.icon.image = battery.image_path - - if (not discharging) and (batpec > 90) then - battery.progressbar.border_color = beautiful.color.battery.good - elseif (discharging) and (batpec <= 25) then - battery.progressbar.border_color = beautiful.color.battery.danger - else - battery.progressbar.border_color = beautiful.color.bar.active - end - - if discharging then - battery.rotator.direction = "east" - else - battery.rotator.direction = "west" - end -end - -battery.readupdate = function() - bin.battery.status( - function(stdout, stderr, exitreason, exitcode) - battery.update(stdout) - end - ) -end - - -battery.widget:connect_signal("button::press", - function(_, _, _, button, mods) - if (button == 1) then - bin.battery.status( - function(stdout, stderr, exitreason, exitcode) - local batpec = string.match(stdout, "(%d?%d?%d)%%") -- (\d?\d?\d)\%) - local batstat = string.match(stdout, "discharging") or false - - if batstat then - batstat = "Discharging, " - else - batstat = "Charging, " - end - - local out = naughty.notify({ - title = "Battery:", - text = batstat .. batpec .. "%", - icon = battery.image_path, - replaces_id = battery.notid, - ignore_suspend = true, - - preset = beautiful.notification_templates.bottom_right - }) - battery.notid = out.id - end - ) - end - end -) - -bin.battery.watch(10, function(_, stdout) battery.update(stdout) end, battery.widget) - -return battery.widget diff --git a/rc.lua b/rc.lua index 6e4ab40..cc78f5d 100755 --- a/rc.lua +++ b/rc.lua @@ -40,6 +40,7 @@ beautiful.init(require("theme")) classes = require("classes") vol = classes.Volume{pa_sink = conf.pamixer_sink} bck = classes.Backlight{} +batt = classes.Battery{} desktop = require("desktop")