mirror of
https://github.com/jtgans/g13gui.git
synced 2025-06-19 16:03:49 -04:00
clock: Add 24-hour toggle, load, ram graphs
This adds a ton of new functionality to the clock widget, and exercises the bitwidgets widgets a bit more. This adds a new button widget, called a LabelWidget. These are pretty unsurprising -- they're just a label inside of a button slot in the buttonbar. They do give us the ability to toggle and add "more" glyphs in the button for more flexibility in the buttonbar. - Make Clock toggle between 12 and 24 hour clock modes. - Add CPU load and RAM load histograms. - Create a new button type, LabelButton. - Create a new widget, the Graph, which shows a histogram of values over time. - Make Button not assign values by way of accessors in the constructor. - Make Label actually dynamically change its bounds based upon properties.
This commit is contained in:
parent
d8fa49c1ed
commit
1212ce91de
@ -1,15 +1,26 @@
|
||||
import gi
|
||||
import time
|
||||
import enum
|
||||
import psutil
|
||||
|
||||
from g13gui.applet.applet import Applet
|
||||
from g13gui.applet.applet import Buttons
|
||||
from g13gui.applet.applet import RunApplet
|
||||
from g13gui.bitwidgets.label import Label
|
||||
from g13gui.bitwidgets.fonts import Fonts
|
||||
from g13gui.bitwidgets.button import LabelButton
|
||||
from g13gui.bitwidgets.graph import Graph
|
||||
from g13gui.bitwidgets import DISPLAY_WIDTH
|
||||
|
||||
gi.require_version('GLib', '2.0')
|
||||
from gi.repository import GLib
|
||||
|
||||
|
||||
class ClockMode(enum.Enum):
|
||||
HOUR_12 = 1
|
||||
HOUR_24 = 2
|
||||
|
||||
|
||||
class ClockApplet(Applet):
|
||||
NAME = 'Clock'
|
||||
|
||||
@ -20,22 +31,84 @@ class ClockApplet(Applet):
|
||||
self._timeLabel.showAll()
|
||||
self.screen.addChild(self._timeLabel)
|
||||
|
||||
self._updateTimeLabel()
|
||||
self._modeButtons = {
|
||||
ClockMode.HOUR_12: LabelButton('12 hour'),
|
||||
ClockMode.HOUR_24: LabelButton('24 hour')
|
||||
}
|
||||
self._clockMode = ClockMode.HOUR_24
|
||||
self._onModeSwitch()
|
||||
|
||||
def _updateTimeLabel(self):
|
||||
self._loadGraphToggle = LabelButton('Load', isToggleable=True)
|
||||
self._ramGraphToggle = LabelButton('RAM', isToggleable=True)
|
||||
self.screen.buttonBar.addChild(self._loadGraphToggle)
|
||||
self.screen.buttonBar.addChild(self._ramGraphToggle)
|
||||
self.screen.buttonBar.showAll()
|
||||
|
||||
self._loadGraph = Graph(1, 18,
|
||||
DISPLAY_WIDTH // 2 - 5, 12)
|
||||
self.screen.addChild(self._loadGraph)
|
||||
|
||||
self._ramGraph = Graph(DISPLAY_WIDTH // 2 + 5, 18,
|
||||
DISPLAY_WIDTH // 2 - 7, 12)
|
||||
self.screen.addChild(self._ramGraph)
|
||||
|
||||
self._update()
|
||||
|
||||
def _update(self):
|
||||
(tm_year, tm_month, tm_mday, tm_hour,
|
||||
tm_min, tm_sec, tm_wday, tm_yday, tm_isdst) = time.localtime()
|
||||
self._timeLabel.text = '%d:%0.2d:%0.2d' % (tm_hour, tm_min, tm_sec)
|
||||
ampm = ''
|
||||
|
||||
if self._clockMode == ClockMode.HOUR_12:
|
||||
ampm = ' AM'
|
||||
if tm_hour >= 12:
|
||||
ampm = ' PM'
|
||||
if tm_hour > 12:
|
||||
tm_hour -= 12
|
||||
|
||||
self._timeLabel.text = '%d:%0.2d:%0.2d%s' % (
|
||||
tm_hour, tm_min, tm_sec, ampm)
|
||||
|
||||
(w, h) = self._timeLabel.bounds
|
||||
x = (DISPLAY_WIDTH // 2) - (w // 2)
|
||||
self._timeLabel.position = (x, 0)
|
||||
|
||||
self._loadGraph.addValue(psutil.cpu_percent())
|
||||
self._ramGraph.addValue(psutil.virtual_memory().percent / 100)
|
||||
|
||||
def _pushTime(self):
|
||||
self._updateTimeLabel()
|
||||
self._update()
|
||||
self.maybePresentScreen()
|
||||
return self.screen.visible
|
||||
|
||||
def onShown(self, timestamp):
|
||||
self._updateTimeLabel()
|
||||
self._update()
|
||||
GLib.timeout_add_seconds(1, self._pushTime)
|
||||
|
||||
def onUpdateScreen(self):
|
||||
self._update()
|
||||
|
||||
def _onModeSwitch(self):
|
||||
if self._clockMode == ClockMode.HOUR_12:
|
||||
self._clockMode = ClockMode.HOUR_24
|
||||
button = self._modeButtons[ClockMode.HOUR_12]
|
||||
elif self._clockMode == ClockMode.HOUR_24:
|
||||
self._clockMode = ClockMode.HOUR_12
|
||||
button = self._modeButtons[ClockMode.HOUR_24]
|
||||
|
||||
button.show()
|
||||
self.screen.buttonBar.setButton(0, button)
|
||||
|
||||
def onKeyReleased(self, timestamp, key):
|
||||
if key == Buttons.L1:
|
||||
self._onModeSwitch()
|
||||
elif key == Buttons.L2:
|
||||
self._loadGraphToggle.toggle()
|
||||
self._loadGraph.visible = self._loadGraphToggle.isOn
|
||||
elif key == Buttons.L3:
|
||||
self._ramGraphToggle.toggle()
|
||||
self._ramGraph.visible = self._ramGraphToggle.isOn
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
RunApplet(ClockApplet)
|
||||
|
@ -1,14 +1,18 @@
|
||||
from builtins import property
|
||||
|
||||
from g13gui.bitwidgets.widget import Widget
|
||||
from g13gui.bitwidgets.label import Label
|
||||
from g13gui.bitwidgets.glyph import Glyph
|
||||
from g13gui.bitwidgets.glyph import Glyphs
|
||||
from g13gui.bitwidgets.rectangle import Rectangle
|
||||
from g13gui.bitwidgets.fonts import Fonts
|
||||
from g13gui.observer.subject import ChangeType
|
||||
|
||||
|
||||
class Button(Widget):
|
||||
def __init__(self, glyph, fill=True):
|
||||
Widget.__init__(self)
|
||||
|
||||
self._rect = Rectangle(*self.position, *self.bounds, fill=False)
|
||||
self._rect.show()
|
||||
self.addChild(self._rect)
|
||||
@ -60,3 +64,94 @@ class Button(Widget):
|
||||
@glyph.setter
|
||||
def glyph(self, glyph):
|
||||
self.setProperty('glyph', glyph)
|
||||
|
||||
|
||||
class LabelButton(Button):
|
||||
def __init__(self, text, isToggleable=False, hasMore=False, fill=True):
|
||||
Button.__init__(self, Glyphs.BLANK, fill)
|
||||
|
||||
self._isOn = False
|
||||
self._isToggleable = isToggleable
|
||||
self._hasMore = hasMore
|
||||
|
||||
self.removeChild(self._glyph)
|
||||
self._glyph = Label(*self.position, text, font=Fonts.TINY)
|
||||
self._glyph.show()
|
||||
self.addChild(self._glyph)
|
||||
|
||||
self._moreGlyph = Glyph(0, 0, Glyphs.CHEVRON_RIGHT)
|
||||
self.addChild(self._moreGlyph)
|
||||
self._toggleGlyph = Glyph(0, 0, Glyphs.BOX)
|
||||
self.addChild(self._toggleGlyph)
|
||||
self.updateGlyphs()
|
||||
|
||||
def updateGlyphs(self):
|
||||
if self.isOn:
|
||||
self._toggleGlyph.glyph = Glyphs.FILLED_BOX
|
||||
else:
|
||||
self._toggleGlyph.glyph = Glyphs.BOX
|
||||
|
||||
self._moreGlyph.visible = self.hasMore
|
||||
self._toggleGlyph.visible = self.isToggleable
|
||||
|
||||
def _updatePositionAndBounds(self, subject, changeType, key, data):
|
||||
super()._updatePositionAndBounds(subject, changeType, key, data)
|
||||
|
||||
(x, y) = self.position
|
||||
(w, h) = self.bounds
|
||||
(glyphW, glyphH) = self._moreGlyph.bounds
|
||||
|
||||
moreX = x + w - glyphW - 1
|
||||
moreY = y + (h // 2) - (glyphH // 2)
|
||||
self._moreGlyph.position = (moreX, moreY)
|
||||
|
||||
toggleX = x + 1
|
||||
toggleY = y + (h // 2) - (glyphH // 2)
|
||||
self._toggleGlyph.position = (toggleX, toggleY)
|
||||
|
||||
(labelX, labelY) = self._glyph.position
|
||||
labelY += 1
|
||||
self._glyph.position = (labelX, labelY)
|
||||
|
||||
@property
|
||||
def isToggleable(self):
|
||||
return self._isToggleable
|
||||
|
||||
@isToggleable.setter
|
||||
def isToggleable(self, value):
|
||||
self.setProperty('isToggleable', value)
|
||||
self.updateGlyphs()
|
||||
|
||||
@property
|
||||
def isOn(self):
|
||||
return self._isOn
|
||||
|
||||
@isOn.setter
|
||||
def isOn(self, value):
|
||||
self.setProperty('isOn', value)
|
||||
self.updateGlyphs()
|
||||
|
||||
@property
|
||||
def isOff(self):
|
||||
return not self._isOn
|
||||
|
||||
def toggle(self):
|
||||
self.setProperty('isOn', not self.isOn)
|
||||
self.updateGlyphs()
|
||||
|
||||
@property
|
||||
def hasMore(self):
|
||||
return self._hasMore
|
||||
|
||||
@hasMore.setter
|
||||
def hasMore(self, value):
|
||||
self.setProperty('hasMore', value)
|
||||
self.updateGlyphs()
|
||||
|
||||
@property
|
||||
def text(self):
|
||||
return self._glyph.text
|
||||
|
||||
@text.setter
|
||||
def text(self, text):
|
||||
self._glyph.text = text
|
||||
|
@ -5,8 +5,9 @@ from g13gui.bitwidgets.display import Display
|
||||
from g13gui.bitwidgets.x11displaydevice import X11DisplayDevice
|
||||
from g13gui.bitwidgets.screen import Screen
|
||||
from g13gui.bitwidgets.button import Button
|
||||
from g13gui.bitwidgets.button import Glyphs
|
||||
from g13gui.bitwidgets.button import Glyph
|
||||
from g13gui.bitwidgets.button import LabelButton
|
||||
from g13gui.bitwidgets.glyph import Glyphs
|
||||
from g13gui.bitwidgets.glyph import Glyph
|
||||
from g13gui.bitwidgets.label import Label
|
||||
from g13gui.bitwidgets.fonts import Fonts
|
||||
|
||||
@ -72,7 +73,7 @@ class ButtonTests(unittest.TestCase):
|
||||
|
||||
def testLabelButton(self):
|
||||
self.dd.name = 'testLabelButton'
|
||||
testButton = Label(0, 0, "Test", font=Fonts.TINY)
|
||||
testButton = LabelButton("Test")
|
||||
self.screen.buttonBar.addChild(testButton)
|
||||
self.screen.buttonBar.showAll()
|
||||
self.screen.nextFrame()
|
||||
|
59
g13gui/bitwidgets/graph.py
Normal file
59
g13gui/bitwidgets/graph.py
Normal file
@ -0,0 +1,59 @@
|
||||
from builtins import property
|
||||
|
||||
from g13gui.bitwidgets.widget import Widget
|
||||
from g13gui.bitwidgets.rectangle import Rectangle
|
||||
|
||||
|
||||
class Graph(Widget):
|
||||
def __init__(self, x, y, w, h):
|
||||
Widget.__init__(self)
|
||||
|
||||
self._rect = Rectangle(x, y, w, h, fill=True)
|
||||
self.addChild(self._rect)
|
||||
|
||||
self.position = (x, y)
|
||||
self.bounds = (w, h)
|
||||
|
||||
self._timeseries = [0] * w
|
||||
|
||||
def addValue(self, value):
|
||||
if value > 1 or value < 0:
|
||||
value = 0
|
||||
|
||||
(w, h) = self.bounds
|
||||
self._timeseries.append(value)
|
||||
if len(self._timeseries) > w:
|
||||
del self._timeseries[0]
|
||||
|
||||
@property
|
||||
def bounds(self):
|
||||
return self._bounds
|
||||
|
||||
@bounds.setter
|
||||
def bounds(self, wh):
|
||||
self.setProperty('bounds', wh)
|
||||
self._rect.bounds = wh
|
||||
self._timeseries = [0] * wh[0]
|
||||
|
||||
def draw(self, ctx):
|
||||
super().draw(ctx)
|
||||
|
||||
(x, y) = self.position
|
||||
(w, h) = self.bounds
|
||||
(t, b, l, r) = (y, y + h, x, x + w)
|
||||
tl = (l, t)
|
||||
bl = (l, b)
|
||||
br = (r, b)
|
||||
|
||||
if self.visible:
|
||||
ctx.line(tl+bl, fill=1)
|
||||
ctx.line(bl+br, fill=1)
|
||||
|
||||
for idx, value in enumerate(self._timeseries):
|
||||
xoffs = idx + x
|
||||
scaledValue = int(value * h)
|
||||
yoffs = b - scaledValue
|
||||
|
||||
points = (xoffs, yoffs,
|
||||
xoffs, b)
|
||||
ctx.line(points, fill=1)
|
@ -21,14 +21,14 @@ class Label(Widget):
|
||||
align=Alignment.LEFT,
|
||||
strokeWidth=0):
|
||||
Widget.__init__(self)
|
||||
self.position = (x, y)
|
||||
self.text = text
|
||||
self.font = font
|
||||
self.fill = fill
|
||||
self.spacing = spacing
|
||||
self.align = align
|
||||
self.strokeWidth = strokeWidth
|
||||
self.bounds = FontManager.getFont(self.font).getsize(self.text)
|
||||
self._position = (x, y)
|
||||
self._text = text
|
||||
self._font = font
|
||||
self._fill = fill
|
||||
self._spacing = spacing
|
||||
self._align = align
|
||||
self._strokeWidth = strokeWidth
|
||||
self._bounds = FontManager.getFont(self.font).getsize(self.text)
|
||||
|
||||
def draw(self, ctx):
|
||||
if self._visible:
|
||||
@ -62,14 +62,17 @@ class Label(Widget):
|
||||
@text.setter
|
||||
def text(self, text):
|
||||
self.setProperty('text', text)
|
||||
self.bounds = FontManager.getFont(self.font).getsize(self.text)
|
||||
|
||||
@font.setter
|
||||
def font(self, font):
|
||||
self.setProperty('font', font)
|
||||
self.bounds = FontManager.getFont(self.font).getsize(self.text)
|
||||
|
||||
@spacing.setter
|
||||
def spacing(self, spacing):
|
||||
self.setProperty('spacing', spacing)
|
||||
self.bounds = FontManager.getFont(self.font).getsize(self.text)
|
||||
|
||||
@align.setter
|
||||
def align(self, align):
|
||||
|
Loading…
Reference in New Issue
Block a user