label.rs 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. use macroquad::prelude::draw_text_ex;
  2. use macroquad::prelude::screen_height;
  3. use macroquad::prelude::Font;
  4. use macroquad::prelude::TextParams;
  5. use crate::utils::in_range;
  6. pub const FONT_SIZE: u16 = 16;
  7. const SPACE_BETWEEN_ROWS: f32 = 16.0;
  8. pub struct Label {
  9. raw_string: String,
  10. fitted_strings: Option<Vec<String>>,
  11. }
  12. impl Label {
  13. pub fn new(string: &str) -> Self {
  14. return Self {
  15. raw_string: string.to_owned(),
  16. fitted_strings: None,
  17. };
  18. }
  19. pub fn fit(self, width_chars: u32) -> Self {
  20. return Self {
  21. fitted_strings: Some(
  22. textwrap::wrap(&self.raw_string, width_chars as usize)
  23. .into_iter()
  24. .map(|s| s.to_string())
  25. .collect(),
  26. ),
  27. ..self
  28. };
  29. }
  30. pub fn line_count(&self) -> usize {
  31. match &self.fitted_strings {
  32. Some(v) => v.len(),
  33. None => 1,
  34. }
  35. }
  36. pub fn height(&self) -> f32 {
  37. return SPACE_BETWEEN_ROWS * self.line_count() as f32;
  38. }
  39. pub fn strings(&self) -> Vec<&str> {
  40. match &self.fitted_strings {
  41. Some(strings) => strings.into_iter().map(|s| s.as_str()).collect(),
  42. None => vec![&self.raw_string],
  43. }
  44. }
  45. pub fn draw(&self, x: f32, y: f32, font: Font) {
  46. for (i, string) in self.strings().into_iter().enumerate() {
  47. let slice = string.to_string();
  48. let i_as_f32 = i as f32;
  49. let text_y = y + i_as_f32 * SPACE_BETWEEN_ROWS;
  50. if in_range(text_y, 0.0, screen_height())
  51. || in_range(text_y + FONT_SIZE as f32, 0.0, screen_height())
  52. {
  53. draw_text_ex(
  54. &slice,
  55. x,
  56. text_y,
  57. TextParams {
  58. font,
  59. font_size: FONT_SIZE,
  60. ..Default::default()
  61. },
  62. );
  63. }
  64. }
  65. }
  66. }