Skip to content

Commit

Permalink
refactor: use properties macro
Browse files Browse the repository at this point in the history
  • Loading branch information
SeaDve committed Jul 24, 2023
1 parent d52dbaa commit d5d0cfb
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 321 deletions.
2 changes: 1 addition & 1 deletion src/area_selector/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ impl AreaSelector {

// Setup paintable
let paintable = sink.property::<gdk::Paintable>("paintable");
imp.view_port.set_paintable(Some(&paintable));
imp.view_port.set_paintable(Some(paintable));

pipeline.set_state(gst::State::Playing)?;

Expand Down
133 changes: 42 additions & 91 deletions src/area_selector/view_port.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,16 @@ impl Selection {

mod imp {
use super::*;
use once_cell::sync::Lazy;

#[derive(Debug, Default)]
#[derive(Debug, Default, glib::Properties)]
#[properties(wrapper_type = super::ViewPort)]
pub struct ViewPort {
#[property(get, set = Self::set_paintable, explicit_notify, nullable)]
pub(super) paintable: RefCell<Option<gdk::Paintable>>,
#[property(get)]
pub(super) selection: Cell<Option<Selection>>,

pub(super) paintable_rect: Cell<Option<Rect>>,

pub(super) selection: Cell<Option<Selection>>,
pub(super) selection_handles: Cell<Option<[Rect; 4]>>, // [top-left, top-right, bottom-right, bottom-left]

pub(super) drag_start: Cell<Option<Point>>,
Expand All @@ -132,43 +133,6 @@ mod imp {
}

impl ObjectImpl for ViewPort {
fn properties() -> &'static [glib::ParamSpec] {
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
vec![
glib::ParamSpecObject::builder::<gdk::Paintable>("paintable")
.explicit_notify()
.build(),
glib::ParamSpecBoxed::builder::<Selection>("selection")
.read_only()
.build(),
]
});

PROPERTIES.as_ref()
}

fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) {
let obj = self.obj();

match pspec.name() {
"paintable" => {
let paintable: Option<gdk::Paintable> = value.get().unwrap();
obj.set_paintable(paintable.as_ref());
}
_ => unimplemented!(),
}
}

fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let obj = self.obj();

match pspec.name() {
"paintable" => obj.paintable().to_value(),
"selection" => obj.selection().to_value(),
_ => unimplemented!(),
}
}

fn constructed(&self) {
self.parent_constructed();

Expand Down Expand Up @@ -198,6 +162,8 @@ mod imp {
}));
obj.add_controller(gesture_drag);
}

crate::derived_properties!();
}

impl WidgetImpl for ViewPort {
Expand Down Expand Up @@ -344,67 +310,52 @@ mod imp {
}
}
}
}

glib::wrapper! {
pub struct ViewPort(ObjectSubclass<imp::ViewPort>)
@extends gtk::Widget;
}

