diff --git a/examples/clipboard/asset.png b/examples/clipboard/asset.png new file mode 100644 index 0000000..d553e74 Binary files /dev/null and b/examples/clipboard/asset.png differ diff --git a/src/clipboard.rs b/src/clipboard.rs new file mode 100644 index 0000000..f11213f --- /dev/null +++ b/src/clipboard.rs @@ -0,0 +1,172 @@ +// Copied from https://github.com/gtk-rs/gtk4-rs/blob/main/examples/clipboard/main.rs + +use gtk4 as gtk; +use gtk::{ + gdk, gio, + glib::{self, clone}, + prelude::*, +}; + +fn main() -> glib::ExitCode { + let application = gtk::Application::builder() + .application_id("com.github.gtk-rs.examples.clipboard") + .build(); + application.connect_activate(build_ui); + application.run() +} + +fn build_ui(application: >k::Application) { + let window = gtk::ApplicationWindow::builder() + .application(application) + .title("Clipboard") + .default_width(660) + .default_height(420) + .build(); + + let display = gdk::Display::default().unwrap(); + let clipboard = display.clipboard(); + + let container = gtk::Box::builder() + .orientation(gtk::Orientation::Vertical) + .margin_top(24) + .margin_bottom(24) + .margin_start(24) + .margin_end(24) + .halign(gtk::Align::Center) + .valign(gtk::Align::Center) + .spacing(24) + .build(); + + // The text copy/paste part + let title = gtk::Label::builder() + .label("Text") + .halign(gtk::Align::Start) + .build(); + title.add_css_class("title-2"); + container.append(&title); + + let text_container = gtk::Box::builder() + .halign(gtk::Align::Center) + .orientation(gtk::Orientation::Horizontal) + .spacing(24) + .build(); + + let from_entry = gtk::Entry::builder() + .placeholder_text("Type text to copy") + .build(); + text_container.append(&from_entry); + + let copy_btn = gtk::Button::with_label("Copy"); + copy_btn.connect_clicked(clone!( + #[weak] + clipboard, + #[weak] + from_entry, + move |_btn| { + let text = from_entry.text(); + clipboard.set_text(&text); + } + )); + text_container.append(©_btn); + + let into_entry = gtk::Entry::new(); + text_container.append(&into_entry); + + let paste_btn = gtk::Button::with_label("Paste"); + paste_btn.connect_clicked(clone!( + #[weak] + clipboard, + #[weak] + into_entry, + move |_btn| { + clipboard.read_text_async( + gio::Cancellable::NONE, + clone!( + #[weak] + into_entry, + move |res| { + if let Ok(Some(text)) = res { + into_entry.set_text(&text); + } + } + ), + ); + } + )); + text_container.append(&paste_btn); + container.append(&text_container); + + // The texture copy/paste part + let title = gtk::Label::builder() + .label("Texture") + .halign(gtk::Align::Start) + .build(); + title.add_css_class("title-2"); + container.append(&title); + + let texture_container = gtk::Box::builder() + .orientation(gtk::Orientation::Horizontal) + .halign(gtk::Align::Center) + .spacing(24) + .build(); + + let file = gio::File::for_path("./examples/clipboard/asset.png"); + let asset_paintable = gdk::Texture::from_file(&file).unwrap(); + + let image_from = gtk::Image::builder() + .pixel_size(96) + .paintable(&asset_paintable) + .build(); + texture_container.append(&image_from); + let copy_texture_btn = gtk::Button::builder() + .label("Copy") + .valign(gtk::Align::Center) + .build(); + copy_texture_btn.connect_clicked(clone!( + #[weak] + clipboard, + #[weak] + image_from, + move |_btn| { + let texture = image_from + .paintable() + .and_downcast::() + .unwrap(); + clipboard.set_texture(&texture); + } + )); + texture_container.append(©_texture_btn); + + let image_into = gtk::Image::builder() + .pixel_size(96) + .icon_name("image-missing") + .build(); + texture_container.append(&image_into); + let paste_texture_btn = gtk::Button::builder() + .label("Paste") + .valign(gtk::Align::Center) + .build(); + paste_texture_btn.connect_clicked(clone!( + #[weak] + clipboard, + move |_btn| { + clipboard.read_texture_async( + gio::Cancellable::NONE, + clone!( + #[weak] + image_into, + move |res| { + if let Ok(Some(texture)) = res { + image_into.set_paintable(Some(&texture)); + } + } + ), + ); + } + )); + texture_container.append(&paste_texture_btn); + container.append(&texture_container); + + window.set_child(Some(&container)); + window.present(); +} \ No newline at end of file diff --git a/src/clock.rs b/src/clock.rs new file mode 100644 index 0000000..ef0aaea --- /dev/null +++ b/src/clock.rs @@ -0,0 +1,45 @@ +// Example copied from https://github.com/gtk-rs/gtk4-rs/blob/main/examples/clock/main.rs + +use chrono::Local; + +use gtk4 as gtk; +use gtk::{glib, prelude::*}; + +fn main() -> glib::ExitCode { + let application = gtk::Application::builder() + .application_id("com.github.gtk-rs.examples.clock") + .build(); + application.connect_activate(build_ui); + application.run() +} + +fn build_ui(application: >k::Application) { + let window = gtk::ApplicationWindow::new(application); + + window.set_title(Some("Clock Example")); + window.set_default_size(260, 40); + + let time = current_time(); + let label = gtk::Label::default(); + label.set_text(&time); + + window.set_child(Some(&label)); + + window.present(); + + // we are using a closure to capture the label (else we could also use a normal + // function) + let tick = move || { + let time = current_time(); + label.set_text(&time); + // we could return glib::ControlFlow::Break to stop our clock after this tick + glib::ControlFlow::Continue + }; + + // executes the closure once every second + glib::timeout_add_seconds_local(1, tick); +} + +fn current_time() -> String { + format!("{}", Local::now().format("%Y-%m-%d %H:%M:%S")) +} diff --git a/src/counter.rs b/src/counter.rs new file mode 100644 index 0000000..b361923 --- /dev/null +++ b/src/counter.rs @@ -0,0 +1,78 @@ +// Example copied from https://github.com/kashifsoofi/blog-code-samples/blob/gtk4-c-counter-app/gtk4-rust-counter-app/src/main.rs + +use std::cell::Cell; +use std::rc::Rc; + +use gtk4 as gtk; +use gtk::glib::clone; +use gtk::prelude::*; +use gtk::{glib, Application, ApplicationWindow, Label, Box, Button, Orientation}; + +const APP_ID: &str = "org.gtk_rs.GTK4Counter"; + +fn main() -> glib::ExitCode { + // Create a new application + let app = Application::builder().application_id(APP_ID).build(); + + // Connect to "activate" signal of `app` + app.connect_activate(build_ui); + + // Run the application + app.run() +} + +fn build_ui(app: &Application) { + let counter = Rc::new(Cell::new(0)); + let label_counter = Label::builder() + .label(&counter.get().to_string()) + .margin_top(12) + .margin_bottom(12) + .margin_start(12) + .margin_end(12) + .build(); + + let button_increase = Button::builder() + .label("Increase") + .margin_top(12) + .margin_bottom(12) + .margin_start(12) + .margin_end(12) + .build(); + + let button_decrease = Button::builder() + .label("Decrease") + .margin_top(12) + .margin_bottom(12) + .margin_start(12) + .margin_end(12) + .build(); + + button_increase.connect_clicked(clone!(@weak counter, @weak label_counter => + move |_| { + counter.set(counter.get() + 1); + label_counter.set_label(&counter.get().to_string()); + })); + + button_decrease.connect_clicked(clone!(@weak label_counter => + move |_| { + counter.set(counter.get() - 1); + label_counter.set_label(&counter.get().to_string()); + })); + + let gtk_box = Box::builder() + .orientation(Orientation::Vertical) + .build(); + gtk_box.append(&label_counter); + gtk_box.append(&button_increase); + gtk_box.append(&button_decrease); + + // Create a window and set the title + let window = ApplicationWindow::builder() + .application(app) + .title("GTK Counter App") + .child(>k_box) + .build(); + + // Present window + window.present(); +} \ No newline at end of file diff --git a/src/notification.rs b/src/notification.rs new file mode 100644 index 0000000..52509d0 --- /dev/null +++ b/src/notification.rs @@ -0,0 +1,29 @@ +use gtk4 as gtk; +use gtk::glib; +use gtk::prelude::*; +use gtk::gio::{Notification, NotificationPriority}; + +const APP_ID: &str = "de.privacy1st.pdt"; + +fn main() -> glib::ExitCode { + let app = gtk::Application::builder().application_id(APP_ID).build(); + app.connect_activate(move |app| build_ui(app)); + app.run() +} + +fn build_ui(app: >k::Application) { + let window = gtk::ApplicationWindow::builder() + .application(app) + .title("System Notification") + .default_width(350) + .default_height(70) + .build(); + window.present(); + + // TODO: Notification does not show up + let notification = Notification::new("Alert"); + notification.set_body(Some("Time is over")); + notification.set_priority(NotificationPriority::Urgent); + let notification_id = "pdt.timeout"; + app.send_notification(Some(notification_id), ¬ification); +}