<commit_before>
use color::Color;
use elmesque::Element;
use graph::Graph;
use graphics::{Context, Graphics};
use graphics::character::CharacterCache;
use label::FontSize;
use mouse::{ButtonState, Mouse, Scroll};
use input;
use input::{
    GenericEvent,
    MouseCursorEvent,
    MouseScrollEvent,
    PressEvent,
    ReleaseEvent,
    RenderEvent,
    TextEvent,
};
use position::{Dimensions, HorizontalAlign, Padding, Point, Position, VerticalAlign};
use std::any::Any;
use std::cell::RefCell;
use std::io::Write;
use theme::Theme;
use widget::{self, Widget, WidgetId};


/// Indicates whether or not the Mouse has been captured by a widget.
#[derive(Copy, Clone, Debug)]
enum Capturing {
    /// The Ui is captured by the Ui element with the given WidgetId.
    Captured(WidgetId),
    /// The Ui has just been uncaptured.
    JustReleased,
}

/// `Ui` is the most important type within Conrod and is necessary for rendering and maintaining
/// widget state.
/// # Ui Handles the following:
/// * Contains the state of all widgets which can be indexed via their WidgetId.
/// * Stores rendering state for each widget until the end of each render cycle.
/// * Contains the theme used for default styling of the widgets.
/// * Maintains the latest user input state (for mouse and keyboard).
/// * Maintains the latest window dimensions.
pub struct Ui<C> {
    /// The theme used to set default styling for widgets.
    pub theme: Theme,
    /// Cache for character textures, used for label width calculation and glyph rendering.
    pub glyph_cache: GlyphCache<C>,
    /// Window width.
    pub win_w: f64,
    /// Window height.
    pub win_h: f64,
    /// The Widget cache, storing state for all widgets.
    widget_graph: Graph,
    /// The latest received mouse state.
    mouse: Mouse,
    /// Keys that have been pressed since the end of the last render cycle.
    keys_just_pressed: Vec<input::keyboard::Key>,
    /// Keys that have been released since the end of the last render cycle.
    keys_just_released: Vec<input::keyboard::Key>,
    /// Text that has been entered since the end of the last render cycle.
    text_just_entered: Vec<String>,
    /// Tracks whether or not the previous event was a Render event.
    prev_event_was_render: bool,
    /// The WidgetId of the widget that was last updated/set.
    maybe_prev_widget_id: Option<WidgetId>,
    /// The WidgetId of the last widget used as a parent for another widget.
    maybe_current_parent_id: Option<WidgetId>,
    /// If the mouse is currently over a widget, its ID will be here.
    maybe_widget_under_mouse: Option<WidgetId>,
    /// The WidgetId of the widget currently capturing mouse input if there is one.
    maybe_captured_mouse: Option<Capturing>,
    /// The WidgetId of the widget currently capturing keyboard input if there is one.
    maybe_captured_keyboard: Option<Capturing>,
    /// Whether or not the `Ui` needs to be re-drawn to screen.
    redraw_count: u8,
    /// A background color to clear the screen with before drawing if one was given.
    maybe_background_color: Option<Color>,
}

/// A wrapper over the current user input state.
#[derive(Clone, Debug)]
pub struct UserInput<'a> {
    /// Mouse state if it is available.
    pub maybe_mouse: Option<Mouse>,
    /// Keys pressed since the last cycle.
    pub pressed_keys: &'a [input::keyboard::Key],
    /// Keys released since the last cycle.
    pub released_keys: &'a [input::keyboard::Key],
    /// Text entered since the last cycle.
    pub entered_text: &'a [String],
    /// Current dimensions of the window.
    pub window_dim: Dimensions,
}

/// A wrapper over some CharacterCache, exposing it's functionality via a RefCell.
pub struct GlyphCache<C>(RefCell<C>);


impl<C> GlyphCache<C> where C: CharacterCache {
    /// Return the width of a character.
    pub fn char_width(&self, font_size: FontSize, ch: char) -> f64 {
        self.0.borrow_mut().character(font_size, ch).width()
    }
    /// Return the width of the given text.
    pub fn width(&self, font_size: FontSize, text: &str) -> f64 {
        self.0.borrow_mut().width(font_size, text)
    }
}

impl<C> ::std::ops::Deref for GlyphCache<C> {
    type Target = RefCell<C>;
    fn deref<'a>(&'a self) -> &'a RefCell<C> { &self.0 }
}

