Add a placeholder for a parameter slider widget
This commit is contained in:
parent
5711f77cc7
commit
291abb8bcf
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1396,7 +1396,7 @@ checksum = "dfa686283ad6dd069f105e5ab091b04c62850d3e4cf5d67debad1933f55023df"
|
|||
[[package]]
|
||||
name = "iced_baseview"
|
||||
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 = [
|
||||
"baseview",
|
||||
"copypasta",
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//!
|
||||
//! 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::channel;
|
||||
use nih_plug::prelude::{Editor, GuiContext, ParentWindowHandle};
|
||||
|
@ -106,12 +106,12 @@ pub trait IcedEditor: 'static + Send + Sync + Sized {
|
|||
}
|
||||
|
||||
/// See [`Application::renderer_settings`].
|
||||
fn renderer_settings() -> iced_baseview::renderer::settings::Settings {
|
||||
iced_baseview::renderer::settings::Settings {
|
||||
fn renderer_settings() -> iced_baseview::backend::settings::Settings {
|
||||
iced_baseview::backend::settings::Settings {
|
||||
// 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.
|
||||
antialiasing: Some(iced_baseview::renderer::settings::Antialiasing::MSAAx4),
|
||||
..iced_baseview::renderer::settings::Settings::default()
|
||||
antialiasing: Some(iced_baseview::backend::settings::Antialiasing::MSAAx4),
|
||||
..iced_baseview::backend::settings::Settings::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,7 @@ impl<E: IcedEditor> Editor for IcedEditorWrapper<E> {
|
|||
window: WindowOpenOptions {
|
||||
title: String::from("iced window"),
|
||||
// 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
|
||||
// not the mouse events.
|
||||
scale: scaling_factor
|
||||
|
|
|
@ -1,7 +1,16 @@
|
|||
//! 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;
|
||||
|
||||
mod param_slider;
|
||||
|
||||
pub use param_slider::ParamSlider;
|
||||
|
||||
/// 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
|
||||
/// [`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]
|
||||
fn renderer_settings() -> iced_baseview::renderer::settings::Settings {
|
||||
fn renderer_settings() -> iced_baseview::backend::settings::Settings {
|
||||
E::renderer_settings()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use nih_plug::prelude::{Editor, GuiContext};
|
||||
use nih_plug_iced::widgets::ParamMessage;
|
||||
use nih_plug_iced::widgets::{ParamMessage, ParamSlider};
|
||||
use nih_plug_iced::*;
|
||||
use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
|
@ -22,7 +22,6 @@ struct GainEditor {
|
|||
params: Pin<Arc<GainParams>>,
|
||||
context: Arc<dyn GuiContext>,
|
||||
|
||||
gain_dummy_state: widget::button::State,
|
||||
meter_dummy_state: widget::button::State,
|
||||
}
|
||||
|
||||
|
@ -44,7 +43,6 @@ impl IcedEditor for GainEditor {
|
|||
let editor = GainEditor {
|
||||
params,
|
||||
context,
|
||||
gain_dummy_state: widget::button::State::new(),
|
||||
meter_dummy_state: widget::button::State::new(),
|
||||
};
|
||||
|
||||
|
@ -73,22 +71,23 @@ impl IcedEditor for GainEditor {
|
|||
.push(
|
||||
Text::new("Gain GUI")
|
||||
.size(40)
|
||||
.height(45.into())
|
||||
.height(50.into())
|
||||
.width(Length::Fill)
|
||||
.horizontal_alignment(alignment::Horizontal::Center)
|
||||
.vertical_alignment(alignment::Vertical::Bottom),
|
||||
)
|
||||
.push(
|
||||
Text::new("Gain")
|
||||
.height(25.into())
|
||||
.height(20.into())
|
||||
.width(Length::Fill)
|
||||
.horizontal_alignment(alignment::Horizontal::Center)
|
||||
.vertical_alignment(alignment::Vertical::Center),
|
||||
)
|
||||
.push(
|
||||
Button::new(&mut self.gain_dummy_state, Text::new("Gain"))
|
||||
.height(30.into())
|
||||
.width(180.into()),
|
||||
ParamSlider::new(&self.params.gain).map(Message::ParamUpdate)
|
||||
// Button::new(&mut self.gain_dummy_state, Text::new("Gain"))
|
||||
// .height(30.into())
|
||||
// .width(180.into()),
|
||||
)
|
||||
.push(Space::with_height(10.into()))
|
||||
.push(
|
||||
|
|
Loading…
Reference in a new issue