impl ViewPort {
pub fn new() -> Self {
glib::Object::builder().build()
}

pub fn set_paintable(&self, paintable: Option<&impl IsA<gdk::Paintable>>) {
let paintable = paintable.map(|p| p.as_ref());
impl ViewPort {
fn set_paintable(&self, paintable: Option<gdk::Paintable>) {
let obj = self.obj();

if paintable == self.paintable().as_ref() {
return;
}
if paintable == obj.paintable() {
return;
}

let _freeze_guard = self.freeze_notify();
let _freeze_guard = obj.freeze_notify();

let imp = self.imp();
let mut handler_ids = self.handler_ids.borrow_mut();

let mut handler_ids = imp.handler_ids.borrow_mut();
if let Some(previous_paintable) = self.paintable.replace(paintable.clone()) {
for handler_id in handler_ids.drain(..) {
previous_paintable.disconnect(handler_id);
}
}

if let Some(previous_paintable) = imp.paintable.replace(paintable.cloned()) {
for handler_id in handler_ids.drain(..) {
previous_paintable.disconnect(handler_id);
if let Some(paintable) = paintable {
handler_ids.push(paintable.connect_invalidate_contents(
clone!(@weak obj => move |_| {
obj.queue_draw();
}),
));
handler_ids.push(
paintable.connect_invalidate_size(clone!(@weak obj => move |_| {
obj.queue_resize();
})),
);
}
}

if let Some(paintable) = paintable {
handler_ids.push(paintable.connect_invalidate_contents(
clone!(@weak self as obj => move |_| {
obj.queue_draw();
}),
));
handler_ids.push(paintable.connect_invalidate_size(
clone!(@weak self as obj => move |_| {
obj.queue_resize();
}),
));
obj.queue_resize();
obj.notify_paintable();
}

self.queue_resize();
self.notify("paintable");
}

pub fn paintable(&self) -> Option<gdk::Paintable> {
self.imp().paintable.borrow().clone()
}
}

pub fn selection(&self) -> Option<Selection> {
self.imp().selection.get()
}
glib::wrapper! {
pub struct ViewPort(ObjectSubclass<imp::ViewPort>)
@extends gtk::Widget;
}

pub fn connect_selection_notify<F>(&self, f: F) -> glib::SignalHandlerId
where
F: Fn(&Self) + 'static,
{
self.connect_notify_local(Some("selection"), move |obj, _| f(obj))
impl ViewPort {
pub fn new() -> Self {
glib::Object::builder().build()
}

pub fn paintable_rect(&self) -> Option<Rect> {
Expand All @@ -419,7 +370,7 @@ impl ViewPort {

fn set_selection(&self, selection: Option<Selection>) {
self.imp().selection.set(selection);
self.notify("selection");
self.notify_selection();
}

fn on_enter(&self, _controller: &gtk::EventControllerMotion, x: f64, y: f64) {
Expand Down
4 changes: 2 additions & 2 deletions src/preferences_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ mod imp {
}

impl ObjectImpl for PreferencesWindow {
crate::derived_properties!();

fn constructed(&self) {
self.parent_constructed();

Expand Down Expand Up @@ -133,6 +131,8 @@ mod imp {
}
}));
}

crate::derived_properties!();
}

impl WidgetImpl for PreferencesWindow {}
Expand Down
120 changes: 22 additions & 98 deletions src/recording.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use gettextrs::gettext;
use gst::prelude::*;
use gtk::{
gio::{self, prelude::*},
glib::{self, clone, closure_local, subclass::prelude::*, translate::IntoGlib},
glib::{self, clone, closure_local, subclass::prelude::*},
};
use once_cell::{sync::Lazy, unsync::OnceCell};

Expand Down Expand Up @@ -63,17 +63,20 @@ mod imp {
use super::*;
use glib::subclass::Signal;

#[derive(Debug, Default)]
#[derive(Debug, Default, glib::Properties)]
#[properties(wrapper_type = super::Recording)]
pub struct Recording {
#[property(get)]
pub(super) state: Cell<State>,
#[property(get)]
pub(super) duration: Cell<gst::ClockTime>,

pub(super) file: OnceCell<gio::File>,

pub(super) timer: RefCell<Option<Timer>>,
pub(super) session: RefCell<Option<ScreencastSession>>,
pub(super) duration_source_id: RefCell<Option<glib::SourceId>>,
pub(super) pipeline: OnceCell<gst::Pipeline>,

pub(super) state: Cell<State>,
pub(super) duration: Cell<gst::ClockTime>,
}

#[glib::object_subclass]
Expand All @@ -83,42 +86,6 @@ mod imp {
}

impl ObjectImpl for Recording {
fn properties() -> &'static [glib::ParamSpec] {
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| {
vec![
glib::ParamSpecBoxed::builder::<State>("state")
.read_only()
.build(),
glib::ParamSpecUInt64::builder("duration")
.maximum(gst::ClockTime::MAX.into_glib())
.read_only()
.build(),
]
});

PROPERTIES.as_ref()
}

fn property(&self, _id: usize, pspec: &glib::ParamSpec) -> glib::Value {
let obj = self.obj();

match pspec.name() {
"state" => obj.state().to_value(),
"duration" => obj.duration().to_value(),
_ => unimplemented!(),
}
}

fn signals() -> &'static [glib::subclass::Signal] {
static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| {
vec![Signal::builder("finished")
.param_types([BoxedResult::static_type()])
.build()]
});

SIGNALS.as_ref()
}

fn dispose(&self) {
if let Some(timer) = self.timer.take() {
timer.cancel();
Expand All @@ -138,6 +105,18 @@ mod imp {
source_id.remove();
}
}

crate::derived_properties!();

fn signals() -> &'static [glib::subclass::Signal] {
static SIGNALS: Lazy<Vec<Signal>> = Lazy::new(|| {
vec![Signal::builder("finished")
.param_types([BoxedResult::static_type()])
.build()]
});

SIGNALS.as_ref()
}
}
}

Expand Down Expand Up @@ -358,28 +337,6 @@ impl Recording {
self.delete_file();
}

pub fn state(&self) -> State {
self.imp().state.get()
}

pub fn connect_state_notify<F>(&self, f: F) -> glib::SignalHandlerId
where
F: Fn(&Self) + 'static,
{
self.connect_notify_local(Some("state"), move |obj, _| f(obj))
}

pub fn duration(&self) -> gst::ClockTime {
self.imp().duration.get()
}

pub fn connect_duration_notify<F>(&self, f: F) -> glib::SignalHandlerId
where
F: Fn(&Self) + 'static,
{
self.connect_notify_local(Some("duration"), move |obj, _| f(obj))
}

pub fn connect_finished<F>(&self, f: F) -> glib::SignalHandlerId
where
F: Fn(&Self, &Result<gio::File>) + 'static,
Expand Down Expand Up @@ -413,7 +370,7 @@ impl Recording {
}

self.imp().state.replace(state);
self.notify("state");
self.notify_state();
}

fn pipeline(&self) -> &gst::Pipeline {
Expand Down Expand Up @@ -467,7 +424,7 @@ impl Recording {
}

self.imp().duration.set(clock_time);
self.notify("duration");
self.notify_duration();
}

fn handle_bus_message(&self, message: &gst::Message) -> glib::Continue {
Expand Down Expand Up @@ -640,36 +597,3 @@ async fn new_screencast_session(

Ok((screencast_session, streams, restore_token, fd))
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn duration() {
let recording = Recording::new();
assert_eq!(recording.duration(), gst::ClockTime::ZERO);
assert_eq!(
recording.property::<gst::ClockTime>("duration"),
gst::ClockTime::ZERO
);
assert_eq!(
recording.property::<u64>("duration"),
gst::ClockTime::ZERO.into_glib()
);

recording
.imp()
.duration
.set(gst::ClockTime::from_seconds(3));
assert_eq!(recording.duration(), gst::ClockTime::from_seconds(3));
assert_eq!(
recording.property::<gst::ClockTime>("duration"),
gst::ClockTime::from_seconds(3)
);
assert_eq!(
recording.property::<u64>("duration"),
gst::ClockTime::from_seconds(3).into_glib()
);
}
}
Loading

0 comments on commit d5d0cfb

Please sign in to comment.