diff --git a/program/MainWindow.cs b/program/MainWindow.cs
index d7c98a1..2f91720 100644
--- a/program/MainWindow.cs
+++ b/program/MainWindow.cs
@@ -29,8 +29,7 @@
[UI] private Image ConnectionIcon = null; // was GtkIconView in the old glade
[UI] private Label ConnectionAlertLabel = null;
- [UI] private Image BatteryIcon = null;
- [UI] private Label BatteryLabel = null;
+ [UI] private DrawingArea BatteryArea = null;
private uint _retryTimerId;
@@ -59,6 +58,7 @@
internal SoundWindow _soundWindow;
internal MapWindow _mapWindow;
// Battery
+ private BatteryStatus _battery = new BatteryStatus();
private uint _batteryTimerId;
private const uint BatteryPollMs = 10000;
@@ -134,8 +134,8 @@
_Language.Register("LanguageLabel", LanguageLabel);
_Language.Register("LanguageToggle", LanguageToggle);
_Language.RegisterDynamic("ConnectionIcon", ConnectionIcon);
- _Language.RegisterDynamic("BatteryIcon", BatteryIcon);
- _Language.RegisterDynamic("BatteryLabel", BatteryLabel);
+ _Language.RegisterDynamic("BatteryArea", BatteryArea);
+ if (BatteryArea != null) BatteryArea.Drawn += OnBatteryDrawn;
ConnectionAlertLabel.Name = "ConnectionAlertLabel";
_Language.Register("ConnectionAlertLabel", ConnectionAlertLabel);
@@ -292,34 +292,141 @@
private void UpdateBattery()
{
- if (BatteryIcon == null) return;
+ if (BatteryArea == null) return;
- BatteryStatus b = BatteryMonitor.Read();
+ _battery = BatteryMonitor.Read();
- if (!b.Present) // desktop / dev machine — hide it entirely
+ if (!_battery.Present) // desktop / dev machine — hide it entirely
{
- BatteryIcon.Visible = false;
- if (BatteryLabel != null) BatteryLabel.Visible = false;
+ BatteryArea.Visible = false;
return;
}
- BatteryIcon.Visible = true;
- BatteryIcon.SetFromIconName(PickBatteryIcon(b), IconSize.Dnd);
+ string key = _battery.Full ? "BatteryIcon.Full"
+ : _battery.Charging ? "BatteryIcon.Charging"
+ : "BatteryIcon.Discharging";
- string key = b.Full ? "BatteryIcon.Full"
- : b.Charging ? "BatteryIcon.Charging"
- : "BatteryIcon.Discharging";
- BatteryIcon.TooltipText = _Language.Format(key, b.Percent);
+ BatteryArea.Visible = true;
+ BatteryArea.TooltipText = _Language.Format(key, _battery.Percent);
+ BatteryArea.QueueDraw();
+ }
+
+ private void OnBatteryDrawn(object o, DrawnArgs args)
+ {
+ DrawingArea area = (DrawingArea)o;
+ Cairo.Context cr = args.Cr;
- if (BatteryLabel != null)
+ double w = area.AllocatedWidth;
+ double h = area.AllocatedHeight;
+
+ Gdk.RGBA fg = area.StyleContext.GetColor(StateFlags.Normal);
+
+ double stroke = Math.Max(1.5, h * 0.07);
+ double nub = Math.Max(2.0, w * 0.055);
+ double gap = Math.Max(1.0, w * 0.02);
+
+ double bw = w - nub - gap - stroke;
+ double bh = Math.Min(h - stroke, bw * 0.52);
+ double bx = stroke / 2;
+ double by = (h - bh) / 2;
+ double r = bh * 0.20;
+
+ // shell
+ cr.LineWidth = stroke;
+ cr.SetSourceRGBA(fg.Red, fg.Green, fg.Blue, fg.Alpha);
+ RoundedRect(cr, bx, by, bw, bh, r);
+ cr.Stroke();
+
+ // terminal
+ double th = bh * 0.42;
+ cr.Rectangle(bx + bw + gap, (h - th) / 2, nub, th);
+ cr.Fill();
+
+ // level fill
+ double pad = stroke * 1.4;
+ double ix = bx + pad, iy = by + pad;
+ double iw = bw - 2 * pad, ih = bh - 2 * pad;
+ double pct = Math.Max(0, Math.Min(100, _battery.Percent));
+ double fillW = iw * (pct / 100.0);
+
+ if (fillW > 0.5)
{
- BatteryLabel.Visible = true;
- BatteryLabel.Text = b.Percent.ToString(CultureInfo.InvariantCulture) + "%";
+ double fr, fgc, fb;
+ if (!_battery.Charging && pct <= 10) { fr = 0.78; fgc = 0.16; fb = 0.16; }
+ else if (!_battery.Charging && pct <= 25) { fr = 0.93; fgc = 0.62; fb = 0.09; }
+ else { fr = 0.18; fgc = 0.65; fb = 0.31; }
- var ctx = BatteryLabel.StyleContext;
- if (b.Percent <= 15 && !b.Charging) ctx.AddClass("battery-low");
- else ctx.RemoveClass("battery-low");
+ cr.Save();
+ RoundedRect(cr, ix, iy, iw, ih, Math.Max(0, r - pad * 0.5));
+ cr.Clip();
+ cr.NewPath();
+ cr.Rectangle(ix, iy, fillW, ih);
+ cr.SetSourceRGB(fr, fgc, fb);
+ cr.Fill();
+ cr.Restore();
}
+
+ // contents: optional charging bolt + the number
+ string text = _battery.Present
+ ? _battery.Percent.ToString(CultureInfo.InvariantCulture)
+ : "--";
+
+ cr.SelectFontFace("Sans", Cairo.FontSlant.Normal, Cairo.FontWeight.Bold);
+ cr.SetFontSize(bh * 0.60);
+ Cairo.TextExtents te = cr.TextExtents(text);
+
+ double boltW = _battery.Charging ? bh * 0.36 : 0;
+ double boltG = _battery.Charging ? bh * 0.14 : 0;
+ double startX = bx + (bw - (boltW + boltG + te.Width)) / 2;
+ double tx = startX + boltW + boltG - te.XBearing;
+ double ty = by + (bh - te.Height) / 2 - te.YBearing;
+
+ System.Action paint = () =>
+ {
+ if (_battery.Charging)
+ DrawBolt(cr, startX, by + bh * 0.16, boltW, bh * 0.68);
+ cr.MoveTo(tx, ty);
+ cr.ShowText(text);
+ };
+
+ cr.Save(); // over the fill -> light
+ cr.Rectangle(ix, 0, fillW, h);
+ cr.Clip();
+ cr.SetSourceRGB(1, 1, 1);
+ paint();
+ cr.Restore();
+
+ cr.Save(); // over the empty part -> theme fg
+ cr.Rectangle(ix + fillW, 0, w, h);
+ cr.Clip();
+ cr.SetSourceRGBA(fg.Red, fg.Green, fg.Blue, fg.Alpha);
+ paint();
+ cr.Restore();
+ }
+
+ private static void RoundedRect(Cairo.Context cr, double x, double y,
+ double w, double h, double r)
+ {
+ cr.NewPath();
+ cr.Arc(x + w - r, y + r, r, -Math.PI / 2, 0);
+ cr.Arc(x + w - r, y + h - r, r, 0, Math.PI / 2);
+ cr.Arc(x + r, y + h - r, r, Math.PI / 2, Math.PI);
+ cr.Arc(x + r, y + r, r, Math.PI, 3 * Math.PI / 2);
+ cr.ClosePath();
+ }
+
+ private static void DrawBolt(Cairo.Context cr, double x, double y,
+ double w, double h)
+ {
+ cr.NewPath();
+ cr.MoveTo(x + w * 0.58, y);
+ cr.LineTo(x, y + h * 0.58);
+ cr.LineTo(x + w * 0.42, y + h * 0.58);
+ cr.LineTo(x + w * 0.32, y + h);
+ cr.LineTo(x + w, y + h * 0.40);
+ cr.LineTo(x + w * 0.56, y + h * 0.40);
+ cr.ClosePath();
+ cr.Fill();
}
private static string PickBatteryIcon(BatteryStatus b)
diff --git a/program/homepageallv7.glade b/program/homepageallv7.glade
index 5fafdb1..f97663a 100644
--- a/program/homepageallv7.glade
+++ b/program/homepageallv7.glade
@@ -81,32 +81,21 @@
4
center
-
-
- False
- False
- 0
-
-
-
-
-
- False
- False
- 1
-
-
+
+
+ False
+ False
+ 3
+
+
False
diff --git a/program/touch_friendly.css b/program/touch_friendly.css
index 207a7d8..0c4851a 100644
--- a/program/touch_friendly.css
+++ b/program/touch_friendly.css
@@ -208,4 +208,6 @@
background-color: #C62828;
padding: 10px 24px;
margin: 8px 40px;
-}
\ No newline at end of file
+}
+/* #BatteryLabel { margin-left: 4px; } */
+#BatteryLabel.battery-low { color: #c62828; font-weight: bold; }
\ No newline at end of file