diff --git a/backends/conrod_example_shared/src/button_xy_pad_toggle.rs b/backends/conrod_example_shared/src/button_xy_pad_toggle.rs new file mode 100644 index 000000000..fb843fe51 --- /dev/null +++ b/backends/conrod_example_shared/src/button_xy_pad_toggle.rs @@ -0,0 +1,106 @@ + +use conrod_core::{ + Colorable, + Widget, + Labelable, + Positionable, + Rect, + Sizeable, + Ui, + UiCell, + widget, +}; + +use layout::*; + +widget_ids! { + pub struct Ids { + button_title, + button, + xy_pad, + toggle, + ball, + } +} + +pub struct GuiState { + ball_xy: conrod_core::Point, + ball_color: conrod_core::Color, +} + +impl GuiState { + pub fn new() -> Self { + Self { + ball_xy: [0.0, 0.0], + ball_color: conrod_core::color::WHITE, + } + } +} + +pub struct Gui { + ids: Ids, +} + +impl Gui { + pub fn new(ui: &mut Ui) -> Self { + Self { + ids: Ids::new(ui.widget_id_generator()), + } + } + + /// Returns id of widget that the next Gui should be down_from + pub fn update(&self, ui: &mut UiCell, state: &mut GuiState, canvas: widget::Id, last: widget::Id, rect: &Rect, side: f64) -> widget::Id { + let ids = &self.ids; + + widget::Text::new("Button, XYPad and Toggle") + .down_from(last, 60.0) + .align_middle_x_of(canvas) + .font_size(SUBTITLE_SIZE) + .set(ids.button_title, ui); + + for _press in widget::Button::new() + .label("PRESS ME") + .mid_left_with_margin_on(canvas, MARGIN) + .down_from(ids.button_title, 60.0) + .w_h(side, side) + .set(ids.button, ui) + { + let x = rand::random::() * (rect.x.end - rect.x.start) - rect.x.end; + let y = rand::random::() * (rect.y.end - rect.y.start) - rect.y.end; + state.ball_xy = [x, y]; + } + + for (x, y) in widget::XYPad::new(state.ball_xy[0], rect.x.start, rect.x.end, + state.ball_xy[1], rect.y.start, rect.y.end) + .label("BALL XY") + .wh_of(ids.button) + .align_middle_y_of(ids.button) + .align_middle_x_of(canvas) + .parent(canvas) + .set(ids.xy_pad, ui) + { + state.ball_xy = [x, y]; + } + + let is_white = state.ball_color == conrod_core::color::WHITE; + let label = if is_white { "WHITE" } else { "BLACK" }; + for is_white in widget::Toggle::new(is_white) + .label(label) + .label_color(if is_white { conrod_core::color::WHITE } else { conrod_core::color::LIGHT_CHARCOAL }) + .mid_right_with_margin_on(canvas, MARGIN) + .align_middle_y_of(ids.button) + .set(ids.toggle, ui) + { + state.ball_color = if is_white { conrod_core::color::WHITE } else { conrod_core::color::BLACK }; + } + + let ball_x = state.ball_xy[0]; + let ball_y = state.ball_xy[1] - rect.y.end - side * 0.5 - MARGIN; + widget::Circle::fill(20.0) + .color(state.ball_color) + .x_y_relative_to(ids.xy_pad, ball_x, ball_y) + .set(ids.ball, ui); + + ids.xy_pad // Return id of widget that the next Gui should be down_from + } +} diff --git a/backends/conrod_example_shared/src/image.rs b/backends/conrod_example_shared/src/image.rs new file mode 100644 index 000000000..0be4fe4de --- /dev/null +++ b/backends/conrod_example_shared/src/image.rs @@ -0,0 +1,49 @@ +use conrod_core::{ + Positionable, + Sizeable, + Ui, + UiCell, + Widget, + widget, +}; + +use layout::*; + +widget_ids! { + pub struct Ids { + image_title, + rust_logo, + } +} + +pub struct Gui { + ids: Ids, +} + +impl Gui { + pub fn new(ui: &mut Ui) -> Self { + Self { + ids: Ids::new(ui.widget_id_generator()), + } + } + + /// Returns id of widget that the next Gui should be down_from + pub fn update(&self, ui: &mut UiCell, rust_logo: conrod_core::image::Id, canvas: widget::Id, last: widget::Id) -> widget::Id { + let ids = &self.ids; + + widget::Text::new("Image") + .down_from(last, MARGIN) + .align_middle_x_of(canvas) + .font_size(SUBTITLE_SIZE) + .set(ids.image_title, ui); + + const LOGO_SIDE: conrod_core::Scalar = 144.0; + widget::Image::new(rust_logo) + .w_h(LOGO_SIDE, LOGO_SIDE) + .down(60.0) + .align_middle_x_of(canvas) + .set(ids.rust_logo, ui); + + ids.rust_logo // Return id of widget that the next Gui should be down_from + } +} diff --git a/backends/conrod_example_shared/src/layout.rs b/backends/conrod_example_shared/src/layout.rs new file mode 100644 index 000000000..e747fff22 --- /dev/null +++ b/backends/conrod_example_shared/src/layout.rs @@ -0,0 +1,6 @@ +use conrod_core::Scalar; + +pub const MARGIN: Scalar = 30.0; +pub const SHAPE_GAP: Scalar = 50.0; +pub const TITLE_SIZE: conrod_core::FontSize = 42; +pub const SUBTITLE_SIZE: conrod_core::FontSize = 32; diff --git a/backends/conrod_example_shared/src/lib.rs b/backends/conrod_example_shared/src/lib.rs index cd1a2586e..36387e0e4 100644 --- a/backends/conrod_example_shared/src/lib.rs +++ b/backends/conrod_example_shared/src/lib.rs @@ -13,13 +13,23 @@ #[macro_use] extern crate conrod_core; extern crate rand; +mod layout; +mod text; +mod shapes; +mod image; +mod button_xy_pad_toggle; +mod number_dialer_plotpath; + +use layout::*; + +use conrod_core::{widget, Rect, Ui, UiCell, Widget}; + pub const WIN_W: u32 = 600; pub const WIN_H: u32 = 420; /// A demonstration of some application state we want to control with a conrod GUI. pub struct DemoApp { - ball_xy: conrod_core::Point, - ball_color: conrod_core::Color, + button_xy_pad_toggle: button_xy_pad_toggle::GuiState, sine_frequency: f32, rust_logo: conrod_core::image::Id, } @@ -29,8 +39,7 @@ impl DemoApp { /// Simple constructor for the `DemoApp`. pub fn new(rust_logo: conrod_core::image::Id) -> Self { DemoApp { - ball_xy: [0.0, 0.0], - ball_color: conrod_core::color::WHITE, + button_xy_pad_toggle: button_xy_pad_toggle::GuiState::new(), sine_frequency: 1.0, rust_logo: rust_logo, } @@ -65,273 +74,63 @@ widget_ids! { pub struct Ids { // The scrollable canvas. canvas, - // The title and introduction widgets. - title, - introduction, - // Shapes. - shapes_canvas, - rounded_rectangle, - shapes_left_col, - shapes_right_col, - shapes_title, - line, - point_path, - rectangle_fill, - rectangle_outline, - trapezoid, - oval_fill, - oval_outline, - circle, - // Image. - image_title, - rust_logo, - // Button, XyPad, Toggle. - button_title, - button, - xy_pad, - toggle, - ball, - // NumberDialer, PlotPath - dialer_title, - number_dialer, - plot_path, // Scrollbar canvas_scrollbar, } } +pub struct Gui { + ids: Ids, + text: text::Gui, + shapes: shapes::Gui, + image: image::Gui, + button_xy_pad_toggle: button_xy_pad_toggle::Gui, + number_dialer_plotpath: number_dialer_plotpath::Gui, +} -/// Instantiate a GUI demonstrating every widget available in conrod. -pub fn gui(ui: &mut conrod_core::UiCell, ids: &Ids, app: &mut DemoApp) { - use conrod_core::{widget, Colorable, Labelable, Positionable, Sizeable, Widget}; - use std::iter::once; - - const MARGIN: conrod_core::Scalar = 30.0; - const SHAPE_GAP: conrod_core::Scalar = 50.0; - const TITLE_SIZE: conrod_core::FontSize = 42; - const SUBTITLE_SIZE: conrod_core::FontSize = 32; - - // `Canvas` is a widget that provides some basic functionality for laying out children widgets. - // By default, its size is the size of the window. We'll use this as a background for the - // following widgets, as well as a scrollable container for the children widgets. - const TITLE: &'static str = "All Widgets"; - widget::Canvas::new().pad(MARGIN).scroll_kids_vertically().set(ids.canvas, ui); - - - //////////////// - ///// TEXT ///// - //////////////// - - - // We'll demonstrate the `Text` primitive widget by using it to draw a title and an - // introduction to the example. - widget::Text::new(TITLE).font_size(TITLE_SIZE).mid_top_of(ids.canvas).set(ids.title, ui); - - const INTRODUCTION: &'static str = - "This example aims to demonstrate all widgets that are provided by conrod.\ - \n\nThe widget that you are currently looking at is the Text widget. The Text widget \ - is one of several special \"primitive\" widget types which are used to construct \ - all other widget types. These types are \"special\" in the sense that conrod knows \ - how to render them via `conrod_core::render::Primitive`s.\ - \n\nScroll down to see more widgets!"; - widget::Text::new(INTRODUCTION) - .padded_w_of(ids.canvas, MARGIN) - .down(60.0) - .align_middle_x_of(ids.canvas) - .center_justify() - .line_spacing(5.0) - .set(ids.introduction, ui); - - - //////////////////////////// - ///// Lines and Shapes ///// - //////////////////////////// - - - widget::Text::new("Lines and Shapes") - .down(70.0) - .align_middle_x_of(ids.canvas) - .font_size(SUBTITLE_SIZE) - .set(ids.shapes_title, ui); - - // Lay out the shapes in two horizontal columns. - // - // TODO: Have conrod provide an auto-flowing, fluid-list widget that is more adaptive for these - // sorts of situations. - widget::Canvas::new() - .down(0.0) - .align_middle_x_of(ids.canvas) - .kid_area_w_of(ids.canvas) - .h(360.0) - .color(conrod_core::color::TRANSPARENT) - .pad(MARGIN) - .flow_down(&[ - (ids.shapes_left_col, widget::Canvas::new()), - (ids.shapes_right_col, widget::Canvas::new()), - ]) - .set(ids.shapes_canvas, ui); - - let shapes_canvas_rect = ui.rect_of(ids.shapes_canvas).unwrap(); - let w = shapes_canvas_rect.w(); - let h = shapes_canvas_rect.h() * 5.0 / 6.0; - let radius = 10.0; - widget::RoundedRectangle::fill([w, h], radius) - .color(conrod_core::color::CHARCOAL.alpha(0.25)) - .middle_of(ids.shapes_canvas) - .set(ids.rounded_rectangle, ui); - - let start = [-40.0, -40.0]; - let end = [40.0, 40.0]; - widget::Line::centred(start, end).mid_left_of(ids.shapes_left_col).set(ids.line, ui); - - let left = [-40.0, -40.0]; - let top = [0.0, 40.0]; - let right = [40.0, -40.0]; - let points = once(left).chain(once(top)).chain(once(right)); - widget::PointPath::centred(points).right(SHAPE_GAP).set(ids.point_path, ui); - - widget::Rectangle::fill([80.0, 80.0]).right(SHAPE_GAP).set(ids.rectangle_fill, ui); - - widget::Rectangle::outline([80.0, 80.0]).right(SHAPE_GAP).set(ids.rectangle_outline, ui); - - let bl = [-40.0, -40.0]; - let tl = [-20.0, 40.0]; - let tr = [20.0, 40.0]; - let br = [40.0, -40.0]; - let points = once(bl).chain(once(tl)).chain(once(tr)).chain(once(br)); - widget::Polygon::centred_fill(points).mid_left_of(ids.shapes_right_col).set(ids.trapezoid, ui); - - widget::Oval::fill([40.0, 80.0]).right(SHAPE_GAP + 20.0).align_middle_y().set(ids.oval_fill, ui); - - widget::Oval::outline([80.0, 40.0]).right(SHAPE_GAP + 20.0).align_middle_y().set(ids.oval_outline, ui); - - widget::Circle::fill(40.0).right(SHAPE_GAP).align_middle_y().set(ids.circle, ui); - - - ///////////////// - ///// Image ///// - ///////////////// - - - widget::Text::new("Image") - .down_from(ids.shapes_canvas, MARGIN) - .align_middle_x_of(ids.canvas) - .font_size(SUBTITLE_SIZE) - .set(ids.image_title, ui); - - const LOGO_SIDE: conrod_core::Scalar = 144.0; - widget::Image::new(app.rust_logo) - .w_h(LOGO_SIDE, LOGO_SIDE) - .down(60.0) - .align_middle_x_of(ids.canvas) - .set(ids.rust_logo, ui); - - - ///////////////////////////////// - ///// Button, XYPad, Toggle ///// - ///////////////////////////////// - - - widget::Text::new("Button, XYPad and Toggle") - .down_from(ids.rust_logo, 60.0) - .align_middle_x_of(ids.canvas) - .font_size(SUBTITLE_SIZE) - .set(ids.button_title, ui); - - let ball_x_range = ui.kid_area_of(ids.canvas).unwrap().w(); - let ball_y_range = ui.h_of(ui.window).unwrap() * 0.5; - let min_x = -ball_x_range / 3.0; - let max_x = ball_x_range / 3.0; - let min_y = -ball_y_range / 3.0; - let max_y = ball_y_range / 3.0; - let side = 130.0; - - for _press in widget::Button::new() - .label("PRESS ME") - .mid_left_with_margin_on(ids.canvas, MARGIN) - .down_from(ids.button_title, 60.0) - .w_h(side, side) - .set(ids.button, ui) - { - let x = rand::random::() * (max_x - min_x) - max_x; - let y = rand::random::() * (max_y - min_y) - max_y; - app.ball_xy = [x, y]; +impl Gui { + pub fn new(ui: &mut Ui) -> Self { + Self { + ids: Ids::new(ui.widget_id_generator()), + text: text::Gui::new(ui), + shapes: shapes::Gui::new(ui), + image: image::Gui::new(ui), + button_xy_pad_toggle: button_xy_pad_toggle::Gui::new(ui), + number_dialer_plotpath: number_dialer_plotpath::Gui::new(ui), + } } - for (x, y) in widget::XYPad::new(app.ball_xy[0], min_x, max_x, - app.ball_xy[1], min_y, max_y) - .label("BALL XY") - .wh_of(ids.button) - .align_middle_y_of(ids.button) - .align_middle_x_of(ids.canvas) - .parent(ids.canvas) - .set(ids.xy_pad, ui) - { - app.ball_xy = [x, y]; - } + /// Instantiate a GUI demonstrating every widget available in conrod. + pub fn update(&self, ui: &mut UiCell, app: &mut DemoApp) { + let ids = &self.ids; + let canvas = ids.canvas; - let is_white = app.ball_color == conrod_core::color::WHITE; - let label = if is_white { "WHITE" } else { "BLACK" }; - for is_white in widget::Toggle::new(is_white) - .label(label) - .label_color(if is_white { conrod_core::color::WHITE } else { conrod_core::color::LIGHT_CHARCOAL }) - .mid_right_with_margin_on(ids.canvas, MARGIN) - .align_middle_y_of(ids.button) - .set(ids.toggle, ui) - { - app.ball_color = if is_white { conrod_core::color::WHITE } else { conrod_core::color::BLACK }; - } + // `Canvas` is a widget that provides some basic functionality for laying out children widgets. + // By default, its size is the size of the window. We'll use this as a background for the + // following widgets, as well as a scrollable container for the children widgets. + widget::Canvas::new().pad(MARGIN).scroll_kids_vertically().set(canvas, ui); - let ball_x = app.ball_xy[0]; - let ball_y = app.ball_xy[1] - max_y - side * 0.5 - MARGIN; - widget::Circle::fill(20.0) - .color(app.ball_color) - .x_y_relative_to(ids.xy_pad, ball_x, ball_y) - .set(ids.ball, ui); + let mut last = self.text.update(ui, canvas); + last = self.shapes.update(ui, canvas, last); - ////////////////////////////////// - ///// NumberDialer, PlotPath ///// - ////////////////////////////////// + last = self.image.update(ui, app.rust_logo, canvas, last); + let ball_x_range = ui.kid_area_of(canvas).unwrap().w(); + let ball_y_range = ui.h_of(ui.window).unwrap() * 0.5; + let rect = Rect::from_xy_dim([0.0, 0.0], [ball_x_range * 2.0 / 3.0, ball_y_range * 2.0 / 3.0]); + let side = 130.0; + + last = self.button_xy_pad_toggle.update(ui, &mut app.button_xy_pad_toggle, canvas, last, &rect, side); + + let space = rect.y.end - rect.y.start + side * 0.5 + MARGIN; + self.number_dialer_plotpath.update(ui, &mut app.sine_frequency, canvas, last, space); - widget::Text::new("NumberDialer and PlotPath") - .down_from(ids.xy_pad, max_y - min_y + side * 0.5 + MARGIN) - .align_middle_x_of(ids.canvas) - .font_size(SUBTITLE_SIZE) - .set(ids.dialer_title, ui); + ///////////////////// + ///// Scrollbar ///// + ///////////////////// - // Use a `NumberDialer` widget to adjust the frequency of the sine wave below. - let min = 0.5; - let max = 200.0; - let decimal_precision = 1; - for new_freq in widget::NumberDialer::new(app.sine_frequency, min, max, decimal_precision) - .down(60.0) - .align_middle_x_of(ids.canvas) - .w_h(160.0, 40.0) - .label("F R E Q") - .set(ids.number_dialer, ui) - { - app.sine_frequency = new_freq; + widget::Scrollbar::y_axis(canvas).auto_hide(true).set(ids.canvas_scrollbar, ui); } - // Use the `PlotPath` widget to display a sine wave. - let min_x = 0.0; - let max_x = std::f32::consts::PI * 2.0 * app.sine_frequency; - let min_y = -1.0; - let max_y = 1.0; - widget::PlotPath::new(min_x, max_x, min_y, max_y, f32::sin) - .kid_area_w_of(ids.canvas) - .h(240.0) - .down(60.0) - .align_middle_x_of(ids.canvas) - .set(ids.plot_path, ui); - - - ///////////////////// - ///// Scrollbar ///// - ///////////////////// - - - widget::Scrollbar::y_axis(ids.canvas).auto_hide(true).set(ids.canvas_scrollbar, ui); } diff --git a/backends/conrod_example_shared/src/number_dialer_plotpath.rs b/backends/conrod_example_shared/src/number_dialer_plotpath.rs new file mode 100644 index 000000000..c050a53b8 --- /dev/null +++ b/backends/conrod_example_shared/src/number_dialer_plotpath.rs @@ -0,0 +1,73 @@ + +use conrod_core::{ + Widget, + Labelable, + Positionable, + Scalar, + Sizeable, + Ui, + UiCell, + widget, +}; + +use layout::*; + +widget_ids! { + pub struct Ids { + dialer_title, + number_dialer, + plot_path, + } +} + +pub struct Gui { + ids: Ids, +} + +impl Gui { + pub fn new(ui: &mut Ui) -> Self { + Self { + ids: Ids::new(ui.widget_id_generator()), + } + } + + /// Returns id of widget that the next Gui should be down_from + pub fn update(&self, ui: &mut UiCell, sine_frequency: &mut f32, canvas: widget::Id, last: widget::Id, space: Scalar) -> widget::Id { + let ids = &self.ids; + + widget::Text::new("NumberDialer and PlotPath") + .down_from(last, space) + .align_middle_x_of(canvas) + .font_size(SUBTITLE_SIZE) + .set(ids.dialer_title, ui); + + // Use a `NumberDialer` widget to adjust the frequency of the sine wave below. + let min = 0.5; + let max = 200.0; + let decimal_precision = 1; + for new_freq in widget::NumberDialer::new(*sine_frequency, min, max, decimal_precision) + .down(60.0) + .align_middle_x_of(canvas) + .w_h(160.0, 40.0) + .label("F R E Q") + .set(ids.number_dialer, ui) + { + *sine_frequency = new_freq; + } + + // Use the `PlotPath` widget to display a sine wave. + let min_x = 0.0; + let max_x = std::f32::consts::PI * 2.0 * *sine_frequency; + let min_y = -1.0; + let max_y = 1.0; + widget::PlotPath::new(min_x, max_x, min_y, max_y, f32::sin) + .kid_area_w_of(canvas) + .h(240.0) + .down(60.0) + .align_middle_x_of(canvas) + .set(ids.plot_path, ui); + + ids.plot_path // Return id of widget that the next Gui should be down_from + } + +} diff --git a/backends/conrod_example_shared/src/shapes.rs b/backends/conrod_example_shared/src/shapes.rs new file mode 100644 index 000000000..5fd85ba77 --- /dev/null +++ b/backends/conrod_example_shared/src/shapes.rs @@ -0,0 +1,110 @@ + +use conrod_core::{ + Colorable, + Widget, + Positionable, + Sizeable, + Ui, + UiCell, + widget, +}; + +use layout::*; + +widget_ids! { + pub struct Ids { + shapes_canvas, + rounded_rectangle, + shapes_left_col, + shapes_right_col, + shapes_title, + line, + point_path, + rectangle_fill, + rectangle_outline, + trapezoid, + oval_fill, + oval_outline, + circle, + } +} + +pub struct Gui { + ids: Ids, +} + +impl Gui { + pub fn new(ui: &mut Ui) -> Self { + Self { + ids: Ids::new(ui.widget_id_generator()), + } + } + + /// Returns id of widget that the next Gui should be down_from + pub fn update(&self, ui: &mut UiCell, canvas: widget::Id, last: widget::Id) -> widget::Id { + use std::iter::once; + + let ids = &self.ids; + + widget::Text::new("Lines and Shapes") + .down_from(last, 70.0) + .align_middle_x_of(canvas) + .font_size(SUBTITLE_SIZE) + .set(ids.shapes_title, ui); + + // Lay out the shapes in two horizontal columns. + // + // TODO: Have conrod provide an auto-flowing, fluid-list widget that is more adaptive for these + // sorts of situations. + widget::Canvas::new() + .down(0.0) + .align_middle_x_of(canvas) + .kid_area_w_of(canvas) + .h(360.0) + .color(conrod_core::color::TRANSPARENT) + .pad(MARGIN) + .flow_down(&[ + (ids.shapes_left_col, widget::Canvas::new()), + (ids.shapes_right_col, widget::Canvas::new()), + ]) + .set(ids.shapes_canvas, ui); + + let shapes_canvas_rect = ui.rect_of(ids.shapes_canvas).unwrap(); + let w = shapes_canvas_rect.w(); + let h = shapes_canvas_rect.h() * 5.0 / 6.0; + let radius = 10.0; + widget::RoundedRectangle::fill([w, h], radius) + .color(conrod_core::color::CHARCOAL.alpha(0.25)) + .middle_of(ids.shapes_canvas) + .set(ids.rounded_rectangle, ui); + + let start = [-40.0, -40.0]; + let end = [40.0, 40.0]; + widget::Line::centred(start, end).mid_left_of(ids.shapes_left_col).set(ids.line, ui); + + let left = [-40.0, -40.0]; + let top = [0.0, 40.0]; + let right = [40.0, -40.0]; + let points = once(left).chain(once(top)).chain(once(right)); + widget::PointPath::centred(points).right(SHAPE_GAP).set(ids.point_path, ui); + + widget::Rectangle::fill([80.0, 80.0]).right(SHAPE_GAP).set(ids.rectangle_fill, ui); + + widget::Rectangle::outline([80.0, 80.0]).right(SHAPE_GAP).set(ids.rectangle_outline, ui); + + let bl = [-40.0, -40.0]; + let tl = [-20.0, 40.0]; + let tr = [20.0, 40.0]; + let br = [40.0, -40.0]; + let points = once(bl).chain(once(tl)).chain(once(tr)).chain(once(br)); + widget::Polygon::centred_fill(points).mid_left_of(ids.shapes_right_col).set(ids.trapezoid, ui); + + widget::Oval::fill([40.0, 80.0]).right(SHAPE_GAP + 20.0).align_middle_y().set(ids.oval_fill, ui); + + widget::Oval::outline([80.0, 40.0]).right(SHAPE_GAP + 20.0).align_middle_y().set(ids.oval_outline, ui); + + widget::Circle::fill(40.0).right(SHAPE_GAP).align_middle_y().set(ids.circle, ui); + + ids.shapes_canvas // Return id of widget that the next Gui should be down_from + } +} diff --git a/backends/conrod_example_shared/src/text.rs b/backends/conrod_example_shared/src/text.rs new file mode 100644 index 000000000..2d9f1137a --- /dev/null +++ b/backends/conrod_example_shared/src/text.rs @@ -0,0 +1,56 @@ +use conrod_core::{ + Positionable, + Sizeable, + Ui, + UiCell, + Widget, + widget, +}; + +use layout::*; + +widget_ids! { + pub struct Ids { + title, + introduction, + } +} + +pub struct Gui { + ids: Ids, +} + +impl Gui { + pub fn new(ui: &mut Ui) -> Self { + Self { + ids: Ids::new(ui.widget_id_generator()), + } + } + + /// Returns id of widget that the next Gui should be down_from + pub fn update(&self, ui: &mut UiCell, canvas: widget::Id) -> widget::Id { + let ids = &self.ids; + + // We'll demonstrate the `Text` primitive widget by using it to draw a title and an + // introduction to the example. + const TITLE: &'static str = "All Widgets"; + widget::Text::new(TITLE).font_size(TITLE_SIZE).mid_top_of(canvas).set(ids.title, ui); + + const INTRODUCTION: &'static str = + "This example aims to demonstrate all widgets that are provided by conrod.\ + \n\nThe widget that you are currently looking at is the Text widget. The Text widget \ + is one of several special \"primitive\" widget types which are used to construct \ + all other widget types. These types are \"special\" in the sense that conrod knows \ + how to render them via `conrod_core::render::Primitive`s.\ + \n\nScroll down to see more widgets!"; + widget::Text::new(INTRODUCTION) + .padded_w_of(canvas, MARGIN) + .down(60.0) + .align_middle_x_of(canvas) + .center_justify() + .line_spacing(5.0) + .set(ids.introduction, ui); + + ids.introduction // Return id of widget that the next Gui should be down_from + } +} diff --git a/backends/conrod_gfx/examples/all_winit_gfx.rs b/backends/conrod_gfx/examples/all_winit_gfx.rs index c7a1e76cd..c75505003 100644 --- a/backends/conrod_gfx/examples/all_winit_gfx.rs +++ b/backends/conrod_gfx/examples/all_winit_gfx.rs @@ -65,7 +65,7 @@ fn main() { let mut ui = conrod_core::UiBuilder::new([WIN_W as f64, WIN_H as f64]) .theme(conrod_example_shared::theme()) .build(); - let ids = conrod_example_shared::Ids::new(ui.widget_id_generator()); + let gui = conrod_example_shared::Gui::new(&mut ui); // Load font from file let assets = find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap(); @@ -167,8 +167,8 @@ fn main() { // Update widgets if any event has happened if ui.global_input().events().next().is_some() { - let mut ui = ui.set_widgets(); - conrod_example_shared::gui(&mut ui, &ids, &mut app); + let mut ui = &mut ui.set_widgets(); + gui.update(&mut ui, &mut app); } } } diff --git a/backends/conrod_glium/examples/all_winit_glium.rs b/backends/conrod_glium/examples/all_winit_glium.rs index 96a4dd76b..5f4ab225b 100644 --- a/backends/conrod_glium/examples/all_winit_glium.rs +++ b/backends/conrod_glium/examples/all_winit_glium.rs @@ -27,10 +27,11 @@ fn main() { let display = support::GliumDisplayWinitWrapper(display); // Construct our `Ui`. - let mut ui = conrod_core::UiBuilder::new([WIN_W as f64, WIN_H as f64]).theme(conrod_example_shared::theme()).build(); + let mut ui = conrod_core::UiBuilder::new([WIN_W as f64, WIN_H as f64]) + .theme(conrod_example_shared::theme()) + .build(); - // The `widget::Id` of each widget instantiated in `conrod_example_shared::gui`. - let ids = conrod_example_shared::Ids::new(ui.widget_id_generator()); + let gui = conrod_example_shared::Gui::new(&mut ui); // Add a `Font` to the `Ui`'s `font::Map` from file. let assets = find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap(); @@ -101,7 +102,8 @@ fn main() { } // Instantiate a GUI demonstrating every widget type provided by conrod. - conrod_example_shared::gui(&mut ui.set_widgets(), &ids, &mut app); + let mut ui = &mut ui.set_widgets(); + gui.update(&mut ui, &mut app); // Draw the `Ui`. if let Some(primitives) = ui.draw_if_changed() { diff --git a/backends/conrod_glium/examples/all_winit_glium_threaded.rs b/backends/conrod_glium/examples/all_winit_glium_threaded.rs index 9f54b3419..3b14f8c36 100644 --- a/backends/conrod_glium/examples/all_winit_glium_threaded.rs +++ b/backends/conrod_glium/examples/all_winit_glium_threaded.rs @@ -80,7 +80,7 @@ fn main() { let mut app = conrod_example_shared::DemoApp::new(rust_logo); // The `widget::Id` of each widget instantiated in `conrod_example_shared::gui`. - let ids = conrod_example_shared::Ids::new(ui.widget_id_generator()); + let gui = conrod_example_shared::Gui::new(&mut ui); // Many widgets require another frame to finish drawing after clicks or hovers, so we // insert an update into the conrod loop using this `bool` after each event. @@ -110,7 +110,8 @@ fn main() { } // Instantiate a GUI demonstrating every widget type provided by conrod. - conrod_example_shared::gui(&mut ui.set_widgets(), &ids, &mut app); + let mut ui = &mut ui.set_widgets(); + gui.update(&mut ui, &mut app); // Render the `Ui` to a list of primitives that we can send to the main thread for // display. Wakeup `winit` for rendering. diff --git a/backends/conrod_piston/examples/all_piston_window.rs b/backends/conrod_piston/examples/all_piston_window.rs index 0b6ae9968..46480c111 100644 --- a/backends/conrod_piston/examples/all_piston_window.rs +++ b/backends/conrod_piston/examples/all_piston_window.rs @@ -54,7 +54,7 @@ pub fn main() { }; // Instantiate the generated list of widget identifiers. - let ids = conrod_example_shared::Ids::new(ui.widget_id_generator()); + let gui = conrod_example_shared::Gui::new(&mut ui); // Load the rust logo from file to a piston_window texture. let rust_logo: G2dTexture = { @@ -84,8 +84,8 @@ pub fn main() { } event.update(|_| { - let mut ui = ui.set_widgets(); - conrod_example_shared::gui(&mut ui, &ids, &mut app); + let mut ui = &mut ui.set_widgets(); + gui.update(&mut ui, &mut app); }); window.draw_2d(&event, |context, graphics| { diff --git a/backends/conrod_vulkano/examples/all_winit_vulkano.rs b/backends/conrod_vulkano/examples/all_winit_vulkano.rs index d8b124dad..f100fbd65 100644 --- a/backends/conrod_vulkano/examples/all_winit_vulkano.rs +++ b/backends/conrod_vulkano/examples/all_winit_vulkano.rs @@ -56,7 +56,7 @@ fn main() { let mut ui = conrod_core::UiBuilder::new([WIN_W as f64, WIN_H as f64]) .theme(conrod_example_shared::theme()) .build(); - let ids = conrod_example_shared::Ids::new(ui.widget_id_generator()); + let gui = conrod_example_shared::Gui::new(&mut ui); // Load font from file let assets = find_folder::Search::KidsThenParents(3, 5) @@ -236,8 +236,8 @@ fn main() { // Update widgets if any event has happened if ui.global_input().events().next().is_some() { - let mut ui = ui.set_widgets(); - conrod_example_shared::gui(&mut ui, &ids, &mut app); + let mut ui = &mut ui.set_widgets(); + gui.update(&mut ui, &mut app); } } }