Skip to content

[FEATURE REQUEST] Newtype support for #[property] #983

Closed
@YaLTeR

Description

@YaLTeR

I have a newtype over f64:

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ScaleRequest {
    FitToAllocation,
    Set(f64),
}

It maps one-to-one to f64 (0. maps to the first item, others map to the second item). I'd like to use it with the properties macro. For GObject it should appear as an f64 property.

Currently this seems to require implementing HasParamSpec, ToValue, From<ScaleRequest> for Value (for some reason?) and FromValue, the last of which requires unsafe code:

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ScaleRequest {
    FitToAllocation,
    Set(f64),
}

impl From<f64> for ScaleRequest {
    fn from(value: f64) -> Self {
        if value == 0. {
            ScaleRequest::FitToAllocation
        } else {
            ScaleRequest::Set(value.clamp(0., 10.))
        }
    }
}

impl glib::HasParamSpec for ScaleRequest {
    type ParamSpec = glib::ParamSpecDouble;
    type SetValue = Self;
    type BuilderFn = fn(&str) -> glib::ParamSpecDoubleBuilder;

    fn param_spec_builder() -> Self::BuilderFn {
        Self::ParamSpec::builder
    }
}

impl From<ScaleRequest> for glib::Value {
    fn from(value: ScaleRequest) -> Self {
        value.to_value()
    }
}

impl glib::ToValue for ScaleRequest {
    fn to_value(&self) -> glib::Value {
        match *self {
            ScaleRequest::FitToAllocation => 0.,
            ScaleRequest::Set(scale) => scale,
        }
        .to_value()
    }

    fn value_type(&self) -> glib::Type {
        f64::static_type()
    }
}

unsafe impl<'a> glib::value::FromValue<'a> for ScaleRequest {
    type Checker = glib::value::GenericValueTypeChecker<f64>;

    unsafe fn from_value(value: &'a glib::Value) -> Self {
        f64::from_value(value).into()
    }
}

Would be great if this could be representable without unsafe code with some kind of pair of From<f64> for T + From<T> for f64.

It's also worth noting that I could instead implement Property with Value = f64 and custom get and set returning f64. However, that would result in my Rust type having getter and setter working with f64 instead of the real type, which is not as nice.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions