ui: more templates and initial handler

This commit is contained in:
PancakeTAS 2025-07-23 20:28:06 +02:00 committed by Pancake
parent bb13eb4656
commit 3dba2a7a3d
18 changed files with 339 additions and 87 deletions

View file

@ -11,7 +11,7 @@
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<child>
<object class="GtkLabel" id="label">
<object class="GtkLabel">
<property name="label"
bind-source="LSPrefDropdown" bind-property="opt-name" bind-flags="sync-create"/>
<property name="halign">start</property>
@ -19,7 +19,7 @@
</object>
</child>
<child>
<object class="GtkDropDown">
<object class="GtkDropDown" id="dropdown">
<property name="selected"
bind-source="LSPrefDropdown" bind-property="default-selection" bind-flags="sync-create"/>
<property name="model"

View file

@ -11,7 +11,7 @@
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<child>
<object class="GtkLabel" id="label">
<object class="GtkLabel">
<property name="label"
bind-source="LSPrefEntry" bind-property="opt-name" bind-flags="sync-create"/>
<property name="halign">start</property>
@ -19,7 +19,7 @@
</object>
</child>
<child>
<object class="GtkEntry">
<object class="GtkEntry" id="entry">
<property name="text"
bind-source="LSPrefEntry" bind-property="default-text" bind-flags="sync-create"/>
<property name="placeholder-text"

41
ui/rsc/pref/number.ui Normal file
View file

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="LSPrefNumber" parent="AdwPreferencesRow">
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<property name="spacing">16</property>
<property name="valign">center</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<child>
<object class="GtkLabel">
<property name="label"
bind-source="LSPrefNumber" bind-property="opt-name" bind-flags="sync-create"/>
<property name="halign">start</property>
<property name="hexpand">true</property>
</object>
</child>
<child>
<object class="GtkSpinButton" id="number">
<property name="digits">0</property>
<property name="climb-rate">1</property>
<property name="numeric">true</property>
<property name="value">2</property>
<property name="adjustment">
<object class="GtkAdjustment">
<property name="lower">1</property>
<property name="upper">20</property>
<property name="step-increment">1</property>
<property name="page-increment">1</property>
<property name="value">2</property>
</object>
</property>
</object>
</child>
</object>
</child>
</template>
</interface>

41
ui/rsc/pref/slider.ui Normal file
View file

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="LSPrefSlider" parent="AdwPreferencesRow">
<child>
<object class="GtkBox">
<property name="orientation">horizontal</property>
<property name="spacing">16</property>
<property name="valign">center</property>
<property name="margin-start">12</property>
<property name="margin-end">12</property>
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<child>
<object class="GtkLabel">
<property name="label"
bind-source="LSPrefSlider" bind-property="opt-name" bind-flags="sync-create"/>
<property name="halign">start</property>
<property name="hexpand">true</property>
</object>
</child>
<child>
<object class="GtkScale" id="slider">
<property name="digits">0</property>
<property name="draw-value">true</property>
<property name="value-pos">right</property>
<property name="hexpand">true</property>
<property name="adjustment">
<object class="GtkAdjustment">
<property name="lower">25</property>
<property name="upper">100</property>
<property name="step-increment">5</property>
<property name="page-increment">10</property>
<property name="value">100</property>
</object>
</property>
</object>
</child>
</object>
</child>
</template>
</interface>

View file

@ -11,7 +11,7 @@
<property name="margin-top">8</property>
<property name="margin-bottom">8</property>
<child>
<object class="GtkLabel" id="label">
<object class="GtkLabel">
<property name="label"
bind-source="LSPrefSwitch" bind-property="opt-name" bind-flags="sync-create"/>
<property name="halign">start</property>
@ -19,7 +19,7 @@
</object>
</child>
<child>
<object class="GtkSwitch">
<object class="GtkSwitch" id="switch">
<property name="active"
bind-source="LSPrefSwitch" bind-property="default-state" bind-flags="sync-create"/>
<property name="css-classes">compact</property>

View file

