Add a placeholder for a parameter slider widget
This commit is contained in:
parent
5711f77cc7
commit
291abb8bcf
6 changed files with 223 additions and 16 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1396,7 +1396,7 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_baseview"
|
name = "iced_baseview"
|
||||||
version = "0.0.3"
|
version = "0.0.3"
|
||||||
source = "git+https://github.com/robbert-vdh/iced_baseview.git?branch=feature/update-dependencies#1109df27432ca3837673f6e11fa1914d33ce93f3"
|
source = "git+https://github.com/robbert-vdh/iced_baseview.git?branch=feature/update-dependencies#d2ab5282141790fabdeb7ad028d23848f9641ac0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"baseview",
|
"baseview",
|
||||||
"copypasta",
|
"copypasta",
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
//!
|
//!
|
||||||
//! TODO: Proper usage example, for now check out the gain_gui example
|
//! TODO: Proper usage example, for now check out the gain_gui example
|
||||||
|
|
||||||
use baseview::{Size, WindowOpenOptions, WindowScalePolicy};
|
use baseview::{WindowOpenOptions, WindowScalePolicy};
|
||||||
use crossbeam::atomic::AtomicCell;
|
use crossbeam::atomic::AtomicCell;
|
||||||
use crossbeam::channel;
|
use crossbeam::channel;
|
||||||
use nih_plug::prelude::{Editor, GuiContext, ParentWindowHandle};
|
use nih_plug::prelude::{Editor, GuiContext, ParentWindowHandle};
|
||||||
|
@ -106,12 +106,12 @@ pub trait IcedEditor: 'static + Send + Sync + Sized {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See [`Application::renderer_settings`].
|
/// See [`Application::renderer_settings`].
|
||||||
fn renderer_settings() -> iced_baseview::renderer::settings::Settings {
|
fn renderer_settings() -> iced_baseview::backend::settings::Settings {
|
||||||
iced_baseview::renderer::settings::Settings {
|
iced_baseview::backend::settings::Settings {
|
||||||
// Enable some anti-aliasing by default. Since GUIs are likely very simple and most of
|
// Enable some anti-aliasing by default. Since GUIs are likely very simple and most of
|
||||||
// the work will be on the CPU anyways this should not affect performance much.
|
// the work will be on the CPU anyways this should not affect performance much.
|
||||||
antialiasing: Some(iced_baseview::renderer::settings::Antialiasing::MSAAx4),
|
antialiasing: Some(iced_baseview::backend::settings::Antialiasing::MSAAx4),
|
||||||
..iced_baseview::renderer::settings::Settings::default()
|
..iced_baseview::backend::settings::Settings::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,7 +196,7 @@ impl<E: IcedEditor> Editor for IcedEditorWrapper<E> {
|
||||||
window: WindowOpenOptions {
|
window: WindowOpenOptions {
|
||||||
title: String::from("iced window"),
|
title: String::from("iced window"),
|
||||||
// Baseview should be doing the DPI scaling for us
|
// Baseview should be doing the DPI scaling for us
|
||||||
size: Size::new(unscaled_width as f64, unscaled_height as f64),
|
size: baseview::Size::new(unscaled_width as f64, unscaled_height as f64),
|
||||||
// NOTE: For some reason passing 1.0 here causes the UI to be scaled on macOS but
|
// NOTE: For some reason passing 1.0 here causes the UI to be scaled on macOS but
|
||||||
// not the mouse events.
|
// not the mouse events.
|
||||||
scale: scaling_factor
|
scale: scaling_factor
|
||||||
|
|
|
@ -1,7 +1,16 @@
|
||||||
//! Widgets and utilities for making widgets to integrate iced with NIH-plug.
|
//! Widgets and utilities for making widgets to integrate iced with NIH-plug.
|
||||||
|
//!
|
||||||
|
//! # Note
|
||||||
|
//!
|
||||||
|
//! None of these widgets are finalized, and their sizes or looks can change at any point. Feel free
|
||||||
|
//! to copy the widgets and modify them to your personal taste.
|
||||||
|
|
||||||
use nih_plug::param::internals::ParamPtr;
|
use nih_plug::param::internals::ParamPtr;
|
||||||
|
|
||||||
|
mod param_slider;
|
||||||
|
|
||||||
|
pub use param_slider::ParamSlider;
|
||||||
|
|
||||||
/// A message to update a parameter value. Since NIH-plug manages the parameters, interacting with
|
/// A message to update a parameter value. Since NIH-plug manages the parameters, interacting with
|
||||||
/// parameter values with iced works a little different from updating any other state. This main
|
/// parameter values with iced works a little different from updating any other state. This main
|
||||||
/// [`IcedEditor`][super::IcedEditor] should have a [`Message`][super::IcedEditor::Message] variant
|
/// [`IcedEditor`][super::IcedEditor] should have a [`Message`][super::IcedEditor::Message] variant
|
||||||
|
|
199
nih_plug_iced/src/widgets/param_slider.rs
Normal file
199
nih_plug_iced/src/widgets/param_slider.rs
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
//! A slider that integrates with NIH-plug's [`Param`] types.
|
||||||
|
|
||||||
|
use crate::backend;
|
||||||
|
use crate::event::{self, Event};
|
||||||
|
use crate::layout;
|
||||||
|
use crate::mouse;
|
||||||
|
use crate::renderer;
|
||||||
|
use crate::text;
|
||||||
|
use crate::{Clipboard, Color, Element, Layout, Length, Point, Rectangle, Shell, Size, Widget};
|
||||||
|
use nih_plug::prelude::Param;
|
||||||
|
|
||||||
|
use super::ParamMessage;
|
||||||
|
|
||||||
|
/// A slider that integrates with NIH-plug's [`Param`] types.
|
||||||
|
///
|
||||||
|
/// TODO: There are currently no styling options at all
|
||||||
|
pub struct ParamSlider<'a, P: Param, Renderer: text::Renderer> {
|
||||||
|
param: &'a P,
|
||||||
|
|
||||||
|
height: Length,
|
||||||
|
width: Length,
|
||||||
|
text_size: Option<u16>,
|
||||||
|
font: Renderer::Font,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, P: Param, Renderer: text::Renderer> ParamSlider<'a, P, Renderer> {
|
||||||
|
/// Creates a new [`ParamSlider`] for the given parameter.
|
||||||
|
pub fn new(param: &'a P) -> Self {
|
||||||
|
Self {
|
||||||
|
param,
|
||||||
|
width: Length::Units(180),
|
||||||
|
height: Length::Units(30),
|
||||||
|
text_size: None,
|
||||||
|
font: Renderer::Font::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the width of the [`ParamSlider`].
|
||||||
|
pub fn width(mut self, width: Length) -> Self {
|
||||||
|
self.width = width;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the height of the [`ParamSlider`].
|
||||||
|
pub fn height(mut self, height: Length) -> Self {
|
||||||
|
self.height = height;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the text size of the [`ParamSlider`].
|
||||||
|
pub fn text_size(mut self, size: u16) -> Self {
|
||||||
|
self.text_size = Some(size);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the font of the [`ParamSlider`].
|
||||||
|
pub fn font(mut self, font: Renderer::Font) -> Self {
|
||||||
|
self.font = font;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, P: Param, Renderer: text::Renderer> Widget<ParamMessage, Renderer>
|
||||||
|
for ParamSlider<'a, P, Renderer>
|
||||||
|
{
|
||||||
|
fn width(&self) -> Length {
|
||||||
|
self.width
|
||||||
|
}
|
||||||
|
|
||||||
|
fn height(&self) -> Length {
|
||||||
|
self.height
|
||||||
|
}
|
||||||
|
|
||||||
|
fn layout(&self, _renderer: &Renderer, limits: &layout::Limits) -> layout::Node {
|
||||||
|
let limits = limits.width(self.width).height(self.height);
|
||||||
|
let size = limits.resolve(Size::ZERO);
|
||||||
|
|
||||||
|
layout::Node::new(size)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_event(
|
||||||
|
&mut self,
|
||||||
|
_event: Event,
|
||||||
|
_layout: Layout<'_>,
|
||||||
|
_cursor_position: Point,
|
||||||
|
_renderer: &Renderer,
|
||||||
|
_clipboard: &mut dyn Clipboard,
|
||||||
|
_shell: &mut Shell<'_, ParamMessage>,
|
||||||
|
) -> event::Status {
|
||||||
|
// TODO: Handle interaction
|
||||||
|
event::Status::Ignored
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mouse_interaction(
|
||||||
|
&self,
|
||||||
|
layout: Layout<'_>,
|
||||||
|
cursor_position: Point,
|
||||||
|
_viewport: &Rectangle,
|
||||||
|
_renderer: &Renderer,
|
||||||
|
) -> mouse::Interaction {
|
||||||
|
let bounds = layout.bounds();
|
||||||
|
let is_mouse_over = bounds.contains(cursor_position);
|
||||||
|
|
||||||
|
if is_mouse_over {
|
||||||
|
mouse::Interaction::Pointer
|
||||||
|
} else {
|
||||||
|
mouse::Interaction::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(
|
||||||
|
&self,
|
||||||
|
renderer: &mut Renderer,
|
||||||
|
_style: &renderer::Style,
|
||||||
|
layout: Layout<'_>,
|
||||||
|
cursor_position: Point,
|
||||||
|
_viewport: &Rectangle,
|
||||||
|
) {
|
||||||
|
let bounds = layout.bounds();
|
||||||
|
let is_mouse_over = bounds.contains(cursor_position);
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
let background_color = if is_mouse_over {
|
||||||
|
Color::new(0.5, 0.5, 0.5, 0.2)
|
||||||
|
} else {
|
||||||
|
Color::TRANSPARENT
|
||||||
|
};
|
||||||
|
|
||||||
|
renderer.fill_quad(
|
||||||
|
renderer::Quad {
|
||||||
|
bounds,
|
||||||
|
border_color: Color::BLACK,
|
||||||
|
border_width: 1.0,
|
||||||
|
border_radius: 0.0,
|
||||||
|
},
|
||||||
|
background_color,
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
|
||||||
|
// renderer.fill_text(Text {
|
||||||
|
// content: &Renderer::ARROW_DOWN_ICON.to_string(),
|
||||||
|
// font: Renderer::ICON_FONT,
|
||||||
|
// size: bounds.height * style.icon_size,
|
||||||
|
// bounds: Rectangle {
|
||||||
|
// x: bounds.x + bounds.width - f32::from(self.padding.horizontal()),
|
||||||
|
// y: bounds.center_y(),
|
||||||
|
// ..bounds
|
||||||
|
// },
|
||||||
|
// color: style.text_color,
|
||||||
|
// horizontal_alignment: alignment::Horizontal::Right,
|
||||||
|
// vertical_alignment: alignment::Vertical::Center,
|
||||||
|
// });
|
||||||
|
|
||||||
|
// if let Some(label) = self
|
||||||
|
// .selected
|
||||||
|
// .as_ref()
|
||||||
|
// .map(ToString::to_string)
|
||||||
|
// .as_ref()
|
||||||
|
// .or_else(|| self.placeholder.as_ref())
|
||||||
|
// {
|
||||||
|
// renderer.fill_text(Text {
|
||||||
|
// content: label,
|
||||||
|
// size: f32::from(self.text_size.unwrap_or(renderer.default_size())),
|
||||||
|
// font: self.font.clone(),
|
||||||
|
// color: is_selected
|
||||||
|
// .then(|| style.text_color)
|
||||||
|
// .unwrap_or(style.placeholder_color),
|
||||||
|
// bounds: Rectangle {
|
||||||
|
// x: bounds.x + f32::from(self.padding.left),
|
||||||
|
// y: bounds.center_y(),
|
||||||
|
// ..bounds
|
||||||
|
// },
|
||||||
|
// horizontal_alignment: alignment::Horizontal::Left,
|
||||||
|
// vertical_alignment: alignment::Vertical::Center,
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, P: Param> ParamSlider<'a, P, backend::Renderer> {
|
||||||
|
/// Convert this [`ParamSlider`] into an [`Element`] with the correct message. You should have a
|
||||||
|
/// variant on your own message type that wraps around [`ParamMessage`] so you can forward those
|
||||||
|
/// messages to
|
||||||
|
/// [`IcedEditor::handle_param_message()`][crate::IcedEditor::handle_param_message()].
|
||||||
|
pub fn map<Message, F>(self, f: F) -> Element<'a, Message>
|
||||||
|
where
|
||||||
|
Message: 'static,
|
||||||
|
F: Fn(ParamMessage) -> Message + 'static,
|
||||||
|
{
|
||||||
|
Element::from(self).map(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, P: Param> From<ParamSlider<'a, P, backend::Renderer>> for Element<'a, ParamMessage> {
|
||||||
|
fn from(widget: ParamSlider<'a, P, backend::Renderer>) -> Self {
|
||||||
|
Element::new(widget)
|
||||||
|
}
|
||||||
|
}
|
|
@ -152,7 +152,7 @@ impl<E: IcedEditor> Application for IcedEditorWrapperApplication<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn renderer_settings() -> iced_baseview::renderer::settings::Settings {
|
fn renderer_settings() -> iced_baseview::backend::settings::Settings {
|
||||||
E::renderer_settings()
|
E::renderer_settings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use nih_plug::prelude::{Editor, GuiContext};
|
use nih_plug::prelude::{Editor, GuiContext};
|
||||||
use nih_plug_iced::widgets::ParamMessage;
|
use nih_plug_iced::widgets::{ParamMessage, ParamSlider};
|
||||||
use nih_plug_iced::*;
|
use nih_plug_iced::*;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
@ -22,7 +22,6 @@ struct GainEditor {
|
||||||
params: Pin<Arc<GainParams>>,
|
params: Pin<Arc<GainParams>>,
|
||||||
context: Arc<dyn GuiContext>,
|
context: Arc<dyn GuiContext>,
|
||||||
|
|
||||||
gain_dummy_state: widget::button::State,
|
|
||||||
meter_dummy_state: widget::button::State,
|
meter_dummy_state: widget::button::State,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +43,6 @@ impl IcedEditor for GainEditor {
|
||||||
let editor = GainEditor {
|
let editor = GainEditor {
|
||||||
params,
|
params,
|
||||||
context,
|
context,
|
||||||
gain_dummy_state: widget::button::State::new(),
|
|
||||||
meter_dummy_state: widget::button::State::new(),
|
meter_dummy_state: widget::button::State::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -73,22 +71,23 @@ impl IcedEditor for GainEditor {
|
||||||
.push(
|
.push(
|
||||||
Text::new("Gain GUI")
|
Text::new("Gain GUI")
|
||||||
.size(40)
|
.size(40)
|
||||||
.height(45.into())
|
.height(50.into())
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.horizontal_alignment(alignment::Horizontal::Center)
|
.horizontal_alignment(alignment::Horizontal::Center)
|
||||||
.vertical_alignment(alignment::Vertical::Bottom),
|
.vertical_alignment(alignment::Vertical::Bottom),
|
||||||
)
|
)
|
||||||
.push(
|
.push(
|
||||||
Text::new("Gain")
|
Text::new("Gain")
|
||||||
.height(25.into())
|
.height(20.into())
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.horizontal_alignment(alignment::Horizontal::Center)
|
.horizontal_alignment(alignment::Horizontal::Center)
|
||||||
.vertical_alignment(alignment::Vertical::Center),
|
.vertical_alignment(alignment::Vertical::Center),
|
||||||
)
|
)
|
||||||
.push(
|
.push(
|
||||||
Button::new(&mut self.gain_dummy_state, Text::new("Gain"))
|
ParamSlider::new(&self.params.gain).map(Message::ParamUpdate)
|
||||||
.height(30.into())
|
// Button::new(&mut self.gain_dummy_state, Text::new("Gain"))
|
||||||
.width(180.into()),
|
// .height(30.into())
|
||||||
|
// .width(180.into()),
|
||||||
)
|
)
|
||||||
.push(Space::with_height(10.into()))
|
.push(Space::with_height(10.into()))
|
||||||
.push(
|
.push(
|
||||||
|
|
Loading…
Add table
Reference in a new issue