widget.rs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. use std::io::{Stdout, Write};
  2. use termion::{cursor, raw::RawTerminal};
  3. use crate::Result;
  4. #[derive(Clone)]
  5. pub struct Widget {
  6. pub width: usize,
  7. pub height: usize,
  8. pub x: usize,
  9. pub y: usize,
  10. title: String,
  11. }
  12. impl Widget {
  13. pub fn new(width: usize, height: usize, x: usize, y: usize, title: String) -> Result<Widget> {
  14. Ok(Widget { width, height, x, y, title })
  15. }
  16. pub fn print(
  17. &self,
  18. stdout: &mut RawTerminal<Stdout>,
  19. x: usize,
  20. y: usize,
  21. text: &str,
  22. ) -> Result<()> {
  23. write!(stdout, "{}{}", cursor::Goto(1 + x as u16, 1 + y as u16), text)?;
  24. Ok(())
  25. }
  26. pub fn print_border(&self, stdout: &mut RawTerminal<Stdout>) -> Result<()> {
  27. let x = self.x;
  28. let y = self.y;
  29. let width = self.width;
  30. let height = self.height;
  31. let hline = "─";
  32. let vline = "│";
  33. let topleftcorner = "┌";
  34. let toprightcorner = "┐";
  35. let downleftcorner = "└";
  36. let downrightcorner = "┘";
  37. self.print(stdout, x, y, topleftcorner)?;
  38. self.print(stdout, x, y + height, downleftcorner)?;
  39. self.print(stdout, x + width - 1, y, toprightcorner)?;
  40. self.print(stdout, x + width - 1, y + height, downrightcorner)?;
  41. for j in (y + 1)..(y + height) {
  42. self.print(stdout, x, j, vline)?;
  43. self.print(stdout, x + width - 1, j, vline)?;
  44. }
  45. for i in (x + 1)..(x + width - 1) {
  46. self.print(stdout, i, y, hline)?;
  47. self.print(stdout, i, y + height, hline)?;
  48. }
  49. Ok(())
  50. }
  51. pub fn clear_current_line(&self, stdout: &mut RawTerminal<Stdout>) -> Result<()> {
  52. let width = self.width;
  53. for i in self.x..(width - 3) {
  54. self.print(stdout, i, self.y, " ")?;
  55. }
  56. Ok(())
  57. }
  58. pub fn draw(&self, stdout: &mut RawTerminal<Stdout>) -> Result<()> {
  59. self.print_border(stdout)?;
  60. self.print(stdout, self.x + 3, self.y, &format!(" {} ", &self.title.clone()))?;
  61. Ok(())
  62. }
  63. }
  64. pub trait Layout {
  65. fn draw(
  66. &mut self,
  67. stdout: &mut RawTerminal<Stdout>,
  68. x: usize,
  69. y: usize,
  70. layout_width: usize,
  71. layout_height: usize,
  72. ) -> Result<(usize, usize)>;
  73. }
  74. pub struct VBox {
  75. widgets: Vec<Widget>,
  76. width: usize,
  77. }
  78. impl VBox {
  79. pub fn new(widgets: Vec<Widget>, width: usize) -> Self {
  80. Self { widgets, width }
  81. }
  82. }
  83. impl Layout for VBox {
  84. fn draw(
  85. &mut self,
  86. stdout: &mut RawTerminal<Stdout>,
  87. x: usize,
  88. y: usize,
  89. layout_width: usize,
  90. layout_height: usize,
  91. ) -> Result<(usize, usize)> {
  92. let len = self.widgets.len();
  93. let widget_width = layout_width / self.width;
  94. for (i, widget) in self.widgets.iter_mut().enumerate() {
  95. widget.width = widget_width - 1;
  96. widget.height = (layout_height / len) - 1;
  97. widget.x = x;
  98. widget.y = (widget.height + 1) * i + y;
  99. widget.draw(stdout)?;
  100. }
  101. Ok((widget_width, y))
  102. }
  103. }
  104. pub struct HBox {
  105. widgets: Vec<Widget>,
  106. pub height: usize,
  107. }
  108. impl HBox {
  109. pub fn new(widgets: Vec<Widget>, height: usize) -> Self {
  110. Self { widgets, height }
  111. }
  112. }
  113. impl Layout for HBox {
  114. fn draw(
  115. &mut self,
  116. stdout: &mut RawTerminal<Stdout>,
  117. x: usize,
  118. y: usize,
  119. layout_width: usize,
  120. layout_height: usize,
  121. ) -> Result<(usize, usize)> {
  122. let len = self.widgets.len();
  123. let widget_height = layout_height / self.height;
  124. for (i, widget) in self.widgets.iter_mut().enumerate() {
  125. widget.width = layout_width / len - 1;
  126. widget.height = widget_height - 1;
  127. widget.x = (widget.width + 1) * i + x;
  128. widget.y = y;
  129. widget.draw(stdout)?;
  130. }
  131. Ok((x, widget_height))
  132. }
  133. }