impl<C> ::std::ops::DerefMut for GlyphCache<C> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut RefCell<C> { &mut self.0 }
}


/// Each time conrod is required to redraw the GUI, it must draw for at least the next three frames
/// to ensure that, in the case that graphics buffers are being swapped, we have filled each
/// buffer. Otherwise if we don't draw into each buffer, we will probably be subject to flickering.
pub const SAFE_REDRAW_COUNT: u8 = 3;


impl<C> Ui<C> {

    /// Constructor for a UiContext.
    pub fn new(character_cache: C, theme: Theme) -> Ui<C> {
        const GRAPH_CAPACITY: usize = 512;
        Ui {
            widget_graph: Graph::with_capacity(GRAPH_CAPACITY),
            theme: theme,
            mouse: Mouse::new([0.0, 0.0], ButtonState::Up, ButtonState::Up, ButtonState::Up),
            keys_just_pressed: Vec::with_capacity(10),
            keys_just_released: Vec::with_capacity(10),
            text_just_entered: Vec::with_capacity(10),
            glyph_cache: GlyphCache(RefCell::new(character_cache)),
            prev_event_was_render: false,
            win_w: 0.0,
            win_h: 0.0,
            maybe_prev_widget_id: None,
            maybe_current_parent_id: None,
            maybe_widget_under_mouse: None,
            maybe_captured_mouse: None,
            maybe_captured_keyboard: None,
            redraw_count: SAFE_REDRAW_COUNT,
            maybe_background_color: None,
        }
    }

    /// Return the dimensions of a widget.
    pub fn widget_size(&self, id: WidgetId) -> Dimensions {
        self.widget_graph[id].dim
    }

    /// Handle game events and update the state.
    pub fn handle_event<E: GenericEvent>(&mut self, event: &E) {

        // The `Ui` tracks various things during a frame - we'll reset those things here.
        if self.prev_event_was_render {

            // Flush input.
            self.keys_just_pressed.clear();
            self.keys_just_released.clear();
            self.text_just_entered.clear();
            self.mouse.scroll = Scroll { x: 0.0, y: 0.0 };

            self.maybe_prev_widget_id = None;
            self.maybe_current_parent_id = None;
            self.prev_event_was_render = false;
            if let Some(Capturing::JustReleased) = self.maybe_captured_mouse {
                self.maybe_captured_mouse = None;
            }
            if let Some(Capturing::JustReleased) = self.maybe_captured_keyboard {
                self.maybe_captured_keyboard = None;
            }
        }

        event.render(|args| {
            self.win_w = args.width as f64;
            self.win_h = args.height as f64;
            self.prev_event_was_render = true;
            self.maybe_widget_under_mouse = self.widget_graph.pick_widget(self.mouse.xy);
        });

        event.mouse_cursor(|x, y| {
            // Convert mouse coords to (0, 0) origin.
            self.mouse.xy = [x - self.win_w / 2.0, -(y - self.win_h / 2.0)];
        });

        event.mouse_scroll(|x, y| {
            self.mouse.scroll.x += x;
            self.mouse.scroll.y += y;
        });

        event.press(|button_type| {
            use input::Button;
            use input::MouseButton::{Left, Middle, Right};

            match button_type {
                Button::Mouse(button) => {
                    *match button {
                        Left => &mut self.mouse.left,
                        Right => &mut self.mouse.right,
                        Middle => &mut self.mouse.middle,
                        _ => &mut self.mouse.unknown,
                    } = ButtonState::Down;
                },
                Button::Keyboard(key) => self.keys_just_pressed.push(key),
            }
        });

        event.release(|button_type| {
            use input::Button;
            use input::MouseButton::Left;
            match button_type {
                Button::Mouse(button) => {
                    *match button {
                        Left => &mut self.mouse.left,
                        _/*input::mouse::Right*/ => &mut self.mouse.right,
                        //Middle => &mut self.mouse.middle,
                    } = ButtonState::Up;
                },
                Button::Keyboard(key) => self.keys_just_released.push(key),
            }
        });

        event.text(|text| {
            self.text_just_entered.push(text.to_string())
        });
    }

