Skip to content

Commit

Permalink
Add ergonomic resizing w/ GuiContextEvent::Resize
Browse files Browse the repository at this point in the history
  • Loading branch information
robbert-vdh committed Mar 18, 2023
1 parent 66b3387 commit ce2eab8
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 2 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Expand Up @@ -10,6 +10,16 @@ Since there is no stable release yet, the changes are organized per day in
reverse chronological order. The main purpose of this document in its current
state is to list breaking changes.

## [2023-03-18]

### Added

- `nih_plug_vizia`: Added a `GuiContextEvent::Resize` event. The plugin can emit
this to trigger a resize to its current size, as specified by its
`ViziaState`'s size callback. This can be used to declaratively resize a
plugin GUI and it removes some potential surface for making mistakes in the
process. See `GuiContextEvent::Resize`'s documentation for an example.

## [2023-03-17]

### Added
Expand Down
3 changes: 2 additions & 1 deletion nih_plug_vizia/src/lib.rs
Expand Up @@ -29,7 +29,8 @@ pub mod widgets;
///
/// The [`GuiContext`] is also passed to the app function. This is only meant for saving and
/// restoring state as part of your plugin's preset handling. You should not interact with this
/// directly to set parameters. Use the [`ParamEvent`][widgets::ParamEvent]s instead.
/// directly to set parameters. Use the [`ParamEvent`][widgets::ParamEvent]s to change parameter
/// values, and [`GuiContextEvent`] to trigger window resizes.
///
/// The `theming` argument controls what level of theming to apply. If you use
/// [`ViziaTheming::Custom`], then you **need** to call
Expand Down
51 changes: 50 additions & 1 deletion nih_plug_vizia/src/widgets.rs
Expand Up @@ -53,7 +53,8 @@ pub enum ParamEvent<'a, P: Param> {
EndSetParameter(&'a P),
}

/// The same as [`ParamEvent`], but type erased.
/// The same as [`ParamEvent`], but type erased. Use `ParamEvent` as an easier way to construct
/// these if you are working with regular parameter objects.
#[derive(Debug, Clone, Copy)]
pub enum RawParamEvent {
/// Begin an automation gesture for a parameter.
Expand All @@ -68,6 +69,43 @@ pub enum RawParamEvent {
ParametersChanged,
}

/// Events that directly interact with the [`GuiContext`]. Used to trigger resizes.
pub enum GuiContextEvent {
/// Resize the window to match the current size reported by the [`ViziaState`]'s size function.
/// By changing the plugin's state that is used to determine the window's size before emitting
/// this event, the window can be resized in a declarative and predictable way:
///
/// ```
/// # use std::sync::Arc;
/// # use std::sync::atomic::{AtomicBool, Ordering};
/// # use nih_plug_vizia::ViziaState;
/// # use nih_plug_vizia::vizia::prelude::*;
/// # use nih_plug_vizia::widgets::GuiContextEvent;
/// // Assuming there is some kind of state variable passed to the editor, likely stored as a
/// // `#[persist]` field in the `Params` struct:
/// let window_state = Arc::new(AtomicBool::new(false));
///
/// // And this is the `ViziaState` passed to `create_vizia_editor()`:
/// ViziaState::new(move || {
/// if window_state.load(Ordering::Relaxed) {
/// (800, 400)
/// } else {
/// (400, 400)
/// }
/// });
///
/// // Then the window's size can be toggled between the two sizes like so:
/// fn toggle_window_size(cx: &mut EventContext, window_state: Arc<AtomicBool>) {
/// window_state.fetch_xor(true, Ordering::Relaxed);
///
/// // This will cause NIH-plug to query the size from the `ViziaState` again and resize the
/// // windo to that size
/// cx.emit(GuiContextEvent::Resize);
/// }
/// ```
Resize,
}

/// Handles parameter updates for VIZIA GUIs. Registered in
/// [`ViziaEditor::spawn()`][super::ViziaEditor::spawn()].
pub(crate) struct ParamModel {
Expand Down Expand Up @@ -106,6 +144,17 @@ impl Model for ParamModel {

impl Model for WindowModel {
fn event(&mut self, cx: &mut EventContext, event: &mut Event) {
event.map(|gui_context_event, meta| match gui_context_event {
GuiContextEvent::Resize => {
// This will trigger a `WindowEvent::GeometryChanged`, which in turn causes the
// handler below this to be fired
let (width, height) = self.vizia_state.inner_logical_size();
cx.set_window_size(WindowSize { width, height });

meta.consume();
}
});

// This gets fired whenever the inner window gets resized
event.map(|window_event, _| {
if let WindowEvent::GeometryChanged { .. } = window_event {
Expand Down

0 comments on commit ce2eab8

Please sign in to comment.