Skip to content
This repository has been archived by the owner on Mar 4, 2024. It is now read-only.

Commit

Permalink
WIP: macro for *Impl, *ImplExt, IsSubclassable boilerplate
Browse files Browse the repository at this point in the history
Just a prototype, but this seems like it could be helpful, in the
absence of full gir-based generation. Not sure if this method will work
for all implementations.
  • Loading branch information
ids1024 committed Dec 24, 2020
1 parent 8a4c2d2 commit ebe878e
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 388 deletions.
47 changes: 47 additions & 0 deletions glib/src/subclass/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,50 @@ pub use self::types::{
register_type, InitializingObject, InitializingType, SignalClassHandlerToken,
SignalInvocationHint, TypeData,
};

#[macro_export]
macro_rules! is_subclassable {
($wrapty:ident, $superty:ident, $prefix:ident @default_override_vfuncs;
$(
fn $fnname:ident(&self, $($arg:ident: $argty:ty),+$(,)?) $(-> $retty:ty)?;
)*
) => {
$crate::is_subclassable!($wrapty, $superty, $prefix;
$(
fn $fnname(&self, $($arg: $argty),+) $(-> $retty)?;
)*);

paste::paste! {
unsafe impl<T: [<$wrapty Impl>]> IsSubclassable<T> for $wrapty {
fn override_vfuncs(class: &mut glib::Class<Self>) {
<$superty as IsSubclassable<T>>::override_vfuncs(class);

let klass = class.as_mut();
$(
klass.$fnname = Some([<$prefix $fnname>]::<T>);
)*
}
}
}
};
($wrapty:ident, $superty:ident, $prefix:ident;
$(
fn $fnname:ident(&self, $($arg:ident: $argty:ty),+$(,)?) $(-> $retty:ty)?;
)*
) => {
paste::paste! {
pub trait [<$wrapty Impl>]: [<$wrapty ImplExt>] + [<$superty Impl>] {
$(
fn $fnname(&self, $($arg: $argty),+) $(-> $retty)? {
self.[<parent_ $fnname>]($($arg),+)
}
)*
}
pub trait [<$wrapty ImplExt>]: ObjectImpl {
$(
fn [<parent_ $fnname>](&self, $($arg: $argty),+) $(-> $retty)?;
)*
}
}
};
}
1 change: 1 addition & 0 deletions gtk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ glib = { path = "../glib" }
gdk = { path = "../gdk" }
gdk-pixbuf = { path = "../gdk-pixbuf" }
pango = { path = "../pango" }
paste = "1.0"

[dev-dependencies]
gir-format-check = "^0.1"
34 changes: 12 additions & 22 deletions gtk/src/subclass/application.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,15 @@ use glib::translate::*;

use glib::subclass::prelude::*;

use crate::Application;
use crate::Window;

pub trait GtkApplicationImpl:
GtkApplicationImplExt + gio::subclass::prelude::ApplicationImpl
{
fn window_added(&self, application: &Self::Type, window: &Window) {
self.parent_window_added(application, window)
}
use gio::subclass::ApplicationImpl;

fn window_removed(&self, application: &Self::Type, window: &Window) {
self.parent_window_removed(application, window)
}
}
use crate::Application as GtkApplication;
use crate::Window;

pub trait GtkApplicationImplExt: ObjectSubclass {
fn parent_window_added(&self, application: &Self::Type, window: &Window);
fn parent_window_removed(&self, application: &Self::Type, window: &Window);
}
glib::is_subclassable!(GtkApplication, Application, application_;
fn window_added(&self, application: &Self::Type, window: &Window);
fn window_removed(&self, application: &Self::Type, window: &Window);
);

