#[macro_use] extern crate conrod_core;
extern crate conrod_glium;
extern crate conrod_winit;
extern crate find_folder;
extern crate glium;
extern crate rand;
mod support;
use glium::Surface;
struct DemoApp {
bg_color: conrod_core::Color,
show_button: bool,
toggle_label: String,
title_pad: f64,
v_slider_height: f64,
border_width: f64,
bool_matrix: [[bool; 8]; 8],
ddl_colors: Vec<String>,
ddl_color: conrod_core::Color,
selected_idx: Option<usize>,
circle_pos: conrod_core::Point,
envelopes: Vec<(Vec<conrod_core::Point>, String)>,
}
impl DemoApp {
fn new() -> DemoApp {
DemoApp {
bg_color: conrod_core::color::rgb(0.2, 0.35, 0.45),
show_button: false,
toggle_label: "OFF".to_string(),
title_pad: 350.0,
v_slider_height: 230.0,
border_width: 1.0,
bool_matrix: [ [true, true, true, true, true, true, true, true],
[true, false, false, false, false, false, false, true],
[true, false, true, false, true, true, true, true],
[true, false, true, false, true, true, true, true],
[true, false, false, false, true, true, true, true],
[true, true, true, true, true, true, true, true],
[true, true, false, true, false, false, false, true],
[true, true, true, true, true, true, true, true] ],
ddl_colors: vec!["Black".to_string(),
"White".to_string(),
"Red".to_string(),
"Green".to_string(),
"Blue".to_string()],
ddl_color: conrod_core::color::PURPLE,
selected_idx: None,
circle_pos: [-50.0, 110.0],
envelopes: vec![(vec![ [0.0, 0.0],
[0.1, 17000.0],
[0.25, 8000.0],
[0.5, 2000.0],
[1.0, 0.0], ], "Envelope A".to_string()),
(vec![ [0.0, 0.85],
[0.3, 0.2],
[0.6, 0.6],
[1.0, 0.0], ], "Envelope B".to_string())],
}
}
}
fn main() {
const WIDTH: u32 = 1100;
const HEIGHT: u32 = 560;
let mut events_loop = glium::glutin::EventsLoop::new();
let window = glium::glutin::WindowBuilder::new()
.with_title("Widget Demonstration")
.with_dimensions((WIDTH, HEIGHT).into());
let context = glium::glutin::ContextBuilder::new()
.with_vsync(true)
.with_multisampling(4);
let display = glium::Display::new(window, context, &events_loop).unwrap();
let display = support::GliumDisplayWinitWrapper(display);
let mut ui = conrod_core::UiBuilder::new([WIDTH as f64, HEIGHT as f64]).build();
let mut ids = Ids::new(ui.widget_id_generator());
let assets = find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap();
let font_path = assets.join("fonts/NotoSans/NotoSans-Regular.ttf");
ui.fonts.insert_from_file(font_path).unwrap();
let mut renderer = conrod_glium::Renderer::new(&display.0).unwrap();
let image_map = conrod_core::image::Map::<glium::texture::Texture2d>::new();
let mut app = DemoApp::new();
let mut event_loop = support::EventLoop::new();
'main: loop {
for event in event_loop.next(&mut events_loop) {
if let Some(event) = conrod_winit::convert_event(event.clone(), &display) {
ui.handle_event(event);
event_loop.needs_update();
}
match event {
glium::glutin::Event::WindowEvent { event, .. } => match event {
glium::glutin::WindowEvent::CloseRequested |
glium::glutin::WindowEvent::KeyboardInput {
input: glium::glutin::KeyboardInput {
virtual_keycode: Some(glium::glutin::VirtualKeyCode::Escape),
..
},
..
} => break 'main,
_ => (),
},
_ => (),
}
}
{
let mut ui = ui.set_widgets();
set_widgets(&mut ui, &mut app, &mut ids);
}
if let Some(primitives) = ui.draw_if_changed() {
renderer.fill(&display.0, primitives, &image_map);
let mut target = display.0.draw();
target.clear_color(0.0, 0.0, 0.0, 1.0);
renderer.draw(&display.0, &mut target, &image_map).unwrap();
target.finish().unwrap();
}
}
}
widget_ids! {
struct Ids {
canvas,
canvas_x_scrollbar,
canvas_y_scrollbar,
title,
button,
title_pad_slider,
toggle,
red_slider,
green_slider,
blue_slider,
slider_height,
border_width,
toggle_matrix,
color_select,
circle_position,
circle,
text_box_a,
text_box_b,
envelope_editor_a,
envelope_editor_b,
}
}
fn set_widgets(ui: &mut conrod_core::UiCell, app: &mut DemoApp, ids: &mut Ids) {
use conrod_core::{color, widget, Colorable, Borderable, Labelable, Positionable, Sizeable, Widget};
widget::Canvas::new()
.border(app.border_width)
.pad(30.0)
.color(app.bg_color)
.scroll_kids()
.set(ids.canvas, ui);
widget::Scrollbar::x_axis(ids.canvas).auto_hide(true).set(ids.canvas_y_scrollbar, ui);
widget::Scrollbar::y_axis(ids.canvas).auto_hide(true).set(ids.canvas_x_scrollbar, ui);
widget::Text::new("Widget Demonstration")
.top_left_with_margins_on(ids.canvas, 0.0, app.title_pad)
.font_size(32)
.color(app.bg_color.plain_contrast())
.set(ids.title, ui);
if app.show_button {
if widget::Button::new()
.w_h(200.0, 50.0)
.mid_left_of(ids.canvas)
.down_from(ids.title, 45.0)
.rgb(0.4, 0.75, 0.6)
.border(app.border_width)
.label("PRESS")
.set(ids.button, ui)
.was_clicked()
{
app.bg_color = color::rgb(rand::random(), rand::random(), rand::random())
}
}
else {
let label = format!("Padding: {}", app.title_pad as i16);
if let Some(new_pad) = widget::Slider::new(app.title_pad, 0.0, 670.0)
.w_h(200.0, 50.0)
.mid_left_of(ids.canvas)
.down_from(ids.title, 45.0)
.rgb(0.5, 0.3, 0.6)
.border(app.border_width)
.label(&label)
.label_color(color::WHITE)
.set(ids.title_pad_slider, ui)
{
app.title_pad = new_pad;
}
}
let shown_widget = if app.show_button { ids.button } else { ids.title_pad_slider };
if let Some(value) = widget::Toggle::new(app.show_button)
.w_h(75.0, 75.0)
.down(20.0)
.rgb(0.6, 0.25, 0.75)
.border(app.border_width)
.label(&app.toggle_label)
.label_color(color::WHITE)
.set(ids.toggle, ui)
.last()
{
app.show_button = value;
app.toggle_label = match value {
true => "ON".to_string(),
false => "OFF".to_string()
}
}
macro_rules! color_slider {
($slider_id:ident, $bg_color:ident, $color:expr, $set_color:ident, $position:ident) => {{
let value = app.bg_color.$bg_color();
let label = format!("{:.*}", 2, value);
for color in widget::Slider::new(value, 0.0, 1.0)
.$position(25.0)
.w_h(40.0, app.v_slider_height)
.color($color)
.border(app.border_width)
.label(&label)
.label_color(color::WHITE)
.set(ids.$slider_id, ui)
{
app.bg_color.$set_color(color);
}
}};
}
color_slider!(red_slider, red, color::rgb(0.75, 0.3, 0.3), set_red, down);
color_slider!(green_slider, green, color::rgb(0.3, 0.75, 0.3), set_green, right);
color_slider!(blue_slider, blue, color::rgb(0.3, 0.3, 0.75), set_blue, right);
for new_height in widget::NumberDialer::new(app.v_slider_height, 25.0, 250.0, 1)
.w_h(260.0, 60.0)
.right_from(shown_widget, 30.0)
.color(app.bg_color.invert())
.border(app.border_width)
.label("Height (px)")
.label_color(app.bg_color.invert().plain_contrast())
.set(ids.slider_height, ui)
{
app.v_slider_height = new_height;
}
for new_width in widget::NumberDialer::new(app.border_width, 0.0, 15.0, 2)
.w_h(260.0, 60.0)
.down(20.0)
.color(app.bg_color.plain_contrast().invert())
.border(app.border_width)
.border_color(app.bg_color.plain_contrast())
.label("Border Width (px)")
.label_color(app.bg_color.plain_contrast())
.set(ids.border_width, ui)
{
app.border_width = new_width;
}
let (cols, rows) = (8, 8);
let mut elements = widget::Matrix::new(cols, rows)
.down(20.0)
.w_h(260.0, 260.0)
.set(ids.toggle_matrix, ui);
while let Some(elem) = elements.next(ui) {
let (col, row) = (elem.col, elem.row);
let (r, g, b, a) = (
0.5 + (elem.col as f32 / cols as f32) / 2.0,
0.75,
1.0 - (elem.row as f32 / rows as f32) / 2.0,
1.0
);
let toggle = widget::Toggle::new(app.bool_matrix[col][row])
.rgba(r, g, b, a)
.border(app.border_width);
if let Some(new_value) = elem.set(toggle, ui).last() {
app.bool_matrix[col][row] = new_value;
}
}
for selected_idx in widget::DropDownList::new(&app.ddl_colors, app.selected_idx)
.w_h(150.0, 40.0)
.right_from(ids.slider_height, 30.0) .max_visible_items(3)
.color(app.ddl_color)
.border(app.border_width)
.border_color(app.ddl_color.plain_contrast())
.label("Colors")
.label_color(app.ddl_color.plain_contrast())
.scrollbar_on_top()
.set(ids.color_select, ui)
{
app.selected_idx = Some(selected_idx);
app.ddl_color = match &app.ddl_colors[selected_idx][..] {
"Black" => color::BLACK,
"White" => color::WHITE,
"Red" => color::RED,
"Green" => color::GREEN,
"Blue" => color::BLUE,
_ => color::PURPLE,
}
}
for (x, y) in widget::XYPad::new(app.circle_pos[0], -75.0, 75.0, app.circle_pos[1], 95.0, 245.0) .w_h(150.0, 150.0)
.right_from(ids.toggle_matrix, 30.0)
.align_bottom_of(ids.toggle_matrix) .color(app.ddl_color)
.border(app.border_width)
.border_color(color::WHITE)
.label("Circle Position")
.label_color(app.ddl_color.plain_contrast().alpha(0.5))
.line_thickness(2.0)
.set(ids.circle_position, ui)
{
app.circle_pos[0] = x;
app.circle_pos[1] = y;
}
widget::Circle::fill(15.0)
.xy_relative_to(ids.circle_position, app.circle_pos)
.color(app.ddl_color)
.set(ids.circle, ui);
for i in 0..2 {
let &mut (ref mut env, ref mut text) = &mut app.envelopes[i];
let (text_box, env_editor, env_y_max, env_skew_y) = match i {
0 => (ids.text_box_a, ids.envelope_editor_a, 20_000.0, 3.0),
1 => (ids.text_box_b, ids.envelope_editor_b, 1.0, 1.0),
_ => unreachable!(),
};
for event in widget::TextBox::new(text)
.and_if(i == 0, |text| text.right_from(ids.color_select, 30.0))
.font_size(20)
.w_h(320.0, 40.0)
.border(app.border_width)
.border_color(app.bg_color.invert().plain_contrast())
.color(app.bg_color.invert())
.set(text_box, ui)
{
match event {
widget::text_box::Event::Enter => println!("TextBox {}: {:?}", i, text),
widget::text_box::Event::Update(string) => *text = string,
}
}
for event in widget::EnvelopeEditor::new(env, 0.0, 1.0, 0.0, env_y_max)
.down(10.0)
.w_h(320.0, 150.0)
.skew_y(env_skew_y)
.color(app.bg_color.invert())
.border(app.border_width)
.border_color(app.bg_color.invert().plain_contrast())
.label(&text)
.label_color(app.bg_color.invert().plain_contrast().alpha(0.5))
.point_radius(6.0)
.line_thickness(2.0)
.set(env_editor, ui)
{
event.update(env);
}
}
}