diff --git a/plugins/spectral_compressor/src/editor.rs b/plugins/spectral_compressor/src/editor.rs
index 4e80bc4e..9d1a16b1 100644
--- a/plugins/spectral_compressor/src/editor.rs
+++ b/plugins/spectral_compressor/src/editor.rs
@@ -23,6 +23,8 @@ use std::sync::Arc;
use crate::{SpectralCompressor, SpectralCompressorParams};
+mod mode_button;
+
/// The entire GUI's width, in logical pixels.
const EXPANDED_GUI_WIDTH: u32 = 1360;
/// The width of the GUI's main part containing the controls.
@@ -44,8 +46,8 @@ pub enum EditorMode {
#[serde(rename = "collapsed")]
Collapsed,
#[default]
- #[serde(rename = "visualizer-shown")]
- Visualizer,
+ #[serde(rename = "visualizer-visible")]
+ VisualizerVisible,
}
#[derive(Lens)]
diff --git a/plugins/spectral_compressor/src/editor/mode_button.rs b/plugins/spectral_compressor/src/editor/mode_button.rs
new file mode 100644
index 00000000..88d46b8b
--- /dev/null
+++ b/plugins/spectral_compressor/src/editor/mode_button.rs
@@ -0,0 +1,86 @@
+// Spectral Compressor: an FFT based compressor
+// Copyright (C) 2021-2023 Robbert van der Helm
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+use std::sync::Arc;
+
+use crossbeam::atomic::AtomicCell;
+use nih_plug_vizia::vizia::prelude::*;
+
+use super::EditorMode;
+
+/// A custom toggleable button that allows changing between the collapsed and expanded editor modes.
+pub struct EditorModeButton {
+ mode: Arc>,
+}
+
+impl EditorModeButton {
+ /// Creates a new button bound to the editor mode setting.
+ pub fn new(cx: &mut Context, lens: L, label: impl Res) -> Handle
+ where
+ L: Lens>>,
+ T: ToString,
+ {
+ Self { mode: lens.get(cx) }
+ .build(cx, move |cx| {
+ Label::new(cx, label);
+ })
+ .checked(lens.map(|v| v.load() == EditorMode::VisualizerVisible))
+ // We'll pretend this is a param-button, so this class is used for assigning a unique
+ // color
+ .class("editor-mode")
+ }
+}
+
+impl View for EditorModeButton {
+ fn element(&self) -> Option<&'static str> {
+ // Reuse the styling from param-button
+ Some("param-button")
+ }
+
+ fn event(&mut self, cx: &mut EventContext, event: &mut Event) {
+ event.map(|window_event, meta| match window_event {
+ WindowEvent::MouseDown(MouseButton::Left)
+ | WindowEvent::MouseDoubleClick(MouseButton::Left)
+ | WindowEvent::MouseTripleClick(MouseButton::Left) => {
+ // TODO: Somehow change the way window sizes work in NIH-plug to be callback based.
+ // Now this can technically go out of sync if the GUI is closed between the
+ // mode changing and the resize actually getting processed
+ let current_mode = self.mode.load();
+ let new_mode = match current_mode {
+ EditorMode::Collapsed => EditorMode::VisualizerVisible,
+ EditorMode::VisualizerVisible => EditorMode::Collapsed,
+ };
+
+ match new_mode {
+ EditorMode::Collapsed => cx.set_window_size(WindowSize {
+ width: super::COLLAPSED_GUI_WIDTH,
+ height: super::GUI_HEIGHT,
+ }),
+ EditorMode::VisualizerVisible => cx.set_window_size(WindowSize {
+ width: super::EXPANDED_GUI_WIDTH,
+ height: super::GUI_HEIGHT,
+ }),
+ }
+
+ self.mode.store(new_mode);
+ meta.consume();
+ }
+ // Mouse scrolling is intentionally not implemented here since it could be very easy to
+ // do that by accident and that would cause the window to jump all over the place
+ _ => {}
+ });
+ }
+}