    /// Get the centred xy coords for some given `Dimension`s, `Position` and alignment.
    pub fn get_xy(&self,
                  position: Position,
                  dim: Dimensions,
                  h_align: HorizontalAlign,
                  v_align: VerticalAlign) -> Point {
        match position {

            Position::Absolute(x, y) => [x, y],

            Position::Relative(x, y, maybe_id) => {
                match maybe_id.or(self.maybe_prev_widget_id.map(|id| id)) {
                    None => [0.0, 0.0],
                    Some(id) => ::vecmath::vec2_add(self.widget_graph[id].xy, [x, y]),
                }
            },

            Position::Direction(direction, px, maybe_id) => {
                match maybe_id.or(self.maybe_prev_widget_id.map(|id| id)) {
                    None => [0.0, 0.0],
                    Some(rel_id) => {
                        use position::Direction;
                        let (rel_xy, element) = {
                            let widget = &self.widget_graph[rel_id];
                            (widget.xy, &widget.element)
                        };
                        let (rel_w, rel_h) = element.get_size();
                        let (rel_w, rel_h) = (rel_w as f64, rel_h as f64);

                        match direction {

                            // For vertical directions, we must consider horizontal alignment.
                            Direction::Up | Direction::Down => {
                                // Check whether or not we are aligning to a specific `Ui` element.
                                let (other_x, other_w) = match h_align.1 {
                                    Some(other_id) => {
                                        let (x, elem) = {
                                            let widget = &self.widget_graph[other_id];
                                            (widget.xy[0], &widget.element)
                                        };
                                        let w = elem.get_width() as f64;
                                        (x, w)
                                    },
                                    None => (rel_xy[0], rel_w),
                                };
                                let x = other_x + h_align.0.to(other_w, dim[0]);
                                let y = match direction {
                                    Direction::Up   => rel_xy[1] + rel_h / 2.0 + dim[1] / 2.0 + px,
                                    Direction::Down => rel_xy[1] - rel_h / 2.0 - dim[1] / 2.0 - px,
                                    _ => unreachable!(),
                                };
                                [x, y]
                            },

                            // For horizontal directions, we must consider vertical alignment.
                            Direction::Left | Direction::Right => {
                                // Check whether or not we are aligning to a specific `Ui` element.
                                let (other_y, other_h) = match h_align.1 {
                                    Some(other_id) => {
                                        let (y, elem) = {
                                            let widget = &self.widget_graph[other_id];
                                            (widget.xy[1], &widget.element)
                                        };
                                        let h = elem.get_height() as f64;
                                        (y, h)
                                    },
                                    None => (rel_xy[1], rel_h),
                                };
                                let y = other_y + v_align.0.to(other_h, dim[1]);
                                let x = match direction {
                                    Direction::Left  => rel_xy[0] - rel_w / 2.0 - dim[0] / 2.0 - px,
                                    Direction::Right => rel_xy[0] + rel_w / 2.0 + dim[0] / 2.0 + px,
                                    _ => unreachable!(),
                                };
                                [x, y]
                            },

                        }
                    },
                }
            },

            Position::Place(place, maybe_parent_id) => {
                let window = || ([0.0, 0.0], [self.win_w, self.win_h], Padding::none());
                let (xy, target_dim, pad) = match maybe_parent_id.or(self.maybe_current_parent_id) {
                    Some(parent_id) => match self.widget_graph.get_widget(parent_id) {
                        Some(parent) =>
                            (parent.kid_area.xy, parent.kid_area.dim, parent.kid_area.pad),
                        // Sometimes the children are placed prior to their parents being set for
                        // the first time. If this is the case, we'll just place them on the window
                        // until we have information about the parents on the next update.
                        None => window(),
                    },
                    None => window(),
                };
                let place_xy = place.within(target_dim, dim);
                let relative_xy = ::vecmath::vec2_add(place_xy, pad.offset_from(place));
                ::vecmath::vec2_add(xy, relative_xy)
            },

        }
    }


