fltk/
enums.rs

1use crate::app::{FONTS, font_index};
2use crate::prelude::{FltkError, FltkErrorKind};
3use crate::utils::{self, FlString};
4use fltk_sys::fl;
5use std::{
6    ffi::{CStr, CString},
7    mem, path,
8};
9
10/// Defines label types
11#[repr(i32)]
12#[derive(Debug, Copy, Clone, PartialEq, Eq)]
13pub enum LabelType {
14    /// Normal
15    Normal = 0,
16    /// None
17    None,
18    /// Shadow
19    Shadow,
20    /// Engraved
21    Engraved,
22    /// Embossed
23    Embossed,
24}
25
26/// Defines the color depth for drawing and rgb images
27#[repr(u8)]
28#[derive(Debug, Copy, Clone, PartialEq, Eq)]
29pub enum ColorDepth {
30    /// Luminance/grayscale
31    L8 = 1,
32    /// Luminance with Alpha channel
33    La8 = 2,
34    /// RGB888
35    Rgb8 = 3,
36    /// RGBA8888 with Alpha channel
37    Rgba8 = 4,
38}
39
40/// Implements some convenience methods for `ColorDepth`
41impl ColorDepth {
42    /// Create a `ColorDepth` from an u8 value
43    pub fn from_u8(val: u8) -> Result<ColorDepth, FltkError> {
44        if (1..=4).contains(&val) {
45            Ok(unsafe { mem::transmute(val) })
46        } else {
47            Err(FltkError::Internal(FltkErrorKind::FailedOperation))
48        }
49    }
50}
51
52#[doc(hidden)]
53#[derive(Copy, Clone, Debug, PartialEq, Eq)]
54pub struct UnmappedFrameType {
55    bits: i32,
56}
57
58impl UnmappedFrameType {
59    #[doc(hidden)]
60    pub const unsafe fn from_i32(val: i32) -> Self {
61        Self { bits: val }
62    }
63}
64
65/// Defines the frame types which can be set using the `set_frame()` and `set_down_frame()` methods
66#[repr(i32)]
67#[non_exhaustive]
68#[derive(Debug, Copy, Clone, PartialEq, Eq)]
69pub enum FrameType {
70    /// No Box
71    NoBox,
72    /// Flat Box
73    FlatBox,
74    /// Up Box
75    UpBox,
76    /// Down Box
77    DownBox,
78    /// Up Frame
79    UpFrame,
80    /// Down Frame
81    DownFrame,
82    /// Thin Up Box
83    ThinUpBox,
84    /// Thin Down Box
85    ThinDownBox,
86    /// Thin Up Frame
87    ThinUpFrame,
88    /// Thin Down Frame
89    ThinDownFrame,
90    /// Engraved Box
91    EngravedBox,
92    /// Embossed Box
93    EmbossedBox,
94    /// Engraved Frame
95    EngravedFrame,
96    /// Embossed Frame
97    EmbossedFrame,
98    /// Border Box
99    BorderBox,
100    /// Shadow Box
101    ShadowBox,
102    /// Border Frame
103    BorderFrame,
104    /// Shadow Frame
105    ShadowFrame,
106    /// Rounded Box
107    RoundedBox,
108    /// Rounded Shadow Box
109    RShadowBox,
110    /// Rounded Frame
111    RoundedFrame,
112    /// Rounded Flat Box
113    RFlatBox,
114    /// Round Up Box
115    RoundUpBox,
116    /// Round Down Box
117    RoundDownBox,
118    /// Diamond Up Box
119    DiamondUpBox,
120    /// Diamond Down Box
121    DiamondDownBox,
122    /// Oval Box
123    OvalBox,
124    /// Oval Shadow Box
125    OShadowBox,
126    /// Oval Frame
127    OvalFrame,
128    /// Oval Flat Box
129    OFlatBox,
130    /// Plastic Up Box
131    PlasticUpBox,
132    /// Plastic Down Box
133    PlasticDownBox,
134    /// Plastic Up Frame
135    PlasticUpFrame,
136    /// Plastic Down Frame
137    PlasticDownFrame,
138    /// Plastic Thin Up Box
139    PlasticThinUpBox,
140    /// Plastic Thin Down Box
141    PlasticThinDownBox,
142    /// Plastic Round Up Box
143    PlasticRoundUpBox,
144    /// Plastic Round Down Box
145    PlasticRoundDownBox,
146    /// Gtk Up Box
147    GtkUpBox,
148    /// Gtk Down Box
149    GtkDownBox,
150    /// Gtk Up Frame
151    GtkUpFrame,
152    /// Gtk Down Frame
153    GtkDownFrame,
154    /// Gtk Thin Up Box
155    GtkThinUpBox,
156    /// Gtk Thin Down Box
157    GtkThinDownBox,
158    /// Gtk Thin Up Frame
159    GtkThinUpFrame,
160    /// Gtk Thin Down Frame
161    GtkThinDownFrame,
162    /// Gtk Round Up Frame
163    GtkRoundUpBox,
164    /// Gtk Round Down Frame
165    GtkRoundDownBox,
166    /// Gleam Up Box
167    GleamUpBox,
168    /// Gleam Down Box
169    GleamDownBox,
170    /// Gleam Up Frame
171    GleamUpFrame,
172    /// Gleam Down Frame
173    GleamDownFrame,
174    /// Gleam Thin Up Box
175    GleamThinUpBox,
176    /// Gleam Thin Down Box
177    GleamThinDownBox,
178    /// Gleam Round Up Box
179    GleamRoundUpBox,
180    /// Gleam Round Down Box
181    GleamRoundDownBox,
182    /// Free `BoxType`
183    FreeBoxType,
184    /// User-defined frame types
185    UserFrameType(UnmappedFrameType),
186}
187
188impl FrameType {
189    /// Get the discriminant value or the user defined frame type
190    pub fn as_i32(&self) -> i32 {
191        match *self {
192            FrameType::UserFrameType(v) => v.bits,
193            _ => self.discriminant(),
194        }
195    }
196    /// Construct a FrameType from an i32 value
197    /// # Safety
198    /// The frametype should be defined using the `app::set_frame_type_cb` function
199    #[doc(hidden)]
200    pub unsafe fn from_i32(v: i32) -> FrameType {
201        unsafe {
202            if (0..=56).contains(&v) {
203                *(&raw const v as *const FrameType)
204            } else {
205                FrameType::UserFrameType(UnmappedFrameType::from_i32(v))
206            }
207        }
208    }
209    #[doc(hidden)]
210    fn discriminant(&self) -> i32 {
211        unsafe { *(std::ptr::from_ref::<Self>(self) as *const i32) }
212    }
213    /// Gets the Frame type by index
214    pub fn by_index(idx: usize) -> FrameType {
215        let idx = if idx > 56 { 56 } else { idx };
216        unsafe { FrameType::from_i32(idx as i32) }
217    }
218
219    /// Get the frame's x offset
220    pub fn dx(self) -> i32 {
221        unsafe { fl::Fl_box_dx(self.as_i32()) }
222    }
223
224    /// Get the frame's y offset
225    pub fn dy(self) -> i32 {
226        unsafe { fl::Fl_box_dy(self.as_i32()) }
227    }
228
229    /// Get the frame's width offset
230    pub fn dw(self) -> i32 {
231        unsafe { fl::Fl_box_dw(self.as_i32()) }
232    }
233
234    /// Get the frame's height offset
235    pub fn dh(self) -> i32 {
236        unsafe { fl::Fl_box_dh(self.as_i32()) }
237    }
238
239    /// Swap frames
240    pub fn swap_frames(old_frame: FrameType, new_frame: FrameType) {
241        unsafe {
242            let new_frame = new_frame.as_i32();
243            let old_frame = old_frame.as_i32();
244            fl::Fl_set_box_type(old_frame, new_frame);
245        }
246    }
247}
248
249bitflags::bitflags! {
250    /// Defines alignment rules used by FLTK for labels
251    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
252    pub struct Align: i32 {
253        /// Center
254        const Center = 0x0000;
255        /// Top
256        const Top = 0x0001;
257        /// Bottom
258        const Bottom = 0x0002;
259        /// Left
260        const Left = 0x0004;
261        /// Right
262        const Right = 0x0008;
263        /// Inside
264        const Inside = 0x0010;
265        /// Text Over Image
266        const TextOverImage = 0x0020;
267        /// Clip
268        const Clip = 0x0040;
269        /// Wrap
270        const Wrap = 0x0080;
271        /// Image Next To Text
272        const ImageNextToText = 0x0100;
273        /// Text Next To Image
274        const TextNextToImage = 0x0120;
275        /// Image Backdrop
276        const ImageBackdrop = 0x0200;
277        /// Top Left
278        const TopLeft = 0x0001 | 0x0004;
279        /// Top Right
280        const TopRight = 0x0001 | 0x0008;
281        /// Bottom Left
282        const BottomLeft = 0x0002 | 0x0004;
283        /// Bottom Right
284        const BottomRight = 0x0002 | 0x0008;
285        /// Left Top
286        const LeftTop = 0x0007;
287        /// Right Top
288        const RightTop = 0x000B;
289        /// Left Bottom
290        const LeftBottom = 0x000D;
291        /// Right Bottom
292        const RightBottom = 0x000E;
293        /// Position Mask
294        const PositionMask = 0x000F;
295        /// Image Mask
296        const ImageMask = 0x0320;
297    }
298}
299
300/// Defines fonts used by FLTK
301#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
302pub struct Font {
303    bits: i32,
304}
305
306impl Font {
307    /// Helvetica
308    pub const Helvetica: Font = Font { bits: 0 };
309    /// Helvetica Bold
310    pub const HelveticaBold: Font = Font { bits: 1 };
311    /// Helvetica Italic
312    pub const HelveticaItalic: Font = Font { bits: 2 };
313    /// Helvetica Bold Italic
314    pub const HelveticaBoldItalic: Font = Font { bits: 3 };
315    /// Courier
316    pub const Courier: Font = Font { bits: 4 };
317    /// Courier Bold
318    pub const CourierBold: Font = Font { bits: 5 };
319    /// Courier Italic
320    pub const CourierItalic: Font = Font { bits: 6 };
321    /// Courier Bold Italic
322    pub const CourierBoldItalic: Font = Font { bits: 7 };
323    /// Times
324    pub const Times: Font = Font { bits: 8 };
325    /// Times Bold
326    pub const TimesBold: Font = Font { bits: 9 };
327    /// Times Italic
328    pub const TimesItalic: Font = Font { bits: 10 };
329    /// Times Bold Italic
330    pub const TimesBoldItalic: Font = Font { bits: 11 };
331    /// Symbol
332    pub const Symbol: Font = Font { bits: 12 };
333    /// Screen
334    pub const Screen: Font = Font { bits: 13 };
335    /// Screen Bold
336    pub const ScreenBold: Font = Font { bits: 14 };
337    /// Zapfdingbats
338    pub const Zapfdingbats: Font = Font { bits: 15 };
339    /// Gets the inner value of the Font
340    pub const fn bits(&self) -> i32 {
341        self.bits
342    }
343    /// Returns a font by index. This is the enum representation of the Font. If you change the default font for your app,
344    /// which by default is Helvetica, `Font::by_index(0)` will still show Helvetica!
345    pub fn by_index(idx: usize) -> Font {
346        if idx < (FONTS.lock().unwrap()).len() {
347            unsafe { mem::transmute(idx as i32) }
348        } else {
349            Font::Helvetica
350        }
351    }
352
353    /// Gets the font by its name, can be queried via the [`app::get_font_names()`](`crate::app::get_font_names`)
354    pub fn by_name(name: &str) -> Font {
355        match font_index(name) {
356            Some(val) => Font::by_index(val),
357            None => Font::Helvetica,
358        }
359    }
360
361    /**
362        Replace a current font with a loaded font
363        ```rust,no_run
364        use fltk::enums::Font;
365        let font = Font::load_font("font.ttf").unwrap();
366        Font::set_font(Font::Helvetica, &font);
367        ```
368    */
369    pub fn set_font(old: Font, new: &str) {
370        let new = CString::safe_new(new);
371        unsafe {
372            fl::Fl_set_font_by_name(old.bits(), new.into_raw() as _);
373        }
374    }
375
376    /**
377        Load font from file.
378        ```rust,no_run
379        use fltk::enums::Font;
380        let font = Font::load_font("font.ttf").unwrap();
381        Font::set_font(Font::Helvetica, &font);
382        ```
383    */
384    pub fn load_font<P: AsRef<path::Path>>(path: P) -> Result<String, FltkError> {
385        Font::load_font_(path.as_ref())
386    }
387
388    fn load_font_(path: &path::Path) -> Result<String, FltkError> {
389        unsafe {
390            if !path.exists() {
391                return Err::<String, FltkError>(FltkError::Internal(
392                    FltkErrorKind::ResourceNotFound,
393                ));
394            }
395            if let Some(p) = path.to_str() {
396                let font_data = std::fs::read(path)?;
397                let Ok(face) = ttf_parser::Face::parse(&font_data, 0) else {
398                    return Err(FltkError::Internal(FltkErrorKind::FailedOperation));
399                };
400
401                let family_name = face
402                    .names()
403                    .into_iter()
404                    .find(|name| {
405                        name.name_id == ttf_parser::name_id::FULL_NAME && name.is_unicode()
406                    })
407                    .and_then(|name| name.to_string());
408                let path = CString::safe_new(p);
409                let ret = fl::Fl_load_font(path.as_ptr());
410                if let Some(family_name) = family_name {
411                    if ret > 0 {
412                        Ok(family_name)
413                    } else {
414                        Err(FltkError::Internal(FltkErrorKind::FailedOperation))
415                    }
416                } else {
417                    Err(FltkError::Internal(FltkErrorKind::FailedOperation))
418                }
419            } else {
420                Err(FltkError::Internal(FltkErrorKind::FailedOperation))
421            }
422        }
423    }
424
425    /// Get the font's real name
426    pub fn get_name(&self) -> String {
427        unsafe {
428            CStr::from_ptr(fl::Fl_get_font_name(self.bits()))
429                .to_string_lossy()
430                .to_string()
431        }
432    }
433}
434
435// todo: implement Display for Font ?
436#[allow(unreachable_patterns)]
437impl std::fmt::Debug for Font {
438    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
439        match *self {
440            Font::Helvetica => write!(f, "Font::Helvetica"),
441            Font::HelveticaBold => write!(f, "Font::HelveticaBold"),
442            Font::HelveticaItalic => write!(f, "Font::HelveticaItalic"),
443            Font::HelveticaBoldItalic => write!(f, "Font::HelveticaBoldItalic"),
444            Font::Courier => write!(f, "Font::Courier"),
445            Font::CourierBold => write!(f, "Font::CourierBold"),
446            Font::CourierItalic => write!(f, "Font::CourierItalic"),
447            Font::CourierBoldItalic => write!(f, "Font::CourierBoldItalic"),
448            Font::Times => write!(f, "Font::Times"),
449            Font::TimesBold => write!(f, "Font::TimesBold"),
450            Font::TimesItalic => write!(f, "Font::TimesItalic"),
451            Font::TimesBoldItalic => write!(f, "Font::TimesBoldItalic"),
452            Font::Symbol => write!(f, "Font::Symbol"),
453            Font::Screen => write!(f, "Font::Screen"),
454            Font::ScreenBold => write!(f, "Font::ScreenBold"),
455            Font::Zapfdingbats => write!(f, "Font::Zapfdingbats"),
456            _ => {
457                write!(f, "Font::from_i32({})", self.bits())
458            }
459        }
460    }
461}
462
463/// Defines colors used by FLTK.
464/// Colors are stored as RGBI values, the last being the index for FLTK colors in this enum.
465/// Colors in this enum don't have an RGB stored. However, custom colors have an RGB, and don't have an index.
466/// The RGBI can be acquired by casting the color to u32 and formatting it to ```0x{08x}```.
467/// The last 2 digits are the hexadecimal representation of the color in this enum.
468/// For example, `Color::White`, has a hex of 0x000000ff, ff being the 255 value of this enum.
469/// A custom color like `Color::from_u32(0x646464)`, will have an representation as 0x64646400,
470/// of which the final 00 indicates that it is not stored in this enum.
471/// For convenience, the `fmt::Display` trait is implemented so that the name of the Color is shown
472/// when there is one, otherwise the RGB value is given.
473
474#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
475pub struct Color {
476    bits: u32,
477}
478
479impl Color {
480    /// Foreground, label colors
481    pub const Foreground: Color = Color { bits: 0 };
482    /// Background2, Is the color inside input, output and text display widgets
483    pub const Background2: Color = Color { bits: 7 };
484    /// Inactive
485    pub const Inactive: Color = Color { bits: 8 };
486    /// Selection
487    pub const Selection: Color = Color { bits: 15 };
488    /// Free
489    pub const Free: Color = Color { bits: 16 };
490    /// Gray0
491    pub const Gray0: Color = Color { bits: 32 };
492    /// `GrayRamp`
493    pub const GrayRamp: Color = Color { bits: 32 };
494    /// Dark3
495    pub const Dark3: Color = Color { bits: 39 };
496    /// Dark2
497    pub const Dark2: Color = Color { bits: 45 };
498    /// Dark1
499    pub const Dark1: Color = Color { bits: 47 };
500    /// `FrameDefault`
501    pub const FrameDefault: Color = Color { bits: 49 };
502    /// Background
503    pub const Background: Color = Color { bits: 49 };
504    /// Light1
505    pub const Light1: Color = Color { bits: 50 };
506    /// Light2
507    pub const Light2: Color = Color { bits: 52 };
508    /// Light3
509    pub const Light3: Color = Color { bits: 54 };
510    /// Black
511    pub const Black: Color = Color { bits: 56 };
512    /// Red
513    pub const Red: Color = Color { bits: 88 };
514    /// Green
515    pub const Green: Color = Color { bits: 63 };
516    /// Yellow
517    pub const Yellow: Color = Color { bits: 95 };
518    /// Blue
519    pub const Blue: Color = Color { bits: 216 };
520    /// Magenta
521    pub const Magenta: Color = Color { bits: 248 };
522    /// Cyan
523    pub const Cyan: Color = Color { bits: 223 };
524    /// `DarkRed`
525    pub const DarkRed: Color = Color { bits: 72 };
526    /// `DarkGreen`
527    pub const DarkGreen: Color = Color { bits: 60 };
528    /// `DarkYellow`
529    pub const DarkYellow: Color = Color { bits: 76 };
530    /// `DarkBlue`
531    pub const DarkBlue: Color = Color { bits: 136 };
532    /// `DarkMagenta`
533    pub const DarkMagenta: Color = Color { bits: 152 };
534    /// `DarkCyan`
535    pub const DarkCyan: Color = Color { bits: 140 };
536    /// White
537    pub const White: Color = Color { bits: 255 };
538
539    /// ANSI/xterm Black, not part of FLTK's colormap
540    pub const XtermBlack: Color = Color { bits: 0x0000_0000 };
541    /// ANSI/xterm Red, not part of FLTK's colormap
542    pub const XtermRed: Color = Color { bits: 0xd000_0000 };
543    /// ANSI/xterm Green, not part of FLTK's colormap
544    pub const XtermGreen: Color = Color { bits: 0x00d0_0000 };
545    /// ANSI/xterm Yellow, not part of FLTK's colormap
546    pub const XtermYellow: Color = Color { bits: 0xd0d0_0000 };
547    /// ANSI/xterm Blue, not part of FLTK's colormap
548    pub const XtermBlue: Color = Color { bits: 0x0000_d000 };
549    /// ANSI/xterm Magenta, not part of FLTK's colormap
550    pub const XtermMagenta: Color = Color { bits: 0xd000_d000 };
551    /// ANSI/xterm Cyan, not part of FLTK's colormap
552    pub const XtermCyan: Color = Color { bits: 0x00d0_d000 };
553    /// ANSI/xterm White, not part of FLTK's colormap
554    pub const XtermWhite: Color = Color { bits: 0xd0d0_d000 };
555    /// ANSI/xterm background Red, not part of FLTK's colormap
556    pub const XtermBgRed: Color = Color { bits: 0xc000_0000 };
557    /// ANSI/xterm background Green, not part of FLTK's colormap
558    pub const XtermBgGreen: Color = Color { bits: 0x00c0_0000 };
559    /// ANSI/xterm background Yelllow, not part of FLTK's colormap
560    pub const XtermBgYellow: Color = Color { bits: 0xc0c0_0000 };
561    /// ANSI/xterm background Blue, not part of FLTK's colormap
562    pub const XtermBgBlue: Color = Color { bits: 0x0000_c000 };
563    /// ANSI/xterm background Magenta, not part of FLTK's colormap
564    pub const XtermBgMagenta: Color = Color { bits: 0xd000_c000 };
565    /// ANSI/xterm background Cyan, not part of FLTK's colormap
566    pub const XtermBgCyan: Color = Color { bits: 0x00c0_c000 };
567    /// ANSI/xterm background White, not part of FLTK's colormap
568    pub const XtermBgWhite: Color = Color { bits: 0xc0c0_c000 };
569
570    /// Special background color value that lets the Terminal widget's `box()` color show through behind the text.
571    /// Not part of FLTK's colormap
572    pub const TransparentBg: Color = Color { bits: 0xffff_ffff };
573
574    /// Gets the inner color representation
575    pub const fn bits(&self) -> u32 {
576        self.bits
577    }
578    /// Returns a color from RGB
579    pub const fn from_rgb(r: u8, g: u8, b: u8) -> Color {
580        let r = r as u32;
581        let g = g as u32;
582        let b = b as u32;
583        let val: u32 = ((r & 0xff) << 24) + ((g & 0xff) << 16) + ((b & 0xff) << 8);
584        Color::from_rgbi(val)
585    }
586
587    #[cfg(feature = "enable-glwindow")]
588    /// Returns a color from RGB
589    pub const fn from_rgba(r: u8, g: u8, b: u8, a: u8) -> Color {
590        let r = r as u32;
591        let g = g as u32;
592        let b = b as u32;
593        let a = a as u32;
594        let val: u32 = ((r & 0xff) << 24) + ((g & 0xff) << 16) + ((b & 0xff) << 8) + (a & 0xff);
595        Color::from_rgbi(val)
596    }
597
598    /// Returns a color enum from RGBI encoding
599    pub const fn from_rgbi(rgbi: u32) -> Color {
600        Color { bits: rgbi }
601    }
602
603    /// Create color from RGBA using alpha compositing. Works for non-group types.
604    pub fn from_composited_rgba8(tup: (u8, u8, u8, u8)) -> Color {
605        if tup.3 == 255 {
606            Color::from_rgb(tup.0, tup.1, tup.2)
607        } else {
608            let bg_col = if let Some(grp) = crate::group::Group::current() {
609                use crate::prelude::WidgetExt;
610                grp.color()
611            } else {
612                Color::Background
613            };
614            let bg_col = bg_col.to_rgb();
615            let alpha = f32::from(tup.3) / 255.0;
616            let r = alpha * f32::from(tup.0) + (1.0 - alpha) * f32::from(bg_col.0);
617            let r = r as u8;
618            let g = alpha * f32::from(tup.1) + (1.0 - alpha) * f32::from(bg_col.1);
619            let g = g as u8;
620            let b = alpha * f32::from(tup.2) + (1.0 - alpha) * f32::from(bg_col.2);
621            let b = b as u8;
622            Color::from_rgb(r, g, b)
623        }
624    }
625
626    /// Returns a color from hex or decimal
627    pub const fn from_u32(val: u32) -> Color {
628        #[cfg(feature = "enable-glwindow")]
629        {
630            let (r, g, b, a) = utils::hex2rgba(val);
631            Color::from_rgba(r, g, b, a)
632        }
633        #[cfg(not(feature = "enable-glwindow"))]
634        {
635            let (r, g, b) = utils::hex2rgb(val);
636            Color::from_rgb(r, g, b)
637        }
638    }
639
640    /// Returns a color from hex or decimal
641    pub const fn from_hex(val: u32) -> Color {
642        Color::from_u32(val)
643    }
644
645    /// Return a Color from a hex color format (`#xxxxxx`)
646    pub fn from_hex_str(col: &str) -> Result<Color, FltkError> {
647        if !col.starts_with('#') || col.len() < 7 {
648            return Err(FltkError::Internal(FltkErrorKind::InvalidColor));
649        }
650        let color: Color;
651        #[cfg(not(feature = "enable-glwindow"))]
652        {
653            color = Color::from_hex(u32::from_str_radix(&col[1..7], 16)?);
654        }
655
656        #[cfg(feature = "enable-glwindow")]
657        {
658            color = Color::from_hex(u32::from_str_radix(&col[1..9], 16)?);
659        }
660        Ok(color)
661    }
662
663    /// Returns the color in hex string format
664    pub fn to_hex_str(&self) -> String {
665        #[cfg(not(feature = "enable-glwindow"))]
666        {
667            let (r, g, b) = self.to_rgb();
668            format!("#{r:02x}{g:02x}{b:02x}")
669        }
670        #[cfg(feature = "enable-glwindow")]
671        {
672            let (r, g, b, a) = self.to_rgba();
673            format!("#{:02x}{:02x}{:02x}{:02x}", r, g, b, a)
674        }
675    }
676
677    /// Returns a color by index of RGBI
678    pub fn by_index(idx: u8) -> Color {
679        unsafe { mem::transmute(u32::from(idx)) }
680    }
681
682    /// Returns an inactive form of the color
683    #[must_use]
684    pub fn inactive(&self) -> Color {
685        unsafe { mem::transmute(fl::Fl_inactive(self.bits())) }
686    }
687
688    /// Returns an darker form of the color
689    #[must_use]
690    pub fn darker(&self) -> Color {
691        unsafe { mem::transmute(fl::Fl_darker(self.bits())) }
692    }
693
694    /// Returns an lighter form of the color
695    #[must_use]
696    pub fn lighter(&self) -> Color {
697        unsafe { mem::transmute(fl::Fl_lighter(self.bits())) }
698    }
699
700    /// Returns a gray color value from black (i == 0) to white (i == `FL_NUM_GRAY` - 1)
701    pub fn gray_ramp(val: i32) -> Color {
702        unsafe { mem::transmute(fl::Fl_gray_ramp(val)) }
703    }
704
705    /// Returns a gray color value from black (i == 0) to white (i == `FL_NUM_GRAY` - 1)
706    pub fn color_average(c1: Color, c2: Color, weight: f32) -> Color {
707        unsafe { mem::transmute(fl::Fl_color_average(c1.bits(), c2.bits(), weight)) }
708    }
709
710    /// Returns a color that contrasts with the background color.
711    pub fn contrast(fg: Color, bg: Color) -> Color {
712        unsafe { mem::transmute(fl::Fl_contrast(fg.bits(), bg.bits())) }
713    }
714
715    /// Returns the color closest to the passed grayscale value
716    pub fn gray_scale(g: u8) -> Color {
717        unsafe { mem::transmute(fl::Fl_rgb_color_grayscale(g)) }
718    }
719
720    /// Returns the color closest to the passed rgb value
721    pub fn rgb_color(r: u8, g: u8, b: u8) -> Color {
722        unsafe { mem::transmute(fl::Fl_rgb_color(r, g, b)) }
723    }
724
725    /// Get the RGB value of the color
726    pub fn to_rgb(&self) -> (u8, u8, u8) {
727        unsafe {
728            let val = self.bits();
729            let r = ((val >> 24) & 0xff) as u8;
730            let g = ((val >> 16) & 0xff) as u8;
731            let b = ((val >> 8) & 0xff) as u8;
732            let i = (val & 0xff) as u8;
733            if (i == 0 && val != 0) || val > 255 {
734                (r, g, b)
735            } else {
736                let val = fl::Fl_cmap(u32::from(i));
737                let r = ((val >> 24) & 0xff) as u8;
738                let g = ((val >> 16) & 0xff) as u8;
739                let b = ((val >> 8) & 0xff) as u8;
740                (r, g, b)
741            }
742        }
743    }
744
745    #[cfg(feature = "enable-glwindow")]
746    /// Get the RGBA value of the color
747    pub fn to_rgba(&self) -> (u8, u8, u8, u8) {
748        let val = self.bits();
749        let r = ((val >> 24) & 0xff) as u8;
750        let g = ((val >> 16) & 0xff) as u8;
751        let b = ((val >> 8) & 0xff) as u8;
752        let a = (val & 0xff) as u8;
753        (r, g, b, a)
754    }
755}
756
757#[allow(unreachable_patterns)]
758impl std::fmt::Display for Color {
759    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
760        match *self {
761            Color::Foreground => write!(f, "Color::Foreground"),
762            Color::Background => write!(f, "Color::Background"),
763            Color::Background2 => write!(f, "Color::Background2"),
764            Color::Inactive => write!(f, "Color::Inactive"),
765            Color::Selection => write!(f, "Color::Selection"),
766            Color::Gray0 => write!(f, "Color::Gray0"),
767            Color::Dark3 => write!(f, "Color::Dark3"),
768            Color::Dark2 => write!(f, "Color::Dark2"),
769            Color::Dark1 => write!(f, "Color::Dark1"),
770            Color::FrameDefault => write!(f, "Color::FrameDefault"),
771            Color::Light1 => write!(f, "Color::Light1"),
772            Color::Light2 => write!(f, "Color::Light2"),
773            Color::Light3 => write!(f, "Color::Light3"),
774            Color::Black => write!(f, "Color::Black"),
775            Color::Red => write!(f, "Color::Red"),
776            Color::Green => write!(f, "Color::Green"),
777            Color::Yellow => write!(f, "Color::Yellow"),
778            Color::Blue => write!(f, "Color::Blue"),
779            Color::Magenta => write!(f, "Color::Magenta"),
780            Color::Cyan => write!(f, "Color::Cyan"),
781            Color::DarkRed => write!(f, "Color::DarkRed"),
782            Color::DarkGreen => write!(f, "Color::DarkGreen"),
783            Color::DarkYellow => write!(f, "Color::DarkYellow"),
784            Color::DarkBlue => write!(f, "Color::DarkBlue"),
785            Color::DarkMagenta => write!(f, "Color::DarkMagenta"),
786            Color::DarkCyan => write!(f, "Color::DarkCyan"),
787            Color::White => write!(f, "Color::White"),
788
789            Color::XtermRed => write!(f, "Color::XtermRed"),
790            Color::XtermGreen => write!(f, "Color::XtermGreen"),
791            Color::XtermYellow => write!(f, "Color::XtermYellow"),
792            Color::XtermBlue => write!(f, "Color::XtermBlue"),
793            Color::XtermMagenta => write!(f, "Color::XtermMagenta"),
794            Color::XtermCyan => write!(f, "Color::XtermCyan"),
795            Color::XtermWhite => write!(f, "Color::XtermWhite"),
796            Color::XtermBgRed => write!(f, "Color::XtermBgRed"),
797            Color::XtermBgGreen => write!(f, "Color::XtermBgGreen"),
798            Color::XtermBgYellow => write!(f, "Color::XtermBgYellow"),
799            Color::XtermBgBlue => write!(f, "Color::XtermBgBlue"),
800            Color::XtermBgMagenta => write!(f, "Color::XtermBgMagenta"),
801            Color::XtermBgCyan => write!(f, "Color::XtermBgCyan"),
802            Color::XtermBgWhite => write!(f, "Color::XtermBgWhite"),
803
804            Color::TransparentBg => write!(f, "Color::TransparentBg"),
805            _ => {
806                let temp = format!("{:08x}", self.bits());
807                write!(f, "Color::from_hex(0x{}_{})", &temp[0..6], &temp[6..8])
808            }
809        }
810    }
811}
812
813#[allow(unreachable_patterns)]
814impl std::fmt::Debug for Color {
815    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
816        write!(f, "{}", *self)
817    }
818}
819
820/// Defines event types captured by FLTK
821#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
822pub struct Event {
823    bits: i32,
824}
825
826impl Event {
827    /// No Event
828    pub const NoEvent: Event = Event { bits: 0 };
829    /// Push
830    pub const Push: Event = Event { bits: 1 };
831    /// Released
832    pub const Released: Event = Event { bits: 2 };
833    /// Enter
834    pub const Enter: Event = Event { bits: 3 };
835    /// Leave
836    pub const Leave: Event = Event { bits: 4 };
837    /// Drag
838    pub const Drag: Event = Event { bits: 5 };
839    /// Focus
840    pub const Focus: Event = Event { bits: 6 };
841    /// Unfocus
842    pub const Unfocus: Event = Event { bits: 7 };
843    /// Keyboard, equivalent to `KeyDown`
844    pub const Keyboard: Event = Event { bits: 8 };
845    /// `KeyDown`
846    pub const KeyDown: Event = Event { bits: 8 };
847    /// `KeyUp`
848    pub const KeyUp: Event = Event { bits: 9 };
849    /// Close
850    pub const Close: Event = Event { bits: 10 };
851    /// Move
852    pub const Move: Event = Event { bits: 11 };
853    /// Shortcut
854    pub const Shortcut: Event = Event { bits: 12 };
855    /// Deactivate
856    pub const Deactivate: Event = Event { bits: 13 };
857    /// Activate
858    pub const Activate: Event = Event { bits: 14 };
859    /// Hide
860    pub const Hide: Event = Event { bits: 15 };
861    /// Show
862    pub const Show: Event = Event { bits: 16 };
863    /// Paste
864    pub const Paste: Event = Event { bits: 17 };
865    /// Selection Clear
866    pub const SelectionClear: Event = Event { bits: 18 };
867    /// `MouseWheel`
868    pub const MouseWheel: Event = Event { bits: 19 };
869    /// `DndEnter`
870    pub const DndEnter: Event = Event { bits: 20 };
871    /// Drag n Drop: Drag
872    pub const DndDrag: Event = Event { bits: 21 };
873    /// Drag n Drop: Leave
874    pub const DndLeave: Event = Event { bits: 22 };
875    /// Drag n Drop: Release
876    pub const DndRelease: Event = Event { bits: 23 };
877    /// Screen Config Changed
878    pub const ScreenConfigChanged: Event = Event { bits: 24 };
879    /// Fullscreen
880    pub const Fullscreen: Event = Event { bits: 25 };
881    /// Zoom Gesture
882    pub const ZoomGesture: Event = Event { bits: 26 };
883    /// Zoom Event
884    pub const ZoomEvent: Event = Event { bits: 27 };
885    /// Window Resize Event.
886    /// Avoid resizing the parent during a resize event
887    /// to avoid infinite recursion
888    pub const Resize: Event = Event { bits: 28 };
889    /// Gets the inner value
890    pub const fn bits(&self) -> i32 {
891        self.bits
892    }
893    /// Creates an event from an i32 value
894    pub const fn from_i32(val: i32) -> Event {
895        Event { bits: val }
896    }
897}
898
899impl From<i32> for Event {
900    fn from(val: i32) -> Event {
901        Event::from_i32(val)
902    }
903}
904
905#[allow(unreachable_patterns)]
906impl std::fmt::Debug for Event {
907    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
908        write!(f, "{}", *self)
909    }
910}
911
912#[allow(unreachable_patterns)]
913impl std::fmt::Display for Event {
914    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
915        match *self {
916            Event::NoEvent => write!(f, "Event::NoEvent"),
917            Event::Push => write!(f, "Event::Push"),
918            Event::Released => write!(f, "Event::Released"),
919            Event::Enter => write!(f, "Event::Enter"),
920            Event::Leave => write!(f, "Event::Leave"),
921            Event::Drag => write!(f, "Event::Drag"),
922            Event::Focus => write!(f, "Event::Focus"),
923            Event::Unfocus => write!(f, "Event::Unfocus"),
924            Event::KeyDown => write!(f, "Event::KeyDown"),
925            Event::KeyUp => write!(f, "Event::KeyUp"),
926            Event::Close => write!(f, "Event::Close"),
927            Event::Move => write!(f, "Event::Move"),
928            Event::Shortcut => write!(f, "Event::Shortcut"),
929            Event::Deactivate => write!(f, "Event::Deactivate"),
930            Event::Activate => write!(f, "Event::Activate"),
931            Event::Hide => write!(f, "Event::Hide"),
932            Event::Show => write!(f, "Event::Show"),
933            Event::Paste => write!(f, "Event::Paste"),
934            Event::SelectionClear => write!(f, "Event::SelectionClear"),
935            Event::MouseWheel => write!(f, "Event::MouseWheel"),
936            Event::DndEnter => write!(f, "Event::DndEnter"),
937            Event::DndDrag => write!(f, "Event::DndDrag"),
938            Event::DndLeave => write!(f, "Event::DndLeave"),
939            Event::DndRelease => write!(f, "Event::DndRelease"),
940            Event::ScreenConfigChanged => write!(f, "Event::ScreenConfigChanged"),
941            Event::Fullscreen => write!(f, "Event::Fullscreen"),
942            Event::ZoomGesture => write!(f, "Event::ZoomGesture"),
943            Event::ZoomEvent => write!(f, "Event::ZoomEvent"),
944            Event::Resize => write!(f, "Event::Resize"),
945            _ => {
946                write!(f, "Event::from_i32({})", self.bits())
947            }
948        }
949    }
950}
951
952/// Defines the inputted virtual keycode
953#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
954pub struct Key {
955    bits: i32,
956}
957
958impl Key {
959    /// None
960    pub const None: Key = Key { bits: 0 };
961    /// Button
962    pub const Button: Key = Key { bits: 0xfee8 };
963    /// `BackSpace`
964    pub const BackSpace: Key = Key { bits: 0xff08 };
965    /// Tab
966    pub const Tab: Key = Key { bits: 0xff09 };
967    /// `IsoKey`
968    pub const IsoKey: Key = Key { bits: 0xff0c };
969    /// Enter
970    pub const Enter: Key = Key { bits: 0xff0d };
971    /// Pause
972    pub const Pause: Key = Key { bits: 0xff13 };
973    /// `ScrollLock`
974    pub const ScrollLock: Key = Key { bits: 0xff14 };
975    /// Escape
976    pub const Escape: Key = Key { bits: 0xff1b };
977    /// Kana
978    pub const Kana: Key = Key { bits: 0xff2e };
979    /// Eisu
980    pub const Eisu: Key = Key { bits: 0xff2f };
981    /// Yen
982    pub const Yen: Key = Key { bits: 0xff30 };
983    /// `JISUnderscore`
984    pub const JISUnderscore: Key = Key { bits: 0xff31 };
985    /// Home
986    pub const Home: Key = Key { bits: 0xff50 };
987    /// Left
988    pub const Left: Key = Key { bits: 0xff51 };
989    /// Up
990    pub const Up: Key = Key { bits: 0xff52 };
991    /// Right
992    pub const Right: Key = Key { bits: 0xff53 };
993    /// Down
994    pub const Down: Key = Key { bits: 0xff54 };
995    /// `PageUp`
996    pub const PageUp: Key = Key { bits: 0xff55 };
997    /// `PageDown`
998    pub const PageDown: Key = Key { bits: 0xff56 };
999    /// End
1000    pub const End: Key = Key { bits: 0xff57 };
1001    /// Print
1002    pub const Print: Key = Key { bits: 0xff61 };
1003    /// Insert
1004    pub const Insert: Key = Key { bits: 0xff63 };
1005    /// Menu
1006    pub const Menu: Key = Key { bits: 0xff67 };
1007    /// Help
1008    pub const Help: Key = Key { bits: 0xff68 };
1009    /// `NumLock`
1010    pub const NumLock: Key = Key { bits: 0xff7f };
1011    /// Keypad
1012    pub const KP: Key = Key { bits: 0xff80 };
1013    /// Keypad Enter
1014    pub const KPEnter: Key = Key { bits: 0xff8d };
1015    /// Keypad Last
1016    pub const KPLast: Key = Key { bits: 0xffbd };
1017    /// F1
1018    pub const F1: Key = Key { bits: 0xffbd + 1 };
1019    /// F2
1020    pub const F2: Key = Key { bits: 0xffbd + 2 };
1021    /// F3
1022    pub const F3: Key = Key { bits: 0xffbd + 3 };
1023    /// F4
1024    pub const F4: Key = Key { bits: 0xffbd + 4 };
1025    /// F5
1026    pub const F5: Key = Key { bits: 0xffbd + 5 };
1027    /// F6
1028    pub const F6: Key = Key { bits: 0xffbd + 6 };
1029    /// F7
1030    pub const F7: Key = Key { bits: 0xffbd + 7 };
1031    /// F8
1032    pub const F8: Key = Key { bits: 0xffbd + 8 };
1033    /// F9
1034    pub const F9: Key = Key { bits: 0xffbd + 9 };
1035    /// F10
1036    pub const F10: Key = Key { bits: 0xffbd + 10 };
1037    /// F11
1038    pub const F11: Key = Key { bits: 0xffbd + 11 };
1039    /// F12
1040    pub const F12: Key = Key { bits: 0xffbd + 12 };
1041    /// Function key last
1042    pub const FLast: Key = Key { bits: 0xffe0 };
1043    /// Shift Left
1044    pub const ShiftL: Key = Key { bits: 0xffe1 };
1045    /// Shift Right
1046    pub const ShiftR: Key = Key { bits: 0xffe2 };
1047    /// Control Left
1048    pub const ControlL: Key = Key { bits: 0xffe3 };
1049    /// Control Right
1050    pub const ControlR: Key = Key { bits: 0xffe4 };
1051    /// Caps Lock
1052    pub const CapsLock: Key = Key { bits: 0xffe5 };
1053    /// Meta Left
1054    pub const MetaL: Key = Key { bits: 0xffe7 };
1055    /// Meta Right
1056    pub const MetaR: Key = Key { bits: 0xffe8 };
1057    /// Alt Left
1058    pub const AltL: Key = Key { bits: 0xffe9 };
1059    /// Alt Right
1060    pub const AltR: Key = Key { bits: 0xffea };
1061    /// Delete
1062    pub const Delete: Key = Key { bits: 0xffff };
1063    /// Gets the i32 value of a Key
1064    pub const fn bits(&self) -> i32 {
1065        self.bits
1066    }
1067    /// Gets a Key from an i32
1068    pub const fn from_i32(val: i32) -> Key {
1069        Key { bits: val }
1070    }
1071
1072    /// Gets a Key from a char
1073    pub const fn from_char(val: char) -> Key {
1074        Key { bits: val as i32 }
1075    }
1076
1077    /// Get the char representation of a Key.
1078    pub const fn to_char(&self) -> Option<char> {
1079        let bits = self.bits();
1080        if bits >= 0xD800 && bits <= 0xDFFF {
1081            None
1082        } else {
1083            Some(bits as u8 as char)
1084        }
1085    }
1086
1087    /// Returns whether a key is a function key
1088    pub const fn is_fn_key(key: Key) -> bool {
1089        key.bits() >= Key::F1.bits() && key.bits() < Key::FLast.bits()
1090    }
1091
1092    /// Return the corresponding function key
1093    pub const fn fn_key(val: i32) -> Key {
1094        Key::from_i32(Key::F1.bits() - 1 + val)
1095    }
1096}
1097
1098#[allow(unreachable_patterns)]
1099impl std::fmt::Debug for Key {
1100    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
1101        match *self {
1102            Key::None => write!(f, "Key::None"),
1103            Key::Button => write!(f, "Key::Button"),
1104            Key::BackSpace => write!(f, "Key::BackSpace"),
1105            Key::Tab => write!(f, "Key::Tab"),
1106            Key::IsoKey => write!(f, "Key::IsoKey"),
1107            Key::Enter => write!(f, "Key::Enter"),
1108            Key::Pause => write!(f, "Key::Pause"),
1109            Key::ScrollLock => write!(f, "Key::ScrollLock"),
1110            Key::Escape => write!(f, "Key::Escape"),
1111            Key::Kana => write!(f, "Key::Kana"),
1112            Key::Eisu => write!(f, "Key::Eisu"),
1113            Key::Yen => write!(f, "Key::Yen"),
1114            Key::JISUnderscore => write!(f, "Key::JISUnderscore"),
1115            Key::Home => write!(f, "Key::Home"),
1116            Key::Left => write!(f, "Key::Left"),
1117            Key::Up => write!(f, "Key::Up"),
1118            Key::Right => write!(f, "Key::Right"),
1119            Key::Down => write!(f, "Key::Down"),
1120            Key::PageUp => write!(f, "Key::PageUp"),
1121            Key::PageDown => write!(f, "Key::PageDown"),
1122            Key::End => write!(f, "Key::End"),
1123            Key::Print => write!(f, "Key::Print"),
1124            Key::Insert => write!(f, "Key::Insert"),
1125            Key::Menu => write!(f, "Key::Menu"),
1126            Key::Help => write!(f, "Key::Help"),
1127            Key::NumLock => write!(f, "Key::NumLock"),
1128            Key::KP => write!(f, "Key::KP"),
1129            Key::KPEnter => write!(f, "Key::KPEnter"),
1130            Key::KPLast => write!(f, "Key::KPLast"),
1131            Key::F1 => write!(f, "Key::F1"),
1132            Key::F2 => write!(f, "Key::F2"),
1133            Key::F3 => write!(f, "Key::F3"),
1134            Key::F4 => write!(f, "Key::F4"),
1135            Key::F5 => write!(f, "Key::F5"),
1136            Key::F6 => write!(f, "Key::F6"),
1137            Key::F7 => write!(f, "Key::F7"),
1138            Key::F8 => write!(f, "Key::F8"),
1139            Key::F9 => write!(f, "Key::F9"),
1140            Key::F10 => write!(f, "Key::F10"),
1141            Key::F11 => write!(f, "Key::F11"),
1142            Key::F12 => write!(f, "Key::F12"),
1143            Key::FLast => write!(f, "Key::FLast"),
1144            Key::ShiftL => write!(f, "Key::ShiftL"),
1145            Key::ShiftR => write!(f, "Key::ShiftR"),
1146            Key::ControlL => write!(f, "Key::ControlL"),
1147            Key::ControlR => write!(f, "Key::ControlR"),
1148            Key::CapsLock => write!(f, "Key::CapsLock"),
1149            Key::MetaL => write!(f, "Key::MetaL"),
1150            Key::MetaR => write!(f, "Key::MetaR"),
1151            Key::AltL => write!(f, "Key::AltL"),
1152            Key::AltR => write!(f, "Key::AltR"),
1153            Key::Delete => write!(f, "Key::Delete"),
1154            _ => {
1155                write!(f, "Key::from_i32({})", self.bits())
1156            }
1157        }
1158    }
1159}
1160
1161bitflags::bitflags! {
1162    /// Defines the modifiers of virtual keycodes
1163    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1164    pub struct Shortcut: i32 {
1165        /// None
1166        const None = 0;
1167        /// Shift
1168        const Shift = 0x0001_0000;
1169        /// Caps Lock
1170        const CapsLock = 0x0002_0000;
1171        /// Ctrl
1172        const Ctrl = 0x0004_0000;
1173        /// Alt
1174        const Alt = 0x0008_0000;
1175        /// Meta
1176        const Meta = 0x0040_0000;
1177        /// Command (Meta for macOS, Ctrl for other systems)
1178        const Command = if cfg!(target_os = "macos") {
1179            Shortcut::Meta.bits()
1180        } else {
1181            Shortcut::Ctrl.bits()
1182        };
1183        /// Control (Ctrl for macOS, Meta for other systems)
1184        const Control = if cfg!(target_os = "macos") {
1185            Shortcut::Ctrl.bits()
1186        } else {
1187            Shortcut::Meta.bits()
1188        };
1189        /// Mouse button 1 is pushed
1190        const Button1 = 0x0100_0000;
1191        /// Mouse button 2 is pushed
1192        const Button2 = 0x0200_0000;
1193        /// Mouse button 3 is pushed
1194        const Button3 = 0x0400_0000;
1195        /// Mouse button 4 is pushed
1196        const Button4 = 0x0800_0000;
1197        /// Mouse button 5 is pushed
1198        const Button5 = 0x1000_0000;
1199        /// Any mouse button is pushed
1200        const Buttons = 0x1f00_0000;
1201    }
1202}
1203
1204/// Alias reflecting FLTK's name
1205pub type EventState = Shortcut;
1206
1207impl Shortcut {
1208    /// Create a shortcut from a char
1209    pub const fn from_char(c: char) -> Shortcut {
1210        Shortcut::from_bits_retain(c as _)
1211    }
1212
1213    /// Create a shortcut from a key
1214    pub const fn from_key(k: Key) -> Shortcut {
1215        Shortcut::from_bits_retain(k.bits())
1216    }
1217
1218    /// Create a shortcut from an i32
1219    pub const fn from_i32(v: i32) -> Shortcut {
1220        Shortcut::from_bits_retain(v)
1221    }
1222
1223    /// get key mask
1224    pub const fn key(&self) -> Key {
1225        let mut temp = self.bits();
1226        temp &= 0x0000_ffff;
1227        Key::from_i32(temp)
1228    }
1229
1230    /// Get the button number
1231    pub const fn button(button_num: i32) -> Shortcut {
1232        Shortcut::from_bits_retain(0x0080_0000 << button_num)
1233    }
1234}
1235
1236bitflags::bitflags! {
1237    /// Defines the types of triggers for widget callback functions. Equivalent to FL_WHEN
1238    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1239    pub struct When: i32 {
1240        /// Never
1241        const Never = 0;
1242        /// Changed
1243        const Changed = 1;
1244        /// Not Changed
1245        const NotChanged = 2;
1246        /// Release
1247        const Release = 4;
1248        /// Release Always
1249        const ReleaseAlways = 6;
1250        /// Enter Key
1251        const EnterKey = 8;
1252        /// Enter Key Always
1253        const EnterKeyAlways = 10;
1254        /// Enter Key and Changed
1255        const EnterKeyChanged = 11;
1256        /// A child widget is closed (in a Tabs widget)
1257        const Closed = 16;
1258    }
1259}
1260
1261/// Defines the callback reasons which can be queried using `app::callback_reason()`.
1262#[repr(i32)]
1263#[non_exhaustive]
1264#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1265pub enum CallbackReason {
1266    /// Unknown reason
1267    Unknown,
1268    /// Item was selected
1269    Selected,
1270    /// Item was deselected
1271    Deselected,
1272    /// Item was reselected
1273    Reselected,
1274    /// Item was opened
1275    Opened,
1276    /// Item was closed
1277    Closed,
1278    /// Item was dragged
1279    Dragged,
1280    /// Operation cancelled
1281    Cancelled,
1282    /// Item was changed
1283    Changed,
1284    /// Item got focus
1285    GotFocus,
1286    /// Item lost focus
1287    LostFocus,
1288    /// Item released
1289    Released,
1290}
1291
1292/// Defines the cursor styles supported by fltk
1293#[repr(i32)]
1294#[derive(Debug, Copy, Clone, PartialEq, Eq)]
1295pub enum Cursor {
1296    /// Default
1297    Default = 0,
1298    /// Arrow
1299    Arrow = 35,
1300    /// Cross
1301    Cross = 66,
1302    /// Wait
1303    Wait = 76,
1304    /// Insert
1305    Insert = 77,
1306    /// Hand
1307    Hand = 31,
1308    /// Help
1309    Help = 47,
1310    /// Move
1311    Move = 27,
1312    /// North South
1313    NS = 78,
1314    /// West East
1315    WE = 79,
1316    /// North West - South East
1317    NWSE = 80,
1318    /// North East - South West
1319    NESW = 81,
1320    /// North
1321    N = 70,
1322    /// North East
1323    NE = 69,
1324    /// East
1325    E = 49,
1326    /// South East
1327    SE = 8,
1328    /// South
1329    S = 9,
1330    /// South West
1331    SW = 7,
1332    /// West
1333    W = 36,
1334    /// North West
1335    NW = 68,
1336    /// None
1337    None = 255,
1338}
1339
1340bitflags::bitflags! {
1341    /// Defines visual mode types (capabilities of the window).
1342    /// Rgb and Single have a value of zero, so they
1343    /// are "on" unless you give Index or Double.
1344    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1345    pub struct Mode: i32 {
1346        /// Rgb color (not indexed)
1347        const Rgb = 0;
1348        /// Single buffered
1349        const Single = 0;
1350        /// Indexed mode
1351        const Index = 1;
1352        /// Double buffered
1353        const Double = 2;
1354        /// Accumulation buffer
1355        const Accum = 4;
1356        /// Alpha channel in color
1357        const Alpha = 8;
1358        /// Depth buffer
1359        const Depth = 16;
1360        /// Stencil buffer
1361        const Stencil = 32;
1362        /// Rgb8 color with at least 8 bits of each color
1363        const Rgb8 = 64;
1364        /// MultiSample anti-aliasing
1365        const MultiSample = 128;
1366        /// Stereoscopic rendering
1367        const Stereo = 256;
1368        /// Fake single buffered windows using double-buffer
1369        const FakeSingle = 512; //
1370        /// Use OpenGL version 3.0 or more
1371        const Opengl3 = 1024;
1372    }
1373}
1374
1375bitflags::bitflags! {
1376    /// Damage masks
1377    #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1378    pub struct Damage: u8 {
1379        /// No damage
1380        const  None = 0x00;
1381        /// A child needs to be redrawn.
1382        const  Child    = 0x01;
1383        /// The window was exposed.
1384        const Expose   = 0x02;
1385        /// The Fl_Scroll widget was scrolled.
1386        const Scroll   = 0x04;
1387        /// The overlay planes need to be redrawn.
1388        const Overlay  = 0x08;
1389        /// First user-defined damage bit.
1390        const User1    = 0x10;
1391        /// Second user-defined damage bit.
1392        const User2    = 0x20;
1393        /// Everything needs to be redrawn.
1394        const All     = 0x80;
1395    }
1396}
1397
1398impl std::ops::BitOr<char> for Shortcut {
1399    type Output = Shortcut;
1400    fn bitor(self, other: char) -> Self::Output {
1401        unsafe { mem::transmute(self.bits() | other as i32) }
1402    }
1403}
1404
1405impl std::ops::BitOr<Key> for Shortcut {
1406    type Output = Shortcut;
1407    fn bitor(self, other: Key) -> Self::Output {
1408        unsafe { mem::transmute(self.bits() | other.bits()) }
1409    }
1410}
1411
1412impl std::ops::BitOr<i32> for Align {
1413    type Output = Align;
1414    fn bitor(self, rhs: i32) -> Self::Output {
1415        unsafe { mem::transmute(self.bits() | rhs) }
1416    }
1417}