mirror of
https://gitlab.freedesktop.org/pipewire/helvum
synced 2026-03-15 19:46:10 +08:00
ui: Port to libadwaita
This ports the application to libadwaita, enabling us to use the libadwaita stylesheet and widgets to better implement the Gnome Human Interface Guidelines.
This commit is contained in:
34
Cargo.lock
generated
34
Cargo.lock
generated
@@ -499,7 +499,7 @@ name = "helvum"
|
|||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"glib",
|
"glib",
|
||||||
"gtk4",
|
"libadwaita",
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"pipewire",
|
"pipewire",
|
||||||
@@ -527,6 +527,38 @@ version = "1.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libadwaita"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06444f4ca05a60693da6e9e2b591bd40a298e65a118a8d5e830771718b3e0253"
|
||||||
|
dependencies = [
|
||||||
|
"gdk-pixbuf",
|
||||||
|
"gdk4",
|
||||||
|
"gio",
|
||||||
|
"glib",
|
||||||
|
"gtk4",
|
||||||
|
"libadwaita-sys",
|
||||||
|
"libc",
|
||||||
|
"pango",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libadwaita-sys"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "021cfe3d1fcfa82411765a791f7e9b32f35dd98ce88d2e3fa10e7320f5cc8ce7"
|
||||||
|
dependencies = [
|
||||||
|
"gdk4-sys",
|
||||||
|
"gio-sys",
|
||||||
|
"glib-sys",
|
||||||
|
"gobject-sys",
|
||||||
|
"gtk4-sys",
|
||||||
|
"libc",
|
||||||
|
"pango-sys",
|
||||||
|
"system-deps",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.147"
|
version = "0.2.147"
|
||||||
|
|||||||
@@ -15,9 +15,10 @@ categories = ["gui", "multimedia"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
pipewire = "0.7.1"
|
pipewire = "0.7.1"
|
||||||
gtk = { version = "0.7", package = "gtk4" }
|
adw = { version = "0.5", package = "libadwaita" }
|
||||||
glib = { version = "0.18", features = ["log"] }
|
glib = { version = "0.18", features = ["log"] }
|
||||||
|
|
||||||
log = "0.4.11"
|
log = "0.4.11"
|
||||||
|
|
||||||
once_cell = "1.7.2"
|
once_cell = "1.7.2"
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ base_id = 'org.pipewire.Helvum'
|
|||||||
|
|
||||||
dependency('glib-2.0', version: '>= 2.66')
|
dependency('glib-2.0', version: '>= 2.66')
|
||||||
dependency('gtk4', version: '>= 4.4.0')
|
dependency('gtk4', version: '>= 4.4.0')
|
||||||
|
dependency('libadwaita-1')
|
||||||
dependency('libpipewire-0.3')
|
dependency('libpipewire-0.3')
|
||||||
|
|
||||||
desktop_file_validate = find_program('desktop-file-validate', required: false)
|
desktop_file_validate = find_program('desktop-file-validate', required: false)
|
||||||
|
|||||||
@@ -14,9 +14,10 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use gtk::{
|
use adw::{
|
||||||
gio,
|
gio,
|
||||||
glib::{self, clone, Receiver},
|
glib::{self, clone, Receiver},
|
||||||
|
gtk,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
subclass::prelude::*,
|
subclass::prelude::*,
|
||||||
};
|
};
|
||||||
@@ -29,11 +30,12 @@ static STYLE: &str = include_str!("style.css");
|
|||||||
mod imp {
|
mod imp {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
use adw::subclass::prelude::AdwApplicationImpl;
|
||||||
use once_cell::unsync::OnceCell;
|
use once_cell::unsync::OnceCell;
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Application {
|
pub struct Application {
|
||||||
pub(super) graphview: ui::graph::GraphView,
|
pub(super) window: ui::Window,
|
||||||
pub(super) graph_manager: OnceCell<GraphManager>,
|
pub(super) graph_manager: OnceCell<GraphManager>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +43,7 @@ mod imp {
|
|||||||
impl ObjectSubclass for Application {
|
impl ObjectSubclass for Application {
|
||||||
const NAME: &'static str = "HelvumApplication";
|
const NAME: &'static str = "HelvumApplication";
|
||||||
type Type = super::Application;
|
type Type = super::Application;
|
||||||
type ParentType = gtk::Application;
|
type ParentType = adw::Application;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectImpl for Application {}
|
impl ObjectImpl for Application {}
|
||||||
@@ -49,36 +51,19 @@ mod imp {
|
|||||||
fn activate(&self) {
|
fn activate(&self) {
|
||||||
let app = &*self.obj();
|
let app = &*self.obj();
|
||||||
|
|
||||||
let scrollwindow = gtk::ScrolledWindow::builder()
|
let graphview = self.window.graph();
|
||||||
.child(&self.graphview)
|
|
||||||
.build();
|
|
||||||
let headerbar = gtk::HeaderBar::new();
|
|
||||||
let zoomentry = ui::graph::ZoomEntry::new(&self.graphview);
|
|
||||||
headerbar.pack_end(&zoomentry);
|
|
||||||
|
|
||||||
let window = gtk::ApplicationWindow::builder()
|
self.window.set_application(Some(app));
|
||||||
.application(app)
|
|
||||||
.default_width(1280)
|
|
||||||
.default_height(720)
|
|
||||||
.title("Helvum - Pipewire Patchbay")
|
|
||||||
.child(&scrollwindow)
|
|
||||||
.build();
|
|
||||||
window
|
|
||||||
.settings()
|
|
||||||
.set_gtk_application_prefer_dark_theme(true);
|
|
||||||
window.set_titlebar(Some(&headerbar));
|
|
||||||
|
|
||||||
let zoom_set_action =
|
let zoom_set_action =
|
||||||
gio::SimpleAction::new("set-zoom", Some(&f64::static_variant_type()));
|
gio::SimpleAction::new("set-zoom", Some(&f64::static_variant_type()));
|
||||||
zoom_set_action.connect_activate(
|
zoom_set_action.connect_activate(clone!(@weak graphview => move|_, param| {
|
||||||
clone!(@weak self.graphview as graphview => move|_, param| {
|
|
||||||
let zoom_factor = param.unwrap().get::<f64>().unwrap();
|
let zoom_factor = param.unwrap().get::<f64>().unwrap();
|
||||||
graphview.set_zoom_factor(zoom_factor, None)
|
graphview.set_zoom_factor(zoom_factor, None)
|
||||||
}),
|
}));
|
||||||
);
|
self.window.add_action(&zoom_set_action);
|
||||||
window.add_action(&zoom_set_action);
|
|
||||||
|
|
||||||
window.show();
|
self.window.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn startup(&self) {
|
fn startup(&self) {
|
||||||
@@ -95,11 +80,12 @@ mod imp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl GtkApplicationImpl for Application {}
|
impl GtkApplicationImpl for Application {}
|
||||||
|
impl AdwApplicationImpl for Application {}
|
||||||
}
|
}
|
||||||
|
|
||||||
glib::wrapper! {
|
glib::wrapper! {
|
||||||
pub struct Application(ObjectSubclass<imp::Application>)
|
pub struct Application(ObjectSubclass<imp::Application>)
|
||||||
@extends gio::Application, gtk::Application,
|
@extends gio::Application, gtk::Application, adw::Application,
|
||||||
@implements gio::ActionGroup, gio::ActionMap;
|
@implements gio::ActionGroup, gio::ActionMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +103,11 @@ impl Application {
|
|||||||
let imp = app.imp();
|
let imp = app.imp();
|
||||||
|
|
||||||
imp.graph_manager
|
imp.graph_manager
|
||||||
.set(GraphManager::new(&imp.graphview, pw_sender, gtk_receiver))
|
.set(GraphManager::new(
|
||||||
|
&imp.window.graph(),
|
||||||
|
pw_sender,
|
||||||
|
gtk_receiver,
|
||||||
|
))
|
||||||
.expect("Should be able to set graph manager");
|
.expect("Should be able to set graph manager");
|
||||||
|
|
||||||
// Add <Control-Q> shortcut for quitting the application.
|
// Add <Control-Q> shortcut for quitting the application.
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use gtk::{glib, prelude::*, subclass::prelude::*};
|
use adw::{glib, prelude::*, subclass::prelude::*};
|
||||||
|
|
||||||
use pipewire::channel::Sender as PwSender;
|
use pipewire::channel::Sender as PwSender;
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ mod graph_manager;
|
|||||||
mod pipewire_connection;
|
mod pipewire_connection;
|
||||||
mod ui;
|
mod ui;
|
||||||
|
|
||||||
use gtk::prelude::*;
|
use adw::{gtk, prelude::*};
|
||||||
use pipewire::spa::{format::MediaType, Direction};
|
use pipewire::spa::{format::MediaType, Direction};
|
||||||
|
|
||||||
/// Messages sent by the GTK thread to notify the pipewire thread.
|
/// Messages sent by the GTK thread to notify the pipewire thread.
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ mod state;
|
|||||||
|
|
||||||
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||||
|
|
||||||
use gtk::glib::{self, clone};
|
use adw::glib::{self, clone};
|
||||||
use log::{debug, info, warn};
|
use log::{debug, info, warn};
|
||||||
use pipewire::{
|
use pipewire::{
|
||||||
link::{Link, LinkChangeMask, LinkInfo, LinkListener, LinkState},
|
link::{Link, LinkChangeMask, LinkInfo, LinkListener, LinkState},
|
||||||
|
|||||||
@@ -36,5 +36,5 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
graphview {
|
graphview {
|
||||||
background-color: @text_view_bg;
|
background-color: @view_bg_color;
|
||||||
}
|
}
|
||||||
@@ -14,11 +14,14 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use gtk::{
|
use adw::{
|
||||||
cairo, gio,
|
gio,
|
||||||
glib::{self, clone},
|
glib::{self, clone},
|
||||||
|
gtk::{
|
||||||
|
self, cairo,
|
||||||
graphene::{self, Point},
|
graphene::{self, Point},
|
||||||
gsk,
|
gsk,
|
||||||
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
subclass::prelude::*,
|
subclass::prelude::*,
|
||||||
};
|
};
|
||||||
@@ -36,11 +39,7 @@ mod imp {
|
|||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
use gtk::{
|
use adw::gtk::gdk::{self};
|
||||||
gdk::{self, RGBA},
|
|
||||||
graphene::Rect,
|
|
||||||
gsk::ColorStop,
|
|
||||||
};
|
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use pipewire::spa::format::MediaType;
|
use pipewire::spa::format::MediaType;
|
||||||
@@ -115,7 +114,7 @@ mod imp {
|
|||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
impl ObjectSubclass for GraphView {
|
impl ObjectSubclass for GraphView {
|
||||||
const NAME: &'static str = "GraphView";
|
const NAME: &'static str = "HelvumGraphView";
|
||||||
type Type = super::GraphView;
|
type Type = super::GraphView;
|
||||||
type ParentType = gtk::Widget;
|
type ParentType = gtk::Widget;
|
||||||
type Interfaces = (gtk::Scrollable,);
|
type Interfaces = (gtk::Scrollable,);
|
||||||
@@ -224,7 +223,7 @@ mod imp {
|
|||||||
let widget = &*self.obj();
|
let widget = &*self.obj();
|
||||||
let alloc = widget.allocation();
|
let alloc = widget.allocation();
|
||||||
|
|
||||||
self.snapshot_background(widget, snapshot);
|
// self.snapshot_background(widget, snapshot);
|
||||||
|
|
||||||
// Draw all visible children
|
// Draw all visible children
|
||||||
self.nodes
|
self.nodes
|
||||||
@@ -462,67 +461,6 @@ mod imp {
|
|||||||
self.obj().add_controller(zoom_gesture);
|
self.obj().add_controller(zoom_gesture);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn snapshot_background(&self, widget: &super::GraphView, snapshot: >k::Snapshot) {
|
|
||||||
// Grid size and line width during neutral zoom (factor 1.0).
|
|
||||||
const NORMAL_GRID_SIZE: f32 = 20.0;
|
|
||||||
const NORMAL_GRID_LINE_WIDTH: f32 = 1.0;
|
|
||||||
|
|
||||||
let zoom_factor = self.zoom_factor.get();
|
|
||||||
let grid_size = NORMAL_GRID_SIZE * zoom_factor as f32;
|
|
||||||
let grid_line_width = NORMAL_GRID_LINE_WIDTH * zoom_factor as f32;
|
|
||||||
|
|
||||||
let alloc = widget.allocation();
|
|
||||||
|
|
||||||
// We need to offset the lines between 0 and (excluding) `grid_size` so the grid moves with
|
|
||||||
// the rest of the view when scrolling.
|
|
||||||
// The offset is rounded so the grid is always aligned to a row of pixels.
|
|
||||||
let hadj = self
|
|
||||||
.hadjustment
|
|
||||||
.borrow()
|
|
||||||
.as_ref()
|
|
||||||
.map(|hadjustment| hadjustment.value())
|
|
||||||
.unwrap_or(0.0);
|
|
||||||
let hoffset = (grid_size - (hadj as f32 % grid_size)) % grid_size;
|
|
||||||
let vadj = self
|
|
||||||
.vadjustment
|
|
||||||
.borrow()
|
|
||||||
.as_ref()
|
|
||||||
.map(|vadjustment| vadjustment.value())
|
|
||||||
.unwrap_or(0.0);
|
|
||||||
let voffset = (grid_size - (vadj as f32 % grid_size)) % grid_size;
|
|
||||||
|
|
||||||
snapshot.push_repeat(
|
|
||||||
&Rect::new(0.0, 0.0, alloc.width() as f32, alloc.height() as f32),
|
|
||||||
Some(&Rect::new(0.0, voffset, alloc.width() as f32, grid_size)),
|
|
||||||
);
|
|
||||||
let grid_color = RGBA::new(0.137, 0.137, 0.137, 1.0);
|
|
||||||
snapshot.append_linear_gradient(
|
|
||||||
&Rect::new(0.0, voffset, alloc.width() as f32, grid_line_width),
|
|
||||||
&Point::new(0.0, 0.0),
|
|
||||||
&Point::new(alloc.width() as f32, 0.0),
|
|
||||||
&[
|
|
||||||
ColorStop::new(0.0, grid_color),
|
|
||||||
ColorStop::new(1.0, grid_color),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
snapshot.pop();
|
|
||||||
|
|
||||||
snapshot.push_repeat(
|
|
||||||
&Rect::new(0.0, 0.0, alloc.width() as f32, alloc.height() as f32),
|
|
||||||
Some(&Rect::new(hoffset, 0.0, grid_size, alloc.height() as f32)),
|
|
||||||
);
|
|
||||||
snapshot.append_linear_gradient(
|
|
||||||
&Rect::new(hoffset, 0.0, grid_line_width, alloc.height() as f32),
|
|
||||||
&Point::new(0.0, 0.0),
|
|
||||||
&Point::new(0.0, alloc.height() as f32),
|
|
||||||
&[
|
|
||||||
ColorStop::new(0.0, grid_color),
|
|
||||||
ColorStop::new(1.0, grid_color),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
snapshot.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw_link(
|
fn draw_link(
|
||||||
&self,
|
&self,
|
||||||
link_cr: &cairo::Context,
|
link_cr: &cairo::Context,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use gtk::{glib, prelude::*, subclass::prelude::*};
|
use adw::{glib, prelude::*, subclass::prelude::*};
|
||||||
use pipewire::spa::format::MediaType;
|
use pipewire::spa::format::MediaType;
|
||||||
|
|
||||||
use super::Port;
|
use super::Port;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use gtk::{glib, prelude::*, subclass::prelude::*};
|
use adw::{glib, gtk, prelude::*, subclass::prelude::*};
|
||||||
use pipewire::spa::Direction;
|
use pipewire::spa::Direction;
|
||||||
|
|
||||||
use super::Port;
|
use super::Port;
|
||||||
|
|||||||
@@ -14,10 +14,10 @@
|
|||||||
//
|
//
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use gtk::{
|
use adw::{
|
||||||
gdk,
|
gdk,
|
||||||
glib::{self, subclass::Signal},
|
glib::{self, subclass::Signal},
|
||||||
graphene,
|
gtk::{self, graphene},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
subclass::prelude::*,
|
subclass::prelude::*,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use gtk::{glib, prelude::*, subclass::prelude::*};
|
use adw::{glib, gtk, prelude::*, subclass::prelude::*};
|
||||||
|
|
||||||
use super::GraphView;
|
use super::GraphView;
|
||||||
|
|
||||||
@@ -127,7 +127,8 @@ mod imp {
|
|||||||
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
|
fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
|
||||||
match pspec.name() {
|
match pspec.name() {
|
||||||
"zoomed-widget" => {
|
"zoomed-widget" => {
|
||||||
let widget: GraphView = value.get().unwrap();
|
let widget: Option<GraphView> = value.get().unwrap();
|
||||||
|
if let Some(ref widget) = widget {
|
||||||
widget.connect_notify_local(
|
widget.connect_notify_local(
|
||||||
Some("zoom-factor"),
|
Some("zoom-factor"),
|
||||||
clone!(@weak self as imp => move |graphview, _| {
|
clone!(@weak self as imp => move |graphview, _| {
|
||||||
@@ -135,7 +136,8 @@ mod imp {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
self.update_zoom_factor_text(widget.zoom_factor());
|
self.update_zoom_factor_text(widget.zoom_factor());
|
||||||
*self.graphview.borrow_mut() = Some(widget);
|
}
|
||||||
|
*self.graphview.borrow_mut() = widget;
|
||||||
}
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,3 +19,6 @@
|
|||||||
//! This module contains gtk widgets needed to present the graphical user interface.
|
//! This module contains gtk widgets needed to present the graphical user interface.
|
||||||
|
|
||||||
pub mod graph;
|
pub mod graph;
|
||||||
|
|
||||||
|
mod window;
|
||||||
|
pub use window::*;
|
||||||
|
|||||||
62
src/ui/window.rs
Normal file
62
src/ui/window.rs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
use adw::{gio, gtk, prelude::*, subclass::prelude::*};
|
||||||
|
|
||||||
|
use super::graph;
|
||||||
|
|
||||||
|
mod imp {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Default, gtk::CompositeTemplate, glib::Properties)]
|
||||||
|
#[properties(wrapper_type = super::Window)]
|
||||||
|
#[template(file = "window.ui")]
|
||||||
|
pub struct Window {
|
||||||
|
#[template_child]
|
||||||
|
pub header_bar: TemplateChild<adw::HeaderBar>,
|
||||||
|
#[template_child]
|
||||||
|
#[property(type = graph::GraphView, get = |_| self.graph.clone())]
|
||||||
|
pub graph: TemplateChild<graph::GraphView>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::object_subclass]
|
||||||
|
impl ObjectSubclass for Window {
|
||||||
|
const NAME: &'static str = "HelvumWindow";
|
||||||
|
type Type = super::Window;
|
||||||
|
type ParentType = adw::ApplicationWindow;
|
||||||
|
|
||||||
|
fn class_init(klass: &mut Self::Class) {
|
||||||
|
// Ensure custom types are registered
|
||||||
|
graph::GraphView::ensure_type();
|
||||||
|
graph::ZoomEntry::ensure_type();
|
||||||
|
|
||||||
|
klass.bind_template();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn instance_init(obj: &glib::subclass::InitializingObject<Self>) {
|
||||||
|
obj.init_template();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[glib::derived_properties]
|
||||||
|
impl ObjectImpl for Window {}
|
||||||
|
impl WidgetImpl for Window {}
|
||||||
|
impl WindowImpl for Window {}
|
||||||
|
impl ApplicationWindowImpl for Window {}
|
||||||
|
impl AdwApplicationWindowImpl for Window {}
|
||||||
|
}
|
||||||
|
|
||||||
|
glib::wrapper! {
|
||||||
|
pub struct Window(ObjectSubclass<imp::Window>)
|
||||||
|
@extends adw::ApplicationWindow, gtk::ApplicationWindow, gtk::Window, gtk::Widget,
|
||||||
|
@implements gio::ActionGroup, gio::ActionMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Window {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
glib::Object::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Window {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
34
src/ui/window.ui
Normal file
34
src/ui/window.ui
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk" version="4.0"/>
|
||||||
|
<requires lib="Adw" version="1.0"/>
|
||||||
|
<template class="HelvumWindow" parent="AdwApplicationWindow">
|
||||||
|
<property name="default-width">1280</property>
|
||||||
|
<property name="default-height">720</property>
|
||||||
|
<property name="title">Helvum - Pipewire Patchbay</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<child>
|
||||||
|
<object class="AdwHeaderBar" id="header_bar">
|
||||||
|
<child type="end">
|
||||||
|
<object class="HelvumZoomEntry">
|
||||||
|
<property name="zoomed-widget">graph</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkScrolledWindow">
|
||||||
|
<child>
|
||||||
|
<object class="HelvumGraphView" id="graph">
|
||||||
|
<property name="hexpand">true</property>
|
||||||
|
<property name="vexpand">true</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
</interface>
|
||||||
Reference in New Issue
Block a user