From 37b5bf364517778febfc8cb14548626b5bd2090c Mon Sep 17 00:00:00 2001 From: Max Bradbury Date: Wed, 30 Sep 2020 16:12:07 +0100 Subject: [PATCH] dummy example --- Cargo.toml | 7 +- src/main.rs | 273 ++++++++++++++++++++------------------- src/support/clipboard.rs | 19 +++ src/support/helsinki.ttf | Bin 0 -> 25680 bytes src/support/mod.rs | 140 ++++++++++++++++++++ 5 files changed, 304 insertions(+), 135 deletions(-) create mode 100644 src/support/clipboard.rs create mode 100644 src/support/helsinki.ttf create mode 100644 src/support/mod.rs diff --git a/Cargo.toml b/Cargo.toml index 00d7a1a..d1db8ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,10 @@ edition = "2018" crate_type = "bin" [dependencies] +clipboard = "^0.5.0" dirs = "^3.0.1" -gio = "^0" -gtk = "^0" +glium = "^0.27.0" +imgui = "^0.5.0" +imgui-glium-renderer = "^0.5.0" +imgui-winit-support = "^0.5.0" rodio = "^0.11.0" diff --git a/src/main.rs b/src/main.rs index 86c18ff..8336d3f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,39 +1,39 @@ #![windows_subsystem = "windows"] -use gio::prelude::*; -use gtk::prelude::*; -use gtk::Orientation; use rodio::{Sink, Source}; use std::env::args; use std::fs::File; use std::io::BufReader; use std::path::PathBuf; use std::process::Command; +use imgui::*; + +mod support; const SPACING: i32 = 16; - -fn error_popup(message: &str) { - let popup = gtk::Window::new(gtk::WindowType::Toplevel); - popup.set_title("error"); - popup.set_border_width(SPACING as u32); - popup.set_position(gtk::WindowPosition::Center); - popup.set_default_size(256, 64); - - let vertical = gtk::Box::new(Orientation::Vertical, SPACING); - popup.add(&vertical); - - let message = gtk::Label::new(Some(message)); - vertical.add(&message); - - let button_ok = gtk::Button::with_label("OK"); - vertical.add(&button_ok); - - popup.show_all(); - - button_ok.connect_clicked(move |_| unsafe { - popup.destroy(); - }); -} +// +// fn error_popup(message: &str) { +// let popup = gtk::Window::new(gtk::WindowType::Toplevel); +// popup.set_title("error"); +// popup.set_border_width(SPACING as u32); +// popup.set_position(gtk::WindowPosition::Center); +// popup.set_default_size(256, 64); +// +// let vertical = gtk::Box::new(Orientation::Vertical, SPACING); +// popup.add(&vertical); +// +// let message = gtk::Label::new(Some(message)); +// vertical.add(&message); +// +// let button_ok = gtk::Button::with_label("OK"); +// vertical.add(&button_ok); +// +// popup.show_all(); +// +// button_ok.connect_clicked(move |_| unsafe { +// popup.destroy(); +// }); +// } fn get_data_dir() -> PathBuf { let mut data_dir = dirs::data_dir().expect("Couldn't find user data directory"); @@ -46,115 +46,122 @@ fn get_data_dir() -> PathBuf { data_dir } - -fn build_ui(application: >k::Application) { - let window = gtk::ApplicationWindow::new(application); - - window.set_title("lull"); - window.set_border_width(SPACING as u32); - window.set_position(gtk::WindowPosition::Center); - window.set_default_size(256, 256); - - let vertical = gtk::Box::new(Orientation::Vertical, SPACING); - vertical.set_homogeneous(true); - - window.add(&vertical); - - let device = rodio::default_output_device().unwrap(); - - let paths = std::fs::read_dir(get_data_dir()) - .expect("Couldn't read from lull data directory"); - - for path in paths { - let path = path.unwrap().path(); - let name: &str = path.file_stem().unwrap().to_str().unwrap(); - - let file = File::open(&path) - .expect("Couldn't open audio file"); - - let source = rodio::Decoder::new( - BufReader::new(file) - ); - - if source.is_err() { - error_popup(&format!( - "Couldn't parse file {}. \n{}.", - path.to_str().unwrap(), - source.err().unwrap() - )); - continue; - } - - let source = source.unwrap().repeat_infinite(); - - let sink = Sink::new(&device); - sink.append(source); - sink.pause(); - - let row = gtk::Box::new(Orientation::Horizontal, SPACING); - row.set_homogeneous(true); - - let label = gtk::Label::new(Some(name)); - row.add(&label); - - let adjustment = gtk::Adjustment::new( - 0.0, - 0.0, - 1.0, - 0.0, - 0.0, - 0.0 - ); - - let slider = gtk::Scale::new( - Orientation::Horizontal, - Some(&adjustment) - ); - - slider.set_draw_value(false); - - slider.connect_value_changed(move |scale| { - let volume = scale.get_value(); - - if volume == 0. { - sink.pause(); - } else { - sink.play(); - sink.set_volume(volume as f32); - } - }); - - row.add(&slider); - - vertical.add(&row); - } - - let row_add = gtk::Box::new(Orientation::Horizontal, SPACING); - row_add.set_homogeneous(true); - - let button_manage_sounds = gtk::Button::with_label("manage sounds"); - - button_manage_sounds.connect_clicked(|_| { - let mut file_manager = Command::new("xdg-open"); - file_manager.arg(get_data_dir()); - file_manager.output().unwrap(); - }); - - row_add.add(&button_manage_sounds); - vertical.add(&row_add); - - window.show_all(); -} +// +// fn build_ui(application: >k::Application) { +// let window = gtk::ApplicationWindow::new(application); +// +// window.set_title("lull"); +// window.set_border_width(SPACING as u32); +// window.set_position(gtk::WindowPosition::Center); +// window.set_default_size(256, 256); +// +// let vertical = gtk::Box::new(Orientation::Vertical, SPACING); +// vertical.set_homogeneous(true); +// +// window.add(&vertical); +// +// let device = rodio::default_output_device().unwrap(); +// +// let paths = std::fs::read_dir(get_data_dir()) +// .expect("Couldn't read from lull data directory"); +// +// for path in paths { +// let path = path.unwrap().path(); +// let name: &str = path.file_stem().unwrap().to_str().unwrap(); +// +// let file = File::open(&path) +// .expect("Couldn't open audio file"); +// +// let source = rodio::Decoder::new( +// BufReader::new(file) +// ); +// +// if source.is_err() { +// error_popup(&format!( +// "Couldn't parse file {}. \n{}.", +// path.to_str().unwrap(), +// source.err().unwrap() +// )); +// continue; +// } +// +// let source = source.unwrap().repeat_infinite(); +// +// let sink = Sink::new(&device); +// sink.append(source); +// sink.pause(); +// +// let row = gtk::Box::new(Orientation::Horizontal, SPACING); +// row.set_homogeneous(true); +// +// let label = gtk::Label::new(Some(name)); +// row.add(&label); +// +// let adjustment = gtk::Adjustment::new( +// 0.0, +// 0.0, +// 1.0, +// 0.0, +// 0.0, +// 0.0 +// ); +// +// let slider = gtk::Scale::new( +// Orientation::Horizontal, +// Some(&adjustment) +// ); +// +// slider.set_draw_value(false); +// +// slider.connect_value_changed(move |scale| { +// let volume = scale.get_value(); +// +// if volume == 0. { +// sink.pause(); +// } else { +// sink.play(); +// sink.set_volume(volume as f32); +// } +// }); +// +// row.add(&slider); +// +// vertical.add(&row); +// } +// +// let row_add = gtk::Box::new(Orientation::Horizontal, SPACING); +// row_add.set_homogeneous(true); +// +// let button_manage_sounds = gtk::Button::with_label("manage sounds"); +// +// button_manage_sounds.connect_clicked(|_| { +// let mut file_manager = Command::new("xdg-open"); +// file_manager.arg(get_data_dir()); +// file_manager.output().unwrap(); +// }); +// +// row_add.add(&button_manage_sounds); +// vertical.add(&row_add); +// +// window.show_all(); +// } fn main() { - let application = gtk::Application::new( - Some("dev.tinybird.max.lull"), - Default::default() - ).expect("Initialization failed..."); + let system = support::init(file!()); - application.connect_activate(|app| { - build_ui(app); + system.main_loop(move |_, ui| { + Window::new(im_str!("Hello world")) + .size([300.0, 100.0], Condition::FirstUseEver) + .build(&ui, || { + ui.text(im_str!("Hello world!")); + ui.text(im_str!("こんにちは世界!")); + ui.text(im_str!("This...is...imgui-rs!")); + ui.separator(); + let mouse_pos = ui.io().mouse_pos; + ui.text(format!( + "Mouse Position: ({:.1},{:.1})", + mouse_pos[0], mouse_pos[1] + )); + }); }); - - application.run(&args().collect::>()); } diff --git a/src/support/clipboard.rs b/src/support/clipboard.rs new file mode 100644 index 0000000..5f1cc34 --- /dev/null +++ b/src/support/clipboard.rs @@ -0,0 +1,19 @@ +use clipboard::{ClipboardContext, ClipboardProvider}; +use imgui::{ClipboardBackend, ImStr, ImString}; + +pub struct ClipboardSupport(ClipboardContext); + +pub fn init() -> Option { + ClipboardContext::new() + .ok() + .map(|ctx| ClipboardSupport(ctx)) +} + +impl ClipboardBackend for ClipboardSupport { + fn get(&mut self) -> Option { + self.0.get_contents().ok().map(|text| text.into()) + } + fn set(&mut self, text: &ImStr) { + let _ = self.0.set_contents(text.to_str().to_owned()); + } +} diff --git a/src/support/helsinki.ttf b/src/support/helsinki.ttf new file mode 100644 index 0000000000000000000000000000000000000000..4857e4da9d7e8b3a3ac90f8150c5dfdf11033f38 GIT binary patch literal 25680 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 b>3jA7udsXk;TABJjX(6$P`!pWTM7Mt@6-m# literal 0 HcmV?d00001 diff --git a/src/support/mod.rs b/src/support/mod.rs new file mode 100644 index 0000000..3e4caff --- /dev/null +++ b/src/support/mod.rs @@ -0,0 +1,140 @@ +use glium::glutin; +use glium::glutin::event::{Event, WindowEvent}; +use glium::glutin::event_loop::{ControlFlow, EventLoop}; +use glium::glutin::window::WindowBuilder; +use glium::{Display, Surface}; +use imgui::{Context, FontConfig, FontGlyphRanges, FontSource, Ui}; +use imgui_glium_renderer::Renderer; +use imgui_winit_support::{HiDpiMode, WinitPlatform}; +use std::time::Instant; + +mod clipboard; + +pub struct System { + pub event_loop: EventLoop<()>, + pub display: glium::Display, + pub imgui: Context, + pub platform: WinitPlatform, + pub renderer: Renderer, + pub font_size: f32, +} + +pub fn init(title: &str) -> System { + let title = match title.rfind('/') { + Some(idx) => title.split_at(idx + 1).1, + None => title, + }; + let event_loop = EventLoop::new(); + let context = glutin::ContextBuilder::new().with_vsync(true); + let builder = WindowBuilder::new() + .with_title(title.to_owned()) + .with_inner_size(glutin::dpi::LogicalSize::new(1024f64, 768f64)); + let display = + Display::new(builder, context, &event_loop).expect("Failed to initialize display"); + + let mut imgui = Context::create(); + imgui.set_ini_filename(None); + + if let Some(backend) = clipboard::init() { + imgui.set_clipboard_backend(Box::new(backend)); + } else { + eprintln!("Failed to initialize clipboard"); + } + + let mut platform = WinitPlatform::init(&mut imgui); + { + let gl_window = display.gl_window(); + let window = gl_window.window(); + platform.attach_window(imgui.io_mut(), &window, HiDpiMode::Rounded); + } + + let hidpi_factor = platform.hidpi_factor(); + let font_size = (13.0 * hidpi_factor) as f32; + imgui.fonts().add_font(&[ + FontSource::DefaultFontData { + config: Some(FontConfig { + size_pixels: font_size, + ..FontConfig::default() + }), + }, + FontSource::TtfData { + data: include_bytes!("helsinki.ttf"), + size_pixels: font_size, + config: Some(FontConfig { + rasterizer_multiply: 1.75, + glyph_ranges: FontGlyphRanges::japanese(), + ..FontConfig::default() + }), + }, + ]); + + imgui.io_mut().font_global_scale = (1.0 / hidpi_factor) as f32; + + let renderer = Renderer::init(&mut imgui, &display) + .expect("Failed to initialize renderer"); + + System { + event_loop, + display, + imgui, + platform, + renderer, + font_size, + } +} + +impl System { + pub fn main_loop(self, mut run_ui: F) { + let System { + event_loop, + display, + mut imgui, + mut platform, + mut renderer, + .. + } = self; + let mut last_frame = Instant::now(); + + event_loop.run(move |event, _, control_flow| match event { + Event::NewEvents(_) => { + let now = Instant::now(); + imgui.io_mut().update_delta_time(now - last_frame); + last_frame = now; + } + Event::MainEventsCleared => { + let gl_window = display.gl_window(); + platform + .prepare_frame(imgui.io_mut(), &gl_window.window()) + .expect("Failed to prepare frame"); + gl_window.window().request_redraw(); + } + Event::RedrawRequested(_) => { + let mut ui = imgui.frame(); + + let mut run = true; + run_ui(&mut run, &mut ui); + if !run { + *control_flow = ControlFlow::Exit; + } + + let gl_window = display.gl_window(); + let mut target = display.draw(); + target.clear_color_srgb(1.0, 1.0, 1.0, 1.0); + platform.prepare_render(&ui, gl_window.window()); + let draw_data = ui.render(); + renderer + .render(&mut target, draw_data) + .expect("Rendering failed"); + target.finish().expect("Failed to swap buffers"); + } + Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } => *control_flow = ControlFlow::Exit, + event => { + let gl_window = display.gl_window(); + platform.handle_event(imgui.io_mut(), gl_window.window(), &event); + } + }) + } +}