@ -3,7 +3,9 @@
<gresource prefix="/gay/pancake/lsfg-vk/">
<file compressed="true" preprocess="xml-stripblanks">window.ui</file>
<file compressed="true" preprocess="xml-stripblanks">pref/dropdown.ui</file>
<file compressed="true" preprocess="xml-stripblanks">pref/number.ui</file>
<file compressed="true" preprocess="xml-stripblanks">pref/entry.ui</file>
<file compressed="true" preprocess="xml-stripblanks">pref/slider.ui</file>
<file compressed="true" preprocess="xml-stripblanks">pref/switch.ui</file>
</gresource>
</gresources>

View file

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<template class="LSApplicationWindow" parent="AdwApplicationWindow">
<property name="title">lsfg-vk Configuration Window</property>
<property name="default-width">800</property>
@ -45,9 +44,9 @@
</child>
</object>
</child>
</object>
</child>
</object>
</object>
</child>
</object>
</property>
<!-- Split View: Main Content -->
<property name="content">
@ -82,32 +81,20 @@
<object class="AdwPreferencesGroup">
<property name="title">Frame Generation</property>
<!-- Frame Generation: Multiplier -->
<child> <!-- FIXME: number -->
<object class="LSPrefDropdown">
<child>
<object class="LSPrefNumber" id="pref_multiplier">
<property name="opt-name">Multiplier</property>
<property name="default-selection">0</property>
<property name="options">
<object class="GtkStringList">
<items>
<item>2x</item>
<item>3x</item>
<item>4x</item>
</items>
</object>
</property>
</object>
</child>
<!-- Frame Generation: Flow Scale -->
<child> <!-- FIXME: slider -->
<object class="LSPrefEntry">
<child>
<object class="LSPrefSlider" id="pref_flow_scale">
<property name="opt-name">Flow Scale</property>
<property name="tooltip-text">Enter a number between 0.25 and 1.00</property>
<property name="default-text">0.7</property>
</object>
</child>
<!-- Frame Generation: Performance Mode -->
<child>
<object class="LSPrefSwitch">
<object class="LSPrefSwitch" id="pref_performance_mode">
<property name="opt-name">Performance Mode</property>
<property name="default-state">false</property>
</object>
@ -120,14 +107,14 @@
<property name="title">Frame Generation</property>
<!-- Misc: HDR Mode -->
<child>
<object class="LSPrefSwitch">
<object class="LSPrefSwitch" id="pref_hdr_mode">
<property name="opt-name">HDR Mode</property>
<property name="default-state">false</property>
</object>
</child>
<!-- Misc: Experimental Present Mode -->
<child>
<object class="LSPrefDropdown">
<object class="LSPrefDropdown" id="pref_experimental_present_mode">
<property name="opt-name">Experimental Present Mode</property>
<property name="default-selection">0</property>
<property name="options">

View file

@ -1,26 +1,9 @@
use adw;
use gtk::{gio, prelude::*};
pub mod wrapper {
pub mod ui;
pub mod pref;
}
mod ui;
const APP_ID: &str = "gay.pancake.lsfg-vk.ConfigurationUi";
fn main() {
gio::resources_register_include!("ui.gresource")
.expect("Failed to register resources");
let app = adw::Application::builder()
.application_id(APP_ID)
.build();
app.connect_activate(build_ui);
app.run();
}
fn build_ui(app: &adw::Application) {
let window = wrapper::ui::Window::new(app);
window.set_application(Some(app));
window.present();
let app = ui::App::new(APP_ID)
.expect("Failed to create application");
app.run()
}

36
ui/src/ui.rs Normal file
View file

@ -0,0 +1,36 @@
use std::sync::Arc;
use adw;
use gtk::{gio, glib, prelude::*};
pub mod ui;
pub mod pref;
pub struct App {
app: Arc<adw::Application>,
}
impl App {
pub fn new(appid: &str) -> Result<Self, glib::Error> {
gio::resources_register_include!("ui.gresource")?;
let app = adw::Application::builder()
.application_id(appid)
.build();
app.connect_activate(Self::build_ui);
Ok(App {
app: Arc::new(app)
})
}
fn build_ui(app: &adw::Application) {
let window = ui::Window::new(app);
window.set_application(Some(app));
window.present();
}
pub fn run(self){
self.app.run();
}
}

