Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Examples: Dialog's response signal handling #1514

Merged
merged 13 commits into from
Jan 29, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ path = "column_view_datagrid/main.rs"
name = "composite_template"
path = "composite_template/main.rs"

[[bin]]
name = "composite_dialog"
path = "composite_dialog/main.rs"

[[bin]]
name = "confetti_snapshot_animation"
path = "confetti_snapshot_animation/main.rs"
Expand Down Expand Up @@ -187,4 +191,3 @@ path = "video_player/main.rs"
[[bin]]
name = "virtual_methods"
path = "virtual_methods/main.rs"

6 changes: 6 additions & 0 deletions examples/composite_dialog/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Composite Template Dialog

This example shows the use of callbacks, custom and bind property, notify and response signal in a composite
template situation.

![Screenshot](screenshot.png)
17 changes: 17 additions & 0 deletions examples/composite_dialog/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
mod my_app_window;

use gtk::glib;
use gtk::prelude::*;
jobale marked this conversation as resolved.
Show resolved Hide resolved
use my_app_window::MyAppWindow;

fn main() -> glib::ExitCode {
let application = gtk::Application::builder()
.application_id("com.github.gtk-rs.examples.composite_dialog")
.build();

application.connect_activate(|app| {
let win = MyAppWindow::new(app);
win.present();
});
application.run()
}
55 changes: 55 additions & 0 deletions examples/composite_dialog/my_app_window/imp.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use std::cell::Cell;

use gtk::{
glib::{self, Properties},
prelude::*,
subclass::prelude::*,
CompositeTemplate,
};

// Object holding the state
jobale marked this conversation as resolved.
Show resolved Hide resolved
#[derive(Default, CompositeTemplate, Properties)]
jobale marked this conversation as resolved.
Show resolved Hide resolved
#[template(file = "window.ui")]
#[properties(wrapper_type = super::MyAppWindow)]
pub struct MyAppWindow {
#[property(get, set)]
counter: Cell<i32>,
#[template_child]
pub count_label: TemplateChild<gtk::Label>,
#[template_child]
pub plus: TemplateChild<gtk::Button>,
#[template_child]
pub minus: TemplateChild<gtk::Button>,
}

// The central trait for subclassing a GObject
#[glib::object_subclass]
impl ObjectSubclass for MyAppWindow {
const NAME: &'static str = "MyAppWindow";
type Type = super::MyAppWindow;
type ParentType = gtk::ApplicationWindow;

fn class_init(klass: &mut Self::Class) {
klass.bind_template();
klass.bind_template_instance_callbacks();
}

fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}

// Trait shared by all GObjects
jobale marked this conversation as resolved.
Show resolved Hide resolved
#[glib::derived_properties]
impl ObjectImpl for MyAppWindow {
fn constructed(&self) {
bilelmoussaoui marked this conversation as resolved.
Show resolved Hide resolved
self.parent_constructed();

// Bind property to a label
// self.obj().bind_counter_to_count();
}
}

jobale marked this conversation as resolved.
Show resolved Hide resolved
impl WidgetImpl for MyAppWindow {}
impl WindowImpl for MyAppWindow {}
impl ApplicationWindowImpl for MyAppWindow {}
80 changes: 80 additions & 0 deletions examples/composite_dialog/my_app_window/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
mod imp;

use gtk::{
glib::{self, ParamSpec},
bilelmoussaoui marked this conversation as resolved.
Show resolved Hide resolved
prelude::*,
ResponseType,
bilelmoussaoui marked this conversation as resolved.
Show resolved Hide resolved
};

glib::wrapper! {
pub struct MyAppWindow(ObjectSubclass<imp::MyAppWindow>)
@extends gtk::Widget, gtk::Window, gtk::ApplicationWindow;
}

#[gtk::template_callbacks]
impl MyAppWindow {
pub fn new<P: glib::IsA<gtk::Application>>(app: &P) -> Self {
jobale marked this conversation as resolved.
Show resolved Hide resolved
glib::Object::builder().property("application", app).build()
}

/// Callback handler for notify::label signal.
jobale marked this conversation as resolved.
Show resolved Hide resolved
///
/// When counter property reach 3, a dialog pops up and present the user
/// with 2 choices: Set the counter to 6 or reset the counter to 0.
#[allow(deprecated)]
bilelmoussaoui marked this conversation as resolved.
Show resolved Hide resolved
#[template_callback]
fn popup_dialog(&self, _p: &ParamSpec) {
// Check counter property and create a Dialog.
if self.counter() == 3 {
let dial = gtk::Dialog::with_buttons(
Some("Counter value is 3"),
Some(self),
gtk::DialogFlags::MODAL,
&[
("Set counter to 6", ResponseType::Other(35)),
("Reset counter", ResponseType::Ok),
],
);
dial.set_transient_for(Some(self));

let app = self.clone();

// Closure handling response signal from gtk::Dialog.
// The signature of the function differ from the documentation for response signal.
// gtk-rs use an i32 instead of a [`gtk::ResponseType`] as a response signal.
dial.connect_closure(
bilelmoussaoui marked this conversation as resolved.
Show resolved Hide resolved
"response",
false,
glib::closure_local!(move |d: &gtk::Dialog, response: i32| {
match ResponseType::from(response) {
ResponseType::Other(35) => {
app.set_counter(6);
d.close();
}
ResponseType::Ok => {
app.set_counter(0);
d.close();
}
_ => (),
}
}),
);

dial.present();
}
}

/// Callback handler for gtk::Button plus.
#[template_callback]
fn add_to_counter(&self, _button: &gtk::Button) {
let n = self.counter() + 1;
self.set_counter(n);
}

/// Callback handler for gtk::Button minus.
#[template_callback]
fn sub_to_counter(&self, _button: &gtk::Button) {
let n = self.counter() - 1;
self.set_counter(n);
}
}
62 changes: 62 additions & 0 deletions examples/composite_dialog/my_app_window/window.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?xml version='1.0' encoding='UTF-8'?>
<interface>
<template class="MyAppWindow" parent="GtkApplicationWindow">
<property name="default-height">300</property>
<property name="default-width">400</property>
<property name="hexpand">True</property>
<property name="show-menubar">True</property>
<property name="title">Composite Template Dialog</property>
<property name="vexpand">True</property>
<signal name="notify::counter" handler="popup_dialog" swapped="true"/>
<child>
<object class="GtkBox">
<property name="halign">center</property>
<property name="margin-top">10</property>
<property name="spacing">5</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="label">Click until you reach 3</property>
<style>
<class name="large-title"/>
</style>
</object>
</child>
<child>
<object class="GtkBox">
<property name="halign">center</property>
<property name="valign">center</property>
<property name="spacing">10</property>
<child>
<object class="GtkButton" id="plus">
<signal name="clicked" handler="add_to_counter" swapped="true"/>
<property name="label">+</property>
<property name="focus-on-click">True</property>
</object>
</child>
<child>
<object class="GtkButton" id="minus">
<signal name="clicked" handler="sub_to_counter" swapped="true"/>
<property name="label">-</property>
<property name="focus-on-click">True</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkLabel" id="count_label">
<property name="label"
bind-source="MyAppWindow"
bind-property="counter"
bind-flags="sync-create"/>
<property name="justify">center</property>
<property name="margin-end">5</property>
<property name="margin-start">5</property>
<property name="margin-top">20</property>
<property name="margin-bottom">5</property>
</object>
</child>
</object>
</child>
</template>
</interface>
Binary file added examples/composite_dialog/screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.