mpc_valet/components/
tuning_form.rs1use crate::components::Icon;
2use crate::model::LayerVelocityMode;
3use wasm_bindgen::JsCast;
4use web_sys::{HtmlInputElement, InputEvent, MouseEvent};
5use yew::{html, Callback, Component, Context, Html, Properties};
6use yew_utils::components::drop_down::DropDown;
7
8#[derive(Properties, PartialEq)]
9pub struct TuningFormProps {
10 #[prop_or_default]
11 pub pitch_preference: f32,
12
13 #[prop_or_default]
14 pub layer_velocity_mode: LayerVelocityMode,
15
16 #[prop_or_default]
17 pub program_name: String,
18
19 #[prop_or_default]
20 pub on_pitch_preference_change: Callback<f32>,
21
22 #[prop_or_default]
23 pub on_layer_velocity_mode_change: Callback<LayerVelocityMode>,
24
25 #[prop_or_default]
26 pub on_program_name_change: Callback<String>,
27
28 #[prop_or_default]
29 pub on_save: Callback<()>,
30}
31
32pub enum TuningFormMessages {
33 PitchPreferenceChange(f32),
34 LayerVelocityModeChange(LayerVelocityMode),
35 ProgramNameChanged(String),
36 Save,
37}
38
39#[derive(Default)]
41pub struct TuningForm {}
42
43impl Component for TuningForm {
44 type Message = TuningFormMessages;
45 type Properties = TuningFormProps;
46
47 fn create(_ctx: &Context<Self>) -> Self {
48 Self {}
49 }
50
51 fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
52 match msg {
53 TuningFormMessages::PitchPreferenceChange(pitch_preference) => {
54 ctx.props()
55 .on_pitch_preference_change
56 .emit(pitch_preference);
57 false
58 }
59 TuningFormMessages::LayerVelocityModeChange(mode) => {
60 ctx.props().on_layer_velocity_mode_change.emit(mode);
61 false
62 }
63 TuningFormMessages::ProgramNameChanged(name) => {
64 ctx.props().on_program_name_change.emit(name);
65 false
66 }
67 TuningFormMessages::Save => {
68 ctx.props().on_save.emit(());
69 false
70 }
71 }
72 }
73
74 fn view(&self, ctx: &Context<Self>) -> Html {
75 let layer_help_text = match ctx.props().layer_velocity_mode {
76 LayerVelocityMode::Automatic => {
77 "Each layer will only be used for a range of the velocity."
78 }
79 LayerVelocityMode::Unison => "All the layers will play at the same time.",
80 };
81 html! {
82 <div class="box">
83 <div class="block">
84 <div class="field">
85 <label class="label">{"Pitch Preference"}</label>
86 <div class="control">
87 <input
88 id="pitch_preference"
89 type="range"
90 min=0
91 max=1
92 step=0.01
93 value={ctx.props().pitch_preference.to_string()}
94 oninput={TuningForm::on_pitch_preference_change(ctx)}
95 />
96 </div>
97 </div>
98 <div class="field">
99 <label class="label">{"Layer Velocity Mode"}</label>
100 <div class="control">
101 <div class="select">
102 <DropDown<LayerVelocityMode>
103 initial={ctx.props().layer_velocity_mode}
104 options={vec![LayerVelocityMode::Unison, LayerVelocityMode::Automatic]}
105 selection_changed={ctx.link().callback(TuningFormMessages::LayerVelocityModeChange)}
106 />
107 </div>
108 </div>
109 <p class="help">{layer_help_text}</p>
110 </div>
111 </div>
112 <div class="block">
113 <div class="field has-addons">
114 <div class="control">
115 <input
116 class="input"
117 type="text"
118 placeholder="Program Name"
119 value={ctx.props().program_name.clone()}
120 oninput={TuningForm::on_program_name_change(ctx)}
121 />
122 </div>
123 <div class="control">
124 <button class="button is-link" onclick={ctx.link().callback(|_: MouseEvent| TuningFormMessages::Save)}>
125 <Icon icon="save" text="Save" />
126 </button>
127 </div>
128 </div>
129 </div>
130 </div>
131 }
132 }
133}
134
135impl TuningForm {
136 fn on_pitch_preference_change(ctx: &Context<TuningForm>) -> Callback<InputEvent> {
137 ctx.link().batch_callback(|e: InputEvent| {
138 let input: HtmlInputElement = e
139 .target()
140 .and_then(|t| t.dyn_into::<HtmlInputElement>().ok())?;
141 Some(TuningFormMessages::PitchPreferenceChange(
142 input.value_as_number() as f32,
143 ))
144 })
145 }
146
147 fn on_program_name_change(ctx: &Context<TuningForm>) -> Callback<InputEvent> {
148 ctx.link().batch_callback(|e: InputEvent| {
149 let input: HtmlInputElement = e
150 .target()
151 .and_then(|t| t.dyn_into::<HtmlInputElement>().ok())?;
152 Some(TuningFormMessages::ProgramNameChanged(input.value()))
153 })
154 }
155}