    /// Tells the `Ui` that it needs to be re-draw everything. It does this by setting the redraw
    /// count to a `SAFE_REDRAW_COUNT`. See the docs for SAFE_REDRAW_COUNT or `draw_if_changed` for
    /// more info on how/why the redraw count is used.
    pub fn needs_redraw(&mut self) {
        self.redraw_count = SAFE_REDRAW_COUNT;
    }

<commit_msg>Added a method for manually setting the redraw_count<commit_after>
use color::Color;
use elmesque::Element;
use graph::Graph;
use graphics::{Context, Graphics};
use graphics::character::CharacterCache;
use label::FontSize;
use mouse::{ButtonState, Mouse, Scroll};
use input;
use input::{
    GenericEvent,
    MouseCursorEvent,
    MouseScrollEvent,
    PressEvent,
    ReleaseEvent,
    RenderEvent,
    TextEvent,
};
use position::{Dimensions, HorizontalAlign, Padding, Point, Position, VerticalAlign};
use std::any::Any;
use std::cell::RefCell;
use std::io::Write;
use theme::Theme;
use widget::{self, Widget, WidgetId};


/// Indicates whether or not the Mouse has been captured by a widget.
#[derive(Copy, Clone, Debug)]
enum Capturing {
    /// The Ui is captured by the Ui element with the given WidgetId.
    Captured(WidgetId),
    /// The Ui has just been uncaptured.
    JustReleased,
}

/// `Ui` is the most important type within Conrod and is necessary for rendering and maintaining
/// widget state.
/// # Ui Handles the following:
/// * Contains the state of all widgets which can be indexed via their WidgetId.
/// * Stores rendering state for each widget until the end of each render cycle.
/// * Contains the theme used for default styling of the widgets.
/// * Maintains the latest user input state (for mouse and keyboard).
/// * Maintains the latest window dimensions.
pub struct Ui<C> {
    /// The theme used to set default styling for widgets.
    pub theme: Theme,
    /// Cache for character textures, used for label width calculation and glyph rendering.
    pub glyph_cache: GlyphCache<C>,
    /// Window width.
    pub win_w: f64,
    /// Window height.
    pub win_h: f64,
    /// The Widget cache, storing state for all widgets.
    widget_graph: Graph,
    /// The latest received mouse state.
    mouse: Mouse,
    /// Keys that have been pressed since the end of the last render cycle.
    keys_just_pressed: Vec<input::keyboard::Key>,
    /// Keys that have been released since the end of the last render cycle.
    keys_just_released: Vec<input::keyboard::Key>,
    /// Text that has been entered since the end of the last render cycle.
    text_just_entered: Vec<String>,
    /// Tracks whether or not the previous event was a Render event.
    prev_event_was_render: bool,
    /// The WidgetId of the widget that was last updated/set.
    maybe_prev_widget_id: Option<WidgetId>,
    /// The WidgetId of the last widget used as a parent for another widget.
    maybe_current_parent_id: Option<WidgetId>,
    /// If the mouse is currently over a widget, its ID will be here.
    maybe_widget_under_mouse: Option<WidgetId>,
    /// The WidgetId of the widget currently capturing mouse input if there is one.
    maybe_captured_mouse: Option<Capturing>,
    /// The WidgetId of the widget currently capturing keyboard input if there is one.
    maybe_captured_keyboard: Option<Capturing>,
    /// The number of frames that that will be used for the `redraw_count` when `need_redraw` is
    /// triggered.
    num_redraw_frames: u8,
    /// Whether or not the `Ui` needs to be re-drawn to screen.
    redraw_count: u8,
    /// A background color to clear the screen with before drawing if one was given.
    maybe_background_color: Option<Color>,
}

/// A wrapper over the current user input state.
#[derive(Clone, Debug)]
pub struct UserInput<'a> {
    /// Mouse state if it is available.
    pub maybe_mouse: Option<Mouse>,
    /// Keys pressed since the last cycle.
    pub pressed_keys: &'a [input::keyboard::Key],
    /// Keys released since the last cycle.
    pub released_keys: &'a [input::keyboard::Key],
    /// Text entered since the last cycle.
    pub entered_text: &'a [String],
    /// Current dimensions of the window.
    pub window_dim: Dimensions,
}

/// A wrapper over some CharacterCache, exposing it's functionality via a RefCell.
pub struct GlyphCache<C>(RefCell<C>);


impl<C> GlyphCache<C> where C: CharacterCache {
    /// Return the width of a character.
    pub fn char_width(&self, font_size: FontSize, ch: char) -> f64 {
        self.0.borrow_mut().character(font_size, ch).width()
    }
    /// Return the width of the given text.
    pub fn width(&self, font_size: FontSize, text: &str) -> f64 {
        self.0.borrow_mut().width(font_size, text)
    }
}

impl<C> ::std::ops::Deref for GlyphCache<C> {
    type Target = RefCell<C>;
    fn deref<'a>(&'a self) -> &'a RefCell<C> { &self.0 }
}

impl<C> ::std::ops::DerefMut for GlyphCache<C> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut RefCell<C> { &mut self.0 }
}


/// Each time conrod is required to redraw the GUI, it must draw for at least the next three frames
/// to ensure that, in the case that graphics buffers are being swapped, we have filled each
/// buffer. Otherwise if we don't draw into each buffer, we will probably be subject to flickering.
pub const SAFE_REDRAW_COUNT: u8 = 3;


