merge integration
This commit is contained in:
commit
d72443905d
|
|
@ -1,8 +1,11 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use iced::{Element, Task};
|
use iced::keyboard::{Key, Modifiers};
|
||||||
|
use iced::{Element, Subscription, Task};
|
||||||
|
|
||||||
|
use crate::behaviors::Action;
|
||||||
|
use crate::gui::native_menu::{NativeMenu, NativeMenuAction};
|
||||||
use crate::gui::time_utility;
|
use crate::gui::time_utility;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
@ -24,6 +27,7 @@ pub enum AppState {
|
||||||
ProjectView(ProjectViewState),
|
ProjectView(ProjectViewState),
|
||||||
NewProject(crate::gui::new_project::State),
|
NewProject(crate::gui::new_project::State),
|
||||||
TimeUtility { tapper_state: time_utility::State, return_state: Box<AppState> },
|
TimeUtility { tapper_state: time_utility::State, return_state: Box<AppState> },
|
||||||
|
Settings { settings_state: crate::gui::settings::State, return_state: Box<AppState> },
|
||||||
Editor(crate::editor::Editor),
|
Editor(crate::editor::Editor),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,12 +63,22 @@ pub enum Message {
|
||||||
TimeUtilityCancel,
|
TimeUtilityCancel,
|
||||||
RunTimeUtilityAnalysis,
|
RunTimeUtilityAnalysis,
|
||||||
|
|
||||||
|
OpenSettings,
|
||||||
|
CloseSettings { save: bool },
|
||||||
|
SettingsMessage(crate::gui::settings::Message),
|
||||||
|
|
||||||
|
KeyPressed(Key, Modifiers),
|
||||||
|
KeyReleased(Key, Modifiers),
|
||||||
|
WindowClosed(iced::window::Id),
|
||||||
|
Tick,
|
||||||
|
|
||||||
EditorMessage(crate::editor::Message),
|
EditorMessage(crate::editor::Message),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct App {
|
pub struct App {
|
||||||
pub state: AppState,
|
pub state: AppState,
|
||||||
pub global_config: crate::config::AudioOxideConfig,
|
pub global_config: crate::config::AudioOxideConfig,
|
||||||
|
native_menu: NativeMenu,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for App {
|
impl Default for App {
|
||||||
|
|
@ -75,12 +89,17 @@ impl Default for App {
|
||||||
} else {
|
} else {
|
||||||
AppState::ProjectView(ProjectViewState::Splash)
|
AppState::ProjectView(ProjectViewState::Splash)
|
||||||
};
|
};
|
||||||
Self { state, global_config: config }
|
Self {
|
||||||
|
state,
|
||||||
|
global_config: config,
|
||||||
|
native_menu: NativeMenu::init(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() -> iced::Result {
|
pub fn main() -> iced::Result {
|
||||||
iced::application("Audio Oxide", App::update, App::view)
|
iced::application("Audio Oxide", App::update, App::view)
|
||||||
|
.subscription(App::subscription)
|
||||||
.run()
|
.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -305,6 +324,80 @@ impl App {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Message::OpenSettings => {
|
||||||
|
if matches!(self.state, AppState::Settings { .. }) {
|
||||||
|
return Task::none();
|
||||||
|
}
|
||||||
|
let return_state = std::mem::replace(
|
||||||
|
&mut self.state,
|
||||||
|
AppState::ProjectView(ProjectViewState::Splash),
|
||||||
|
);
|
||||||
|
let settings_state = crate::gui::settings::State::new(&self.global_config);
|
||||||
|
self.state = AppState::Settings {
|
||||||
|
settings_state,
|
||||||
|
return_state: Box::new(return_state),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Message::CloseSettings { save } => {
|
||||||
|
if save {
|
||||||
|
if let AppState::Settings { ref settings_state, .. } = self.state {
|
||||||
|
self.global_config = settings_state.config.clone();
|
||||||
|
crate::first_run::save_config(&self.global_config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(rs) = self.take_settings_return() {
|
||||||
|
self.state = rs;
|
||||||
|
} else {
|
||||||
|
self.state = AppState::ProjectView(ProjectViewState::Splash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Message::SettingsMessage(settings_msg) => {
|
||||||
|
if let AppState::Settings { ref mut settings_state, .. } = self.state {
|
||||||
|
let is_save = matches!(settings_msg, crate::gui::settings::Message::Save);
|
||||||
|
let is_cancel = matches!(settings_msg, crate::gui::settings::Message::Cancel);
|
||||||
|
let done = crate::gui::settings::handle_message(settings_state, settings_msg);
|
||||||
|
if done {
|
||||||
|
return self.update(Message::CloseSettings { save: is_save && !is_cancel });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::KeyPressed(key, modifiers) => {
|
||||||
|
if let Some(action) = crate::triggers::map_key_press_to_action(&self.state, key, modifiers) {
|
||||||
|
return self.dispatch_action(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Message::KeyReleased(key, modifiers) => {
|
||||||
|
if let Some(action) = crate::triggers::map_key_release_to_action(&self.state, key, modifiers) {
|
||||||
|
return self.dispatch_action(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Message::Tick => {
|
||||||
|
let menu_actions = self.native_menu.poll_events();
|
||||||
|
if let Some(first) = menu_actions.into_iter().next() {
|
||||||
|
match first {
|
||||||
|
NativeMenuAction::Action(action) => {
|
||||||
|
return self.dispatch_action(action);
|
||||||
|
}
|
||||||
|
NativeMenuAction::ShowNewTrackWizard => {
|
||||||
|
return self.update(Message::EditorMessage(crate::editor::Message::ShowNewTrackWizard));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Message::WindowClosed(window_id) => {
|
||||||
|
if let AppState::Editor(ref mut editor) = self.state {
|
||||||
|
if editor.module_for_window(window_id).is_some() {
|
||||||
|
let title = editor.module_window_title(window_id);
|
||||||
|
let _had_view = editor.module_window_view(window_id).is_some();
|
||||||
|
debug_log!("module window closed: {:?} (had_view={})", title, _had_view);
|
||||||
|
drop(title);
|
||||||
|
return editor.close_module_window_by_id(window_id).map(Message::EditorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Message::EditorMessage(editor_msg) => {
|
Message::EditorMessage(editor_msg) => {
|
||||||
if let AppState::Editor(ref mut editor) = self.state {
|
if let AppState::Editor(ref mut editor) = self.state {
|
||||||
return editor.update(editor_msg).map(Message::EditorMessage);
|
return editor.update(editor_msg).map(Message::EditorMessage);
|
||||||
|
|
@ -331,12 +424,82 @@ impl App {
|
||||||
AppState::TimeUtility { tapper_state, .. } => {
|
AppState::TimeUtility { tapper_state, .. } => {
|
||||||
time_utility::view(tapper_state)
|
time_utility::view(tapper_state)
|
||||||
}
|
}
|
||||||
|
AppState::Settings { settings_state, .. } => {
|
||||||
|
crate::gui::settings::view(settings_state)
|
||||||
|
.map(Message::SettingsMessage)
|
||||||
|
}
|
||||||
AppState::Editor(editor) => {
|
AppState::Editor(editor) => {
|
||||||
editor.view().map(Message::EditorMessage)
|
editor.view().map(Message::EditorMessage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn subscription(&self) -> Subscription<Message> {
|
||||||
|
use iced::keyboard;
|
||||||
|
Subscription::batch([
|
||||||
|
keyboard::on_key_press(|key, modifiers| Some(Message::KeyPressed(key, modifiers))),
|
||||||
|
keyboard::on_key_release(|key, modifiers| Some(Message::KeyReleased(key, modifiers))),
|
||||||
|
iced::window::close_events().map(Message::WindowClosed),
|
||||||
|
iced::time::every(std::time::Duration::from_millis(100)).map(|_| Message::Tick),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dispatch_action(&mut self, action: Action) -> Task<Message> {
|
||||||
|
match action {
|
||||||
|
Action::TimeUtilityTapPressed => self.update(Message::TimeUtilityTapPressed),
|
||||||
|
Action::TimeUtilityTapReleased => self.update(Message::TimeUtilityTapReleased),
|
||||||
|
Action::OpenSettings => self.update(Message::OpenSettings),
|
||||||
|
Action::NewProject => self.update(Message::ViewNewProject),
|
||||||
|
Action::EditorTogglePlayback => {
|
||||||
|
self.update(Message::EditorMessage(crate::editor::Message::PlayPressed))
|
||||||
|
}
|
||||||
|
Action::EditorStop => {
|
||||||
|
self.update(Message::EditorMessage(crate::editor::Message::StopPressed))
|
||||||
|
}
|
||||||
|
Action::EditorToggleRecord => {
|
||||||
|
self.update(Message::EditorMessage(crate::editor::Message::RecordPressed))
|
||||||
|
}
|
||||||
|
Action::EditorRewind => {
|
||||||
|
self.update(Message::EditorMessage(crate::editor::Message::RewindPressed))
|
||||||
|
}
|
||||||
|
Action::EditorPlayFromBeginning => {
|
||||||
|
self.update(Message::EditorMessage(crate::editor::Message::RewindPressed))
|
||||||
|
}
|
||||||
|
Action::EditorToggleInspector => {
|
||||||
|
self.update(Message::EditorMessage(crate::editor::Message::ToggleInspector))
|
||||||
|
}
|
||||||
|
Action::EditorToggleBottomPanel => {
|
||||||
|
self.update(Message::EditorMessage(crate::editor::Message::ToggleBottomPanel))
|
||||||
|
}
|
||||||
|
Action::EditorToggleMixer => {
|
||||||
|
self.update(Message::EditorMessage(crate::editor::Message::SetBottomPanelMode(
|
||||||
|
crate::editor::BottomPanelMode::Mixer,
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
Action::EditorToggleCycle => {
|
||||||
|
self.update(Message::EditorMessage(crate::editor::Message::CycleToggled))
|
||||||
|
}
|
||||||
|
Action::EditorToggleMetronome => {
|
||||||
|
self.update(Message::EditorMessage(crate::editor::Message::MetronomeToggled))
|
||||||
|
}
|
||||||
|
Action::ZoomInH => {
|
||||||
|
self.update(Message::EditorMessage(crate::editor::Message::ZoomH(1.25)))
|
||||||
|
}
|
||||||
|
Action::ZoomOutH => {
|
||||||
|
self.update(Message::EditorMessage(crate::editor::Message::ZoomH(0.8)))
|
||||||
|
}
|
||||||
|
Action::ZoomInV => {
|
||||||
|
self.update(Message::EditorMessage(crate::editor::Message::ZoomV(1.25)))
|
||||||
|
}
|
||||||
|
Action::ZoomOutV => {
|
||||||
|
self.update(Message::EditorMessage(crate::editor::Message::ZoomV(0.8)))
|
||||||
|
}
|
||||||
|
action => {
|
||||||
|
self.update(Message::EditorMessage(crate::editor::Message::EditAction(action)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn take_time_utility_return(&mut self) -> Option<AppState> {
|
fn take_time_utility_return(&mut self) -> Option<AppState> {
|
||||||
let placeholder = AppState::ProjectView(ProjectViewState::Splash);
|
let placeholder = AppState::ProjectView(ProjectViewState::Splash);
|
||||||
let old = std::mem::replace(&mut self.state, placeholder);
|
let old = std::mem::replace(&mut self.state, placeholder);
|
||||||
|
|
@ -347,4 +510,15 @@ impl App {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn take_settings_return(&mut self) -> Option<AppState> {
|
||||||
|
let placeholder = AppState::ProjectView(ProjectViewState::Splash);
|
||||||
|
let old = std::mem::replace(&mut self.state, placeholder);
|
||||||
|
if let AppState::Settings { return_state, .. } = old {
|
||||||
|
Some(*return_state)
|
||||||
|
} else {
|
||||||
|
self.state = old;
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue