multitouch 0.3.2

Raw macOS multitouch, gesture recognition, device monitoring, and Force Touch haptics
Documentation
use crate::cf::{Cf, array, dictionary, number, number_f32, string};
use crate::{BaseWaveform, IntensityMultipliers, ToneWaveform};
use objc2_core_foundation::{CFDictionary, CFRetained};

#[derive(Clone, Debug)]
pub struct HapticPattern {
    pub base_waveform: BaseWaveform,
    pub tones: Vec<ToneWaveform>,
    pub base_multipliers: Option<IntensityMultipliers>,
    pub tone_multipliers: Option<IntensityMultipliers>,
}

impl HapticPattern {
    pub fn new(base_waveform: BaseWaveform) -> Self {
        Self {
            base_waveform,
            tones: Vec::new(),
            base_multipliers: None,
            tone_multipliers: None,
        }
    }

    pub fn with_tones(mut self, tones: impl IntoIterator<Item = ToneWaveform>) -> Self {
        self.tones = tones.into_iter().collect();
        self
    }

    pub fn with_base_multipliers(mut self, multipliers: IntensityMultipliers) -> Self {
        self.base_multipliers = Some(multipliers);
        self
    }

    pub fn with_tone_multipliers(mut self, multipliers: IntensityMultipliers) -> Self {
        self.tone_multipliers = Some(multipliers);
        self
    }

    pub(super) fn to_cf_dictionary(&self) -> CFRetained<CFDictionary> {
        dictionary([
            (
                "BaseWaveform",
                Some(waveform_dictionary(self.base_waveform)),
            ),
            (
                "Tones",
                (!self.tones.is_empty()).then(|| {
                    let tones: Vec<_> = self.tones.iter().copied().map(tone_dictionary).collect();
                    array(&tones).into()
                }),
            ),
            (
                "BaseMultipliers",
                self.base_multipliers.map(multiplier_dictionary),
            ),
            (
                "ToneMultipliers",
                self.tone_multipliers.map(multiplier_dictionary),
            ),
        ])
    }
}

fn waveform_dictionary(waveform: BaseWaveform) -> Cf {
    dictionary([
        ("Type", Some(string(waveform.kind.as_str()))),
        ("DurationMS", Some(number(waveform.duration_ms))),
        ("Amplitude", Some(number(waveform.amplitude))),
    ])
    .into()
}

fn tone_dictionary(tone: ToneWaveform) -> Cf {
    dictionary([
        ("Type", Some(string(tone.kind.as_str()))),
        ("DelayMS", Some(number(tone.delay_ms))),
        ("DurationMS", Some(number(tone.duration_ms))),
        ("Amplitude", Some(number(tone.amplitude))),
        ("FrequencykHz", Some(number(tone.frequency_khz))),
    ])
    .into()
}

fn multiplier_dictionary(m: IntensityMultipliers) -> Cf {
    dictionary([
        ("Light", Some(number_f32(m.light))),
        ("Medium", Some(number_f32(m.medium))),
        ("Firm", Some(number_f32(m.firm))),
    ])
    .into()
}