impl<T: GtkApplicationImpl> GtkApplicationImplExt for T {
fn parent_window_added(&self, application: &Self::Type, window: &Window) {
Expand All @@ -34,7 +24,7 @@ impl<T: GtkApplicationImpl> GtkApplicationImplExt for T {
if let Some(f) = (*parent_class).window_added {
f(
application
.unsafe_cast_ref::<Application>()
.unsafe_cast_ref::<GtkApplication>()
.to_glib_none()
.0,
window.to_glib_none().0,
Expand All @@ -50,7 +40,7 @@ impl<T: GtkApplicationImpl> GtkApplicationImplExt for T {
if let Some(f) = (*parent_class).window_removed {
f(
application
.unsafe_cast_ref::<Application>()
.unsafe_cast_ref::<GtkApplication>()
.to_glib_none()
.0,
window.to_glib_none().0,
Expand All @@ -60,15 +50,15 @@ impl<T: GtkApplicationImpl> GtkApplicationImplExt for T {
}
}

unsafe impl<T: GtkApplicationImpl> IsSubclassable<T> for Application {
unsafe impl<T: GtkApplicationImpl> IsSubclassable<T> for GtkApplication {
fn override_vfuncs(class: &mut ::glib::Class<Self>) {
unsafe extern "C" fn application_window_added<T: GtkApplicationImpl>(
ptr: *mut ffi::GtkApplication,
wptr: *mut ffi::GtkWindow,
) {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.get_impl();
let wrap: Borrowed<Application> = from_glib_borrow(ptr);
let wrap: Borrowed<GtkApplication> = from_glib_borrow(ptr);

imp.window_added(wrap.unsafe_cast_ref(), &from_glib_borrow(wptr))
}
Expand All @@ -78,7 +68,7 @@ unsafe impl<T: GtkApplicationImpl> IsSubclassable<T> for Application {
) {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.get_impl();
let wrap: Borrowed<Application> = from_glib_borrow(ptr);
let wrap: Borrowed<GtkApplication> = from_glib_borrow(ptr);

imp.window_removed(wrap.unsafe_cast_ref(), &from_glib_borrow(wptr))
}
Expand Down
28 changes: 4 additions & 24 deletions gtk/src/subclass/button.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,10 @@ use glib::Cast;
use super::widget::WidgetImpl;
use crate::{Button, Widget};

pub trait ButtonImpl: ButtonImplExt + WidgetImpl {
fn activate(&self, button: &Self::Type) {
self.parent_activate(button)
}

fn clicked(&self, button: &Self::Type) {
self.parent_clicked(button)
}
}

pub trait ButtonImplExt: ObjectSubclass {
fn parent_activate(&self, button: &Self::Type);
fn parent_clicked(&self, button: &Self::Type);
}
glib::is_subclassable!(Button, Widget, button_ @default_override_vfuncs;
fn activate(&self, button: &Self::Type);
fn clicked(&self, button: &Self::Type);
);

impl<T: ButtonImpl> ButtonImplExt for T {
fn parent_activate(&self, button: &Self::Type) {
Expand All @@ -44,16 +34,6 @@ impl<T: ButtonImpl> ButtonImplExt for T {
}
}

unsafe impl<T: ButtonImpl> IsSubclassable<T> for Button {
fn override_vfuncs(class: &mut glib::Class<Self>) {
<Widget as IsSubclassable<T>>::override_vfuncs(class);

let klass = class.as_mut();
klass.activate = Some(button_activate::<T>);
klass.clicked = Some(button_clicked::<T>);
}
}

unsafe extern "C" fn button_activate<T: ButtonImpl>(ptr: *mut ffi::GtkButton) {
let instance = &*(ptr as *mut T::Instance);
let imp = instance.get_impl();
Expand Down
33 changes: 3 additions & 30 deletions gtk/src/subclass/cell_renderer_accel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,17 @@ use super::cell_renderer_text::CellRendererTextImpl;
use crate::CellRendererAccel;
use crate::CellRendererText;

pub trait CellRendererAccelImpl: CellRendererAccelImplExt + CellRendererTextImpl {
glib::is_subclassable!(CellRendererAccel, CellRendererText, cell_renderer_ @default_override_vfuncs;
fn accel_edited(
&self,
renderer: &Self::Type,
path: &str,
accel_key: u32,
accel_mods: gdk::ModifierType,
hardware_keycode: u32,
) {
self.parent_accel_edited(renderer, path, accel_key, accel_mods, hardware_keycode);
}

fn accel_cleared(&self, renderer: &Self::Type, path: &str) {
self.parent_accel_cleared(renderer, path);
}
}

pub trait CellRendererAccelImplExt: ObjectSubclass {
fn parent_accel_edited(
&self,
renderer: &Self::Type,
path: &str,
accel_key: u32,
accel_mods: gdk::ModifierType,
hardware_keycode: u32,
);
fn parent_accel_cleared(&self, renderer: &Self::Type, path: &str);
}
fn accel_cleared(&self, renderer: &Self::Type, path: &str);
);

impl<T: CellRendererAccelImpl> CellRendererAccelImplExt for T {
fn parent_accel_edited(
Expand Down Expand Up @@ -85,16 +68,6 @@ impl<T: CellRendererAccelImpl> CellRendererAccelImplExt for T {
}
}

unsafe impl<T: CellRendererAccelImpl> IsSubclassable<T> for CellRendererAccel {
fn override_vfuncs(class: &mut ::glib::Class<Self>) {
<CellRendererText as IsSubclassable<T>>::override_vfuncs(class);

let klass = class.as_mut();
klass.accel_edited = Some(cell_renderer_accel_edited::<T>);
klass.accel_cleared = Some(cell_renderer_accel_cleared::<T>);
}
}

unsafe extern "C" fn cell_renderer_accel_edited<T: CellRendererAccelImpl>(
ptr: *mut ffi::GtkCellRendererAccel,
path: *const c_char,
Expand Down
Loading

0 comments on commit ebe878e

Please sign in to comment.