impl<C> Ui<C> {

    /// Constructor for a UiContext.
    pub fn new(character_cache: C, theme: Theme) -> Ui<C> {
        const GRAPH_CAPACITY: usize = 512;
        Ui {
            widget_graph: Graph::with_capacity(GRAPH_CAPACITY),
            theme: theme,
            mouse: Mouse::new([0.0, 0.0], ButtonState::Up, ButtonState::Up, ButtonState::Up),
            keys_just_pressed: Vec::with_capacity(10),
            keys_just_released: Vec::with_capacity(10),
            text_just_entered: Vec::with_capacity(10),
            glyph_cache: GlyphCache(RefCell::new(character_cache)),
            prev_event_was_render: false,
            win_w: 0.0,
            win_h: 0.0,
            maybe_prev_widget_id: None,
            maybe_current_parent_id: None,
            maybe_widget_under_mouse: None,
            maybe_captured_mouse: None,
            maybe_captured_keyboard: None,
            num_redraw_frames: SAFE_REDRAW_COUNT,
            redraw_count: SAFE_REDRAW_COUNT,
            maybe_background_color: None,
        }
    }

    /// Return the dimensions of a widget.
    pub fn widget_size(&self, id: WidgetId) -> Dimensions {
        self.widget_graph[id].dim
    }

    /// Handle game events and update the state.
    pub fn handle_event<E: GenericEvent>(&mut self, event: &E) {

        // The `Ui` tracks various things during a frame - we'll reset those things here.
        if self.prev_event_was_render {

            // Flush input.
            self.keys_just_pressed.clear();
            self.keys_just_released.clear();
            self.text_just_entered.clear();
            self.mouse.scroll = Scroll { x: 0.0, y: 0.0 };

            self.maybe_prev_widget_id = None;
            self.maybe_current_parent_id = None;
            self.prev_event_was_render = false;
            if let Some(Capturing::JustReleased) = self.maybe_captured_mouse {
                self.maybe_captured_mouse = None;
            }
            if let Some(Capturing::JustReleased) = self.maybe_captured_keyboard {
                self.maybe_captured_keyboard = None;
            }
        }

        event.render(|args| {
            self.win_w = args.width as f64;
            self.win_h = args.height as f64;
            self.prev_event_was_render = true;
            self.maybe_widget_under_mouse = self.widget_graph.pick_widget(self.mouse.xy);
        });

        event.mouse_cursor(|x, y| {
            // Convert mouse coords to (0, 0) origin.
            self.mouse.xy = [x - self.win_w / 2.0, -(y - self.win_h / 2.0)];
        });

        event.mouse_scroll(|x, y| {
            self.mouse.scroll.x += x;
            self.mouse.scroll.y += y;
        });

        event.press(|button_type| {
            use input::Button;
            use input::MouseButton::{Left, Middle, Right};

            match button_type {
                Button::Mouse(button) => {
                    *match button {
                        Left => &mut self.mouse.left,
                        Right => &mut self.mouse.right,
                        Middle => &mut self.mouse.middle,
                        _ => &mut self.mouse.unknown,
                    } = ButtonState::Down;
                },
                Button::Keyboard(key) => self.keys_just_pressed.push(key),
            }
        });

        event.release(|button_type| {
            use input::Button;
            use input::MouseButton::Left;
            match button_type {
                Button::Mouse(button) => {
                    *match button {
                        Left => &mut self.mouse.left,
                        _/*input::mouse::Right*/ => &mut self.mouse.right,
                        //Middle => &mut self.mouse.middle,
                    } = ButtonState::Up;
                },
                Button::Keyboard(key) => self.keys_just_released.push(key),
            }
        });

        event.text(|text| {
            self.text_just_entered.push(text.to_string())
        });
    }

