widgets.rs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. use crate::window::Size;
  2. use pango::LayoutExt;
  3. #[derive(Debug,Clone,Copy)]
  4. pub enum Located {
  5. FromLeft(i32),
  6. FromRight(i32),
  7. }
  8. pub struct Config<'r> {
  9. pub left: Vec<&'r Widget>,
  10. pub right: Vec<&'r Widget>,
  11. }
  12. impl<'r> Config<'r> {
  13. pub fn draw(&self, d: &Drawing) {
  14. let mut offset = 10;
  15. for w in self.left.iter() {
  16. offset += 10 + w.draw(d, Located::FromLeft(offset));
  17. }
  18. offset = 10;
  19. for w in self.right.iter() {
  20. offset += 10 + w.draw(d, Located::FromRight(offset));
  21. }
  22. }
  23. }
  24. impl Located {
  25. fn draw_text(&self, d: &Drawing, msg: &str) -> i32 {
  26. d.lyt.set_text(msg);
  27. let (w, _) = d.lyt.get_size();
  28. d.ctx.move_to(self.target_x(d, w / pango::SCALE), 4.0);
  29. pangocairo::functions::show_layout(d.ctx, d.lyt);
  30. w / pango::SCALE
  31. }
  32. fn target_x(&self, d: &Drawing, w: i32) -> f64 {
  33. match self {
  34. Located::FromLeft(x) => *x as f64,
  35. Located::FromRight(x) => (d.size.wd - (x + w)) as f64,
  36. }
  37. }
  38. }
  39. pub struct Drawing<'t> {
  40. pub ctx: &'t cairo::Context,
  41. pub lyt: &'t pango::Layout,
  42. pub size: Size,
  43. }
  44. pub trait Widget {
  45. fn draw(&self, d: &Drawing, loc: Located) -> i32;
  46. }
  47. #[derive(Debug)]
  48. pub struct Time {
  49. fmt: String,
  50. }
  51. impl Time {
  52. pub fn new() -> Time {
  53. Time {
  54. fmt: format!("%a %b %d %H:%M")
  55. }
  56. }
  57. }
  58. impl Widget for Time {
  59. fn draw(&self, d: &Drawing, loc: Located) -> i32 {
  60. let now = chrono::Local::now();
  61. loc.draw_text(d, &format!("{}", &now.format(&self.fmt)))
  62. }
  63. }
  64. #[derive(Debug)]
  65. pub struct Text<'t> {
  66. text: &'t str,
  67. }
  68. impl<'t> Text<'t> {
  69. pub fn new(text: &str) -> Text {
  70. Text { text }
  71. }
  72. }
  73. impl<'t> Widget for Text<'t> {
  74. fn draw(&self, d: &Drawing, loc: Located) -> i32 {
  75. loc.draw_text(d, &self.text)
  76. }
  77. }
  78. pub struct SmallBox;
  79. impl Widget for SmallBox {
  80. fn draw(&self, d: &Drawing, loc: Located) -> i32 {
  81. let sz = d.size.ht - 8;
  82. let x = loc.target_x(d, sz);
  83. d.ctx.rectangle(x, 4.0, sz as f64, sz as f64);
  84. d.ctx.fill();
  85. sz
  86. }
  87. }
  88. pub struct Battery {
  89. file_list: Vec<std::path::PathBuf>,
  90. }
  91. impl Battery {
  92. pub fn new() -> Result<Battery, failure::Error> {
  93. use std::fs;
  94. let mut batteries = Vec::new();
  95. for entry in fs::read_dir("/sys/class/power_supply")? {
  96. let e = entry?;
  97. if e.file_name().to_string_lossy().starts_with("BAT") {
  98. let mut path = e.path();
  99. path.push("capacity");
  100. batteries.push(path);
  101. }
  102. }
  103. Ok(Battery {
  104. file_list: batteries,
  105. })
  106. }
  107. fn read_status(&self) -> Result<f64, failure::Error> {
  108. let charges: Result<Vec<i32>, failure::Error> =
  109. self.file_list.iter().map(|path| {
  110. Ok(std::fs::read_to_string(path)?.trim().parse()?)
  111. }).collect();
  112. let charges = charges?;
  113. let len = charges.len() as f64;
  114. let sum: i32 = charges.into_iter().sum();
  115. Ok(sum as f64 / len / 100.0)
  116. }
  117. }
  118. impl Widget for Battery {
  119. fn draw(&self, d: &Drawing, loc: Located) -> i32 {
  120. let amt = self.read_status().unwrap();
  121. let sz = d.size.ht - 8;
  122. let x = loc.target_x(d, sz);
  123. if amt < 0.1 {
  124. d.ctx.set_source_rgb(1.0, 0.0, 0.0);
  125. } else if amt < 0.5 {
  126. d.ctx.set_source_rgb(1.0, 1.0, 0.0);
  127. } else {
  128. d.ctx.set_source_rgb(0.0, 1.0, 0.5);
  129. }
  130. d.ctx.rectangle(x, 8.0, sz as f64 * amt, sz as f64 - 8.0);
  131. d.ctx.fill();
  132. d.ctx.set_source_rgb(1.0, 1.0, 1.0);
  133. d.ctx.rectangle(x, 8.0, sz as f64, sz as f64 - 8.0);
  134. d.ctx.stroke();
  135. sz
  136. }
  137. }