1 use std::ops::{BitOr, BitXor}; 2 use super::{chtype, A_ALTCHARSET, A_BLINK, A_BOLD, A_CHARTEXT, A_DIM, A_INVIS, A_LEFTLINE}; 3 use super::{A_ITALIC, A_OVERLINE, A_REVERSE, A_RIGHTLINE, A_STRIKEOUT, A_UNDERLINE}; 4 use super::colorpair::ColorPair; 5 6 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] 7 pub enum Attribute { 8 AlternativeCharSet, 9 Bold, 10 Blink, 11 CharText, 12 Dim, 13 Leftline, 14 Invisible, 15 Italic, 16 Normal, 17 Overline, 18 Reverse, 19 Rightline, 20 Strikeout, 21 Underline, 22 } 23 24 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] 25 pub struct Attributes { 26 raw: chtype, 27 color_pair: ColorPair, 28 } 29 30 macro_rules! attribute_setter { 31 ($name:ident, $attr:ident) => { 32 pub fn $name(&mut self, enabled: bool) { 33 if enabled { 34 self.raw |= $attr; 35 } else { 36 self.raw ^= $attr; 37 } 38 } 39 }; 40 } 41 42 impl Attributes { new() -> Attributes43 pub fn new() -> Attributes { 44 Attributes { 45 raw: 0, 46 color_pair: ColorPair(0), 47 } 48 } 49 is_alternative_char_set(&self) -> bool50 pub fn is_alternative_char_set(&self) -> bool { 51 (self.raw & A_ALTCHARSET) > 0 52 } 53 attribute_setter!(set_alternative_char_set, A_ALTCHARSET); 54 is_bold(&self) -> bool55 pub fn is_bold(&self) -> bool { 56 (self.raw & A_BOLD) > 0 57 } 58 attribute_setter!(set_bold, A_BOLD); 59 is_blink(&self) -> bool60 pub fn is_blink(&self) -> bool { 61 (self.raw & A_BLINK) > 0 62 } 63 attribute_setter!(set_blink, A_BLINK); 64 is_char_text(&self) -> bool65 pub fn is_char_text(&self) -> bool { 66 (self.raw & A_CHARTEXT) > 0 67 } 68 attribute_setter!(set_char_text, A_CHARTEXT); 69 is_dim(&self) -> bool70 pub fn is_dim(&self) -> bool { 71 (self.raw & A_DIM) > 0 72 } 73 attribute_setter!(set_dim, A_DIM); 74 is_leftline(&self) -> bool75 pub fn is_leftline(&self) -> bool { 76 (self.raw & A_LEFTLINE) > 0 77 } 78 attribute_setter!(set_leftline, A_LEFTLINE); 79 is_invisible(&self) -> bool80 pub fn is_invisible(&self) -> bool { 81 (self.raw & A_INVIS) > 0 82 } 83 attribute_setter!(set_invisible, A_INVIS); 84 is_italic(&self) -> bool85 pub fn is_italic(&self) -> bool { 86 (self.raw & A_ITALIC) > 0 87 } 88 attribute_setter!(set_italic, A_ITALIC); 89 is_normal(&self) -> bool90 pub fn is_normal(&self) -> bool { 91 self.raw == 0 92 } set_normal(&mut self)93 pub fn set_normal(&mut self) { 94 self.raw = 0 95 } 96 is_overline(&self) -> bool97 pub fn is_overline(&self) -> bool { 98 (self.raw & A_OVERLINE) > 0 99 } 100 attribute_setter!(set_overline, A_OVERLINE); 101 is_reverse(&self) -> bool102 pub fn is_reverse(&self) -> bool { 103 (self.raw & A_REVERSE) > 0 104 } 105 attribute_setter!(set_reverse, A_REVERSE); 106 is_rightline(&self) -> bool107 pub fn is_rightline(&self) -> bool { 108 (self.raw & A_RIGHTLINE) > 0 109 } 110 attribute_setter!(set_rightline, A_RIGHTLINE); 111 is_strikeout(&self) -> bool112 pub fn is_strikeout(&self) -> bool { 113 (self.raw & A_STRIKEOUT) > 0 114 } 115 attribute_setter!(set_strikeout, A_STRIKEOUT); 116 is_underline(&self) -> bool117 pub fn is_underline(&self) -> bool { 118 (self.raw & A_UNDERLINE) > 0 119 } 120 attribute_setter!(set_underline, A_UNDERLINE); 121 color_pair(&self) -> ColorPair122 pub fn color_pair(&self) -> ColorPair { 123 self.color_pair 124 } set_color_pair(&mut self, color_pair: ColorPair)125 pub fn set_color_pair(&mut self, color_pair: ColorPair) { 126 let color_chtype: chtype = color_pair.into(); 127 self.raw = self.raw | color_chtype; 128 self.color_pair = color_pair; 129 } 130 } 131 132 /// Implement the | operator for adding an Attribute to Attributes 133 /// 134 /// # Example 135 /// 136 /// ``` 137 /// use pancurses::{Attribute, Attributes}; 138 /// 139 /// let mut attributes = Attributes::new(); 140 /// assert!(!attributes.is_bold()); 141 /// attributes = attributes | Attribute::Bold; 142 /// assert!(attributes.is_bold()); 143 /// ``` 144 impl BitOr<Attribute> for Attributes { 145 type Output = Attributes; 146 bitor(mut self, rhs: Attribute) -> Attributes147 fn bitor(mut self, rhs: Attribute) -> Attributes { 148 match rhs { 149 Attribute::AlternativeCharSet => self.set_alternative_char_set(true), 150 Attribute::Bold => self.set_bold(true), 151 Attribute::Blink => self.set_blink(true), 152 Attribute::CharText => self.set_char_text(true), 153 Attribute::Dim => self.set_dim(true), 154 Attribute::Leftline => self.set_leftline(true), 155 Attribute::Invisible => self.set_invisible(true), 156 Attribute::Italic => self.set_italic(true), 157 Attribute::Normal => self.set_normal(), 158 Attribute::Overline => self.set_overline(true), 159 Attribute::Reverse => self.set_reverse(true), 160 Attribute::Rightline => self.set_rightline(true), 161 Attribute::Strikeout => self.set_strikeout(true), 162 Attribute::Underline => self.set_underline(true), 163 } 164 self 165 } 166 } 167 168 /// Implement the ^ operator for disabling an Attribute from Attributes 169 /// 170 /// # Example 171 /// 172 /// ``` 173 /// use pancurses::{Attribute, Attributes}; 174 /// 175 /// let mut attributes = Attributes::from(Attribute::Bold); 176 /// assert!(attributes.is_bold()); 177 /// attributes = attributes ^ Attribute::Bold; 178 /// assert!(!attributes.is_bold()); 179 /// ``` 180 impl BitXor<Attribute> for Attributes { 181 type Output = Attributes; 182 bitxor(mut self, rhs: Attribute) -> Attributes183 fn bitxor(mut self, rhs: Attribute) -> Attributes { 184 match rhs { 185 Attribute::AlternativeCharSet => self.set_alternative_char_set(false), 186 Attribute::Bold => self.set_bold(false), 187 Attribute::Blink => self.set_blink(false), 188 Attribute::CharText => self.set_char_text(false), 189 Attribute::Dim => self.set_dim(false), 190 Attribute::Leftline => self.set_leftline(false), 191 Attribute::Invisible => self.set_invisible(false), 192 Attribute::Italic => self.set_italic(false), 193 Attribute::Normal => (), 194 Attribute::Overline => self.set_overline(false), 195 Attribute::Reverse => self.set_reverse(false), 196 Attribute::Rightline => self.set_rightline(false), 197 Attribute::Strikeout => self.set_strikeout(false), 198 Attribute::Underline => self.set_underline(false), 199 } 200 self 201 } 202 } 203 204 /// Implement the | operator for adding Attributes to Attributes 205 /// 206 /// # Example 207 /// 208 /// ``` 209 /// use pancurses::{Attribute, Attributes}; 210 /// 211 /// let mut attributes = Attributes::new() | Attribute::Bold; 212 /// let other = Attributes::new() | Attribute::Reverse; 213 /// attributes = attributes | other; 214 /// assert!(attributes.is_bold()); 215 /// assert!(attributes.is_reverse()); 216 /// assert!(!attributes.is_italic()); 217 /// ``` 218 impl BitOr for Attributes { 219 type Output = Attributes; 220 bitor(self, rhs: Attributes) -> Attributes221 fn bitor(self, rhs: Attributes) -> Attributes { 222 Attributes { 223 raw: self.raw | rhs.raw, 224 color_pair: ColorPair(self.color_pair.0 | rhs.color_pair.0), 225 } 226 } 227 } 228 229 /// Implement the ^ operator for removing Attributes from Attributes 230 /// 231 /// # Example 232 /// 233 /// ``` 234 /// use pancurses::{Attribute, Attributes}; 235 /// 236 /// let mut attributes = Attributes::new() | Attribute::Blink | Attribute::Bold; 237 /// let other = Attributes::new() | Attribute::Reverse | Attribute::Bold; 238 /// attributes = attributes ^ other; 239 /// assert!(!attributes.is_bold()); 240 /// assert!(attributes.is_reverse()); 241 /// assert!(attributes.is_blink()); 242 /// ``` 243 impl BitXor for Attributes { 244 type Output = Attributes; 245 bitxor(self, rhs: Attributes) -> Attributes246 fn bitxor(self, rhs: Attributes) -> Attributes { 247 Attributes { 248 raw: self.raw ^ rhs.raw, 249 color_pair: ColorPair(self.color_pair.0 ^ rhs.color_pair.0), 250 } 251 } 252 } 253 254 /// Implement the | operator for combining two 'Attribute's into Attributes 255 /// 256 /// # Example 257 /// 258 /// ``` 259 /// use pancurses::{Attribute, Attributes}; 260 /// 261 /// let attributes = Attribute::Blink | Attribute::Reverse; 262 /// assert!(!attributes.is_bold()); 263 /// assert!(attributes.is_blink()); 264 /// assert!(attributes.is_reverse()); 265 /// ``` 266 impl BitOr for Attribute { 267 type Output = Attributes; 268 bitor(self, rhs: Attribute) -> Attributes269 fn bitor(self, rhs: Attribute) -> Attributes { 270 Attributes::new() | self | rhs 271 } 272 } 273 274 /// Implement Default for Attributes 275 /// 276 /// # Example 277 /// 278 /// ``` 279 /// use pancurses::Attributes; 280 /// let attributes: Attributes = Default::default(); 281 /// assert_eq!(attributes, Attributes::new()); 282 /// ``` 283 impl Default for Attributes { default() -> Self284 fn default() -> Self { 285 Self::new() 286 } 287 } 288 289 impl From<Attribute> for Attributes { from(attribute: Attribute) -> Attributes290 fn from(attribute: Attribute) -> Attributes { 291 Attributes::new() | attribute 292 } 293 } 294 295 impl From<Attribute> for chtype { from(attribute: Attribute) -> chtype296 fn from(attribute: Attribute) -> chtype { 297 chtype::from(Attributes::from(attribute)) 298 } 299 } 300 301 impl From<Attributes> for chtype { from(attributes: Attributes) -> chtype302 fn from(attributes: Attributes) -> chtype { 303 attributes.raw 304 } 305 } 306