    /// Get the centred xy coords for some given `Dimension`s, `Position` and alignment.
    pub fn get_xy(&self,
                  position: Position,
                  dim: Dimensions,
                  h_align: HorizontalAlign,
                  v_align: VerticalAlign) -> Point {
        match position {

            Position::Absolute(x, y) => [x, y],

            Position::Relative(x, y, maybe_id) => {
                match maybe_id.or(self.maybe_prev_widget_id.map(|id| id)) {
                    None => [0.0, 0.0],
                    Some(id) => ::vecmath::vec2_add(self.widget_graph[id].xy, [x, y]),
                }
            },

            Position::Direction(direction, px, maybe_id) => {
                match maybe_id.or(self.maybe_prev_widget_id.map(|id| id)) {
                    None => [0.0, 0.0],
                    Some(rel_id) => {
                        use position::Direction;
                        let (rel_xy, element) = {
                            let widget = &self.widget_graph[rel_id];
                            (widget.xy, &widget.element)
                        };
                        let (rel_w, rel_h) = element.get_size();
                        let (rel_w, rel_h) = (rel_w as f64, rel_h as f64);

                        match direction {

                            // For vertical directions, we must consider horizontal alignment.
                            Direction::Up | Direction::Down => {
                                // Check whether or not we are aligning to a specific `Ui` element.
                                let (other_x, other_w) = match h_align.1 {
                                    Some(other_id) => {
                                        let (x, elem) = {
                                            let widget = &self.widget_graph[other_id];
                                            (widget.xy[0], &widget.element)
                                        };
                                        let w = elem.get_width() as f64;
                                        (x, w)
                                    },
                                    None => (rel_xy[0], rel_w),
                                };
                                let x = other_x + h_align.0.to(other_w, dim[0]);
                                let y = match direction {
                                    Direction::Up   => rel_xy[1] + rel_h / 2.0 + dim[1] / 2.0 + px,
                                    Direction::Down => rel_xy[1] - rel_h / 2.0 - dim[1] / 2.0 - px,
                                    _ => unreachable!(),
                                };
                                [x, y]
                            },

                            // For horizontal directions, we must consider vertical alignment.
                            Direction::Left | Direction::Right => {
                                // Check whether or not we are aligning to a specific `Ui` element.
                                let (other_y, other_h) = match h_align.1 {
                                    Some(other_id) => {
                                        let (y, elem) = {
                                            let widget = &self.widget_graph[other_id];
                                            (widget.xy[1], &widget.element)
                                        };
                                        let h = elem.get_height() as f64;
                                        (y, h)
                                    },
                                    None => (rel_xy[1], rel_h),
                                };
                                let y = other_y + v_align.0.to(other_h, dim[1]);
                                let x = match direction {
                                    Direction::Left  => rel_xy[0] - rel_w / 2.0 - dim[0] / 2.0 - px,
                                    Direction::Right => rel_xy[0] + rel_w / 2.0 + dim[0] / 2.0 + px,
                                    _ => unreachable!(),
                                };
                                [x, y]
                            },

                        }
                    },
                }
            },

            Position::Place(place, maybe_parent_id) => {
                let window = || ([0.0, 0.0], [self.win_w, self.win_h], Padding::none());
                let (xy, target_dim, pad) = match maybe_parent_id.or(self.maybe_current_parent_id) {
                    Some(parent_id) => match self.widget_graph.get_widget(parent_id) {
                        Some(parent) =>
                            (parent.kid_area.xy, parent.kid_area.dim, parent.kid_area.pad),
                        // Sometimes the children are placed prior to their parents being set for
                        // the first time. If this is the case, we'll just place them on the window
                        // until we have information about the parents on the next update.
                        None => window(),
                    },
                    None => window(),
                };
                let place_xy = place.within(target_dim, dim);
                let relative_xy = ::vecmath::vec2_add(place_xy, pad.offset_from(place));
                ::vecmath::vec2_add(xy, relative_xy)
            },

        }
    }


    /// Set the number of frames that the `Ui` should draw in the case that `needs_redraw` is
    /// called. The default is `3` (see the SAFE_REDRAW_COUNT docs for details).
    pub fn set_num_redraw_frames(&mut self, num_frames: u8) {
        self.num_redraw_frames = num_frames;
    }

    /// Tells the `Ui` that it needs to be re-draw everything. It does this by setting the redraw
    /// count to a `SAFE_REDRAW_COUNT`. See the docs for SAFE_REDRAW_COUNT or `draw_if_changed` for
    /// more info on how/why the redraw count is used.
    pub fn needs_redraw(&mut self) {
        self.redraw_count = self.num_redraw_frames;
    }


{'fraction_non_alphanumeric': 0.10486301369863013, 'fraction_numerical': 0.007157534246575343, 'mean_word_length': 1.5449712393236883, 'pattern_counts': {'":': 0, '<': 63, '<?xml version=': 0, '>': 147, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 92, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2386537', 'n_tokens_mistral': 8231, 'n_tokens_neox': 7874, 'n_words': 2298}