old school music tracker
at dev 204 lines 4.9 kB view raw
1use std::ops::{Add, RangeInclusive}; 2 3/// font size in pixel. font is a square 4pub const FONT_SIZE: u8 = 8; 5pub const FONT_SIZE16: u16 = FONT_SIZE as u16; 6/// window size in characters 7pub const WINDOW_SIZE_CHARS: (u8, u8) = (80, 50); 8/// window size in pixel 9pub const WINDOW_SIZE: (u16, u16) = ( 10 // TODO: use from once const traits are available 11 FONT_SIZE16 * WINDOW_SIZE_CHARS.0 as u16, 12 FONT_SIZE16 * WINDOW_SIZE_CHARS.1 as u16, 13); 14 15/// CharRect as well as PixelRect uses all values inclusive, meaning the borders are included 16#[derive(Debug, Clone, Copy)] 17pub struct CharRect { 18 top: u8, 19 bot: u8, 20 left: u8, 21 right: u8, 22} 23 24impl CharRect { 25 /// row 11 is reserved for the page title. The page shouldn't draw on it 26 pub const PAGE_AREA: Self = Self::new(12, WINDOW_SIZE_CHARS.1 - 1, 0, WINDOW_SIZE_CHARS.0 - 1); 27 pub const HEADER_AREA: Self = Self::new(0, 10, 0, WINDOW_SIZE_CHARS.0 - 1); 28 29 pub const fn new(top: u8, bot: u8, left: u8, right: u8) -> Self { 30 assert!(top <= bot, "top needs to be smaller than bot"); 31 assert!(left <= right, "left needs to be smaller than right"); 32 assert!(bot < WINDOW_SIZE_CHARS.1, "lower than window bounds"); 33 assert!(right < WINDOW_SIZE_CHARS.0, "right out of window bounds"); 34 35 Self { 36 top, 37 bot, 38 left, 39 right, 40 } 41 } 42 43 pub const fn top(self) -> u8 { 44 self.top 45 } 46 pub const fn bot(self) -> u8 { 47 self.bot 48 } 49 pub const fn right(self) -> u8 { 50 self.right 51 } 52 pub const fn left(self) -> u8 { 53 self.left 54 } 55 56 pub const fn top_left(self) -> CharPosition { 57 CharPosition { 58 x: self.left, 59 y: self.top, 60 } 61 } 62 63 pub const fn width(self) -> u8 { 64 self.right - self.left 65 } 66 67 pub const fn height(self) -> u8 { 68 self.bot - self.top 69 } 70} 71 72impl From<CharPosition> for CharRect { 73 fn from(value: CharPosition) -> Self { 74 Self::new(value.y, value.y, value.x, value.x) 75 } 76} 77 78#[cfg(feature = "accesskit")] 79impl From<CharRect> for accesskit::Rect { 80 fn from(value: CharRect) -> Self { 81 accesskit::Rect { 82 x0: value.left as f64, 83 y0: value.top as f64, 84 x1: value.right as f64, 85 y1: value.bot as f64, 86 } 87 } 88} 89 90/// PixelRect as well as CharRect uses all values inclusive, meaning the borders are included 91#[derive(Debug, Clone, Copy)] 92pub struct PixelRect { 93 top: u16, 94 bot: u16, 95 right: u16, 96 left: u16, 97} 98 99impl PixelRect { 100 pub const fn new(top: u16, bot: u16, right: u16, left: u16) -> Self { 101 assert!(top <= bot, "top needs to be smaller than bot"); 102 assert!(left <= right, "left needs to be smaller than right"); 103 assert!(bot < WINDOW_SIZE.1, "lower than window bounds"); 104 assert!(right < WINDOW_SIZE.0, "right out of window bounds"); 105 106 Self { 107 top, 108 bot, 109 right, 110 left, 111 } 112 } 113 114 pub const fn vertical_range(&self) -> RangeInclusive<u16> { 115 RangeInclusive::new(self.top, self.bot) 116 } 117 118 pub const fn horizontal_range(&self) -> RangeInclusive<u16> { 119 RangeInclusive::new(self.left, self.right) 120 } 121 122 pub const fn top(&self) -> u16 { 123 self.top 124 } 125 126 pub const fn bot(&self) -> u16 { 127 self.bot 128 } 129 130 pub const fn right(&self) -> u16 { 131 self.right 132 } 133 134 pub const fn left(&self) -> u16 { 135 self.left 136 } 137} 138 139impl From<CharRect> for PixelRect { 140 fn from(value: CharRect) -> Self { 141 Self::new( 142 u16::from(value.top) * FONT_SIZE16, 143 u16::from(value.bot) * FONT_SIZE16 + FONT_SIZE16 - 1, 144 u16::from(value.right) * FONT_SIZE16 + FONT_SIZE16 - 1, 145 u16::from(value.left) * FONT_SIZE16, 146 ) 147 } 148} 149 150impl From<CharPosition> for PixelRect { 151 fn from(value: CharPosition) -> Self { 152 Self::from(CharRect::from(value)) 153 } 154} 155 156#[derive(Debug, Clone, Copy)] 157pub struct CharPosition { 158 x: u8, 159 y: u8, 160} 161 162impl CharPosition { 163 #[track_caller] 164 pub const fn new(x: u8, y: u8) -> Self { 165 assert!(y < WINDOW_SIZE_CHARS.1); 166 assert!(x < WINDOW_SIZE_CHARS.0); 167 168 Self { x, y } 169 } 170 171 pub const fn x(&self) -> u8 { 172 self.x 173 } 174 175 pub const fn y(&self) -> u8 { 176 self.y 177 } 178} 179 180impl Add for CharPosition { 181 type Output = Self; 182 183 #[track_caller] 184 fn add(self, rhs: Self) -> Self::Output { 185 Self::new(self.x + rhs.x, self.y + rhs.y) 186 } 187} 188 189impl Add<(u8, u8)> for CharPosition { 190 type Output = Self; 191 192 #[track_caller] 193 fn add(self, rhs: (u8, u8)) -> Self::Output { 194 Self::new(self.x + rhs.0, self.y + rhs.1) 195 } 196} 197 198// impl Mul<usize> for CharPosition { 199// type Output = Self; 200 201// fn mul(self, rhs: usize) -> Self::Output { 202// Self::new(self.x * rhs, self.y * rhs) 203// } 204// }