View file

@ -4,6 +4,8 @@ use adw;
pub mod dropdown;
pub mod entry;
pub mod number;
pub mod slider;
pub mod switch;
glib::wrapper! {
@ -22,6 +24,22 @@ glib::wrapper! {
gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
}
glib::wrapper! {
pub struct PrefNumber(ObjectSubclass<number::PrefNumber>)
@extends
adw::PreferencesRow, gtk::ListBoxRow, gtk::Widget,
@implements
gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
}
glib::wrapper! {
pub struct PrefSlider(ObjectSubclass<slider::PrefSlider>)
@extends
adw::PreferencesRow, gtk::ListBoxRow, gtk::Widget,
@implements
gtk::Accessible, gtk::Actionable, gtk::Buildable, gtk::ConstraintTarget;
}
glib::wrapper! {
pub struct PrefEntry(ObjectSubclass<entry::PrefEntry>)
@extends
@ -42,6 +60,18 @@ impl PrefSwitch {
}
}
impl PrefNumber {
pub fn new() -> Self {
glib::Object::new()
}
}
impl PrefSlider {
pub fn new() -> Self {
glib::Object::new()
}
}
impl PrefEntry {
pub fn new() -> Self {
glib::Object::new()

View file

@ -15,6 +15,9 @@ pub struct PrefDropdown {
default_selection: RefCell<u32>,
#[property(get, set)]
options: RefCell<gtk::StringList>,
#[template_child]
pub dropdown: TemplateChild<gtk::DropDown>,
}
#[glib::object_subclass]

View file

@ -14,7 +14,10 @@ pub struct PrefEntry {
#[property(get, set)]
default_text: RefCell<String>,
#[property(get, set)]
tooltip_text: RefCell<String>
tooltip_text: RefCell<String>,
#[template_child]
pub entry: TemplateChild<gtk::Entry>,
}
#[glib::object_subclass]

43
ui/src/ui/pref/number.rs Normal file
View file

@ -0,0 +1,43 @@
use std::cell::RefCell;
use gtk::glib;
use gtk::subclass::prelude::*;
use adw::subclass::prelude::*;
use adw::prelude::*;
#[derive(gtk::CompositeTemplate, glib::Properties, Default)]
#[properties(wrapper_type = super::PrefNumber)]
#[template(resource = "/gay/pancake/lsfg-vk/pref/number.ui")]
pub struct PrefNumber {
#[property(get, set)]
opt_name: RefCell<String>,
#[template_child]
pub number: TemplateChild<gtk::SpinButton>,
}
#[glib::object_subclass]
impl ObjectSubclass for PrefNumber {
const NAME: &'static str = "LSPrefNumber";
type Type = super::PrefNumber;
type ParentType = adw::PreferencesRow;
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
}
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for PrefNumber {
fn constructed(&self) {
self.parent_constructed();
}
}
impl WidgetImpl for PrefNumber {}
impl ListBoxRowImpl for PrefNumber {}
impl PreferencesRowImpl for PrefNumber {}

43
ui/src/ui/pref/slider.rs Normal file
View file

@ -0,0 +1,43 @@
use std::cell::RefCell;
use gtk::glib;
use gtk::subclass::prelude::*;
use adw::subclass::prelude::*;
use adw::prelude::*;
#[derive(gtk::CompositeTemplate, glib::Properties, Default)]
#[properties(wrapper_type = super::PrefSlider)]
#[template(resource = "/gay/pancake/lsfg-vk/pref/slider.ui")]
pub struct PrefSlider {
#[property(get, set)]
opt_name: RefCell<String>,
#[template_child]
pub slider: TemplateChild<gtk::Scale>,
}
#[glib::object_subclass]
impl ObjectSubclass for PrefSlider {
const NAME: &'static str = "LSPrefSlider";
type Type = super::PrefSlider;
type ParentType = adw::PreferencesRow;
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
}
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}
#[glib::derived_properties]
impl ObjectImpl for PrefSlider {
fn constructed(&self) {
self.parent_constructed();
}
}
impl WidgetImpl for PrefSlider {}
impl ListBoxRowImpl for PrefSlider {}
impl PreferencesRowImpl for PrefSlider {}

View file

@ -13,6 +13,9 @@ pub struct PrefSwitch {
opt_name: RefCell<String>,
#[property(get, set)]
default_state: RefCell<bool>,
#[template_child]
pub switch: TemplateChild<gtk::Switch>,
}
#[glib::object_subclass]

73
ui/src/ui/ui/window.rs Normal file
View file

@ -0,0 +1,73 @@
use gtk::{prelude::RangeExt, subclass::prelude::*};
use adw::subclass::prelude::*;
use crate::ui::pref::*;
use gtk::{glib, CompositeTemplate};
#[derive(CompositeTemplate, Default)]
#[template(resource = "/gay/pancake/lsfg-vk/window.ui")]
pub struct Window {
// main config elements
#[template_child]
pref_multiplier: TemplateChild<PrefNumber>,
#[template_child]
pref_flow_scale: TemplateChild<PrefSlider>,
#[template_child]
pref_performance_mode: TemplateChild<PrefSwitch>,
#[template_child]
pref_hdr_mode: TemplateChild<PrefSwitch>,
#[template_child]
pref_experimental_present_mode: TemplateChild<PrefDropdown>,
}
#[glib::object_subclass]
impl ObjectSubclass for Window {
const NAME: &'static str = "LSApplicationWindow";
type Type = super::Window;
type ParentType = adw::ApplicationWindow;
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
}
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}
impl ObjectImpl for Window {
fn constructed(&self) {
self.parent_constructed();
self.pref_multiplier.get()
.imp().number.get().connect_value_changed(|dropdown| {
let selected = dropdown.value();
println!("Multiplier changed: {}", selected);
});
self.pref_flow_scale.get()
.imp().slider.get().connect_value_changed(|slider| {
let value = slider.value();
println!("Flow scale changed: {}", value);
});
self.pref_performance_mode.get()
.imp().switch.get().connect_state_notify(|switch| {
let state = switch.state();
println!("Performance mode changed: {}", state);
});
self.pref_hdr_mode.get()
.imp().switch.get().connect_state_notify(|switch| {
let state = switch.state();
println!("HDR mode changed: {}", state);
});
self.pref_experimental_present_mode.get()
.imp().dropdown.get().connect_selected_notify(|dropdown| {
let selected = dropdown.selected();
println!("Experimental present mode changed: {}", selected);
});
}
}
impl WidgetImpl for Window {}
impl WindowImpl for Window {}
impl ApplicationWindowImpl for Window {}
impl AdwWindowImpl for Window {}
impl AdwApplicationWindowImpl for Window {}

View file

@ -1,36 +0,0 @@
use gtk::subclass::prelude::*;
use adw::subclass::prelude::*;
use gtk::{glib, CompositeTemplate};
#[derive(CompositeTemplate, Default)]
#[template(resource = "/gay/pancake/lsfg-vk/window.ui")]
pub struct Window {
}
#[glib::object_subclass]
impl ObjectSubclass for Window {
const NAME: &'static str = "LSApplicationWindow";
type Type = super::Window;
type ParentType = adw::ApplicationWindow;
fn class_init(klass: &mut Self::Class) {
klass.bind_template();
}
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
obj.init_template();
}
}
impl ObjectImpl for Window {
fn constructed(&self) {
self.parent_constructed();
}
}
impl WidgetImpl for Window {}
impl WindowImpl for Window {}
impl ApplicationWindowImpl for Window {}
impl AdwWindowImpl for Window {}
impl AdwApplicationWindowImpl for Window {}