summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/main.rs147
1 files changed, 86 insertions, 61 deletions
diff --git a/src/main.rs b/src/main.rs
index 13510b9..336378e 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,19 +4,21 @@ mod environment;
mod error;
#[allow(clippy::all, dead_code)]
mod icon;
+mod options;
mod panes;
mod theme;
mod types;
+mod values;
mod widget;
use std::path::PathBuf;
+use std::sync::Arc;
use config::Config;
use dialogs::{error_dialog, unsaved_changes_dialog, warning_dialog};
use error::Error;
use iced::advanced::widget::Id;
-use iced::widget::pane_grid::{self, Pane, PaneGrid};
-use iced::widget::{Column, container, pick_list, row, text_editor};
+use iced::widget::{Column, container, pane_grid, pick_list, row, text_editor};
use iced::{Alignment, Element, Length, Task, Theme, clipboard, keyboard};
use iced_anim::transition::Easing;
use iced_anim::{Animated, Animation};
@@ -25,13 +27,12 @@ use tokio::runtime;
use types::{Action, DesignerPane, ElementName, Message, Project};
fn main() -> Result<(), Box<dyn std::error::Error>> {
- let mut args = std::env::args();
- let _ = args.next();
-
- let version = args.next().is_some_and(|s| s == "--version" || s == "-V");
+ let version = std::env::args()
+ .nth(1)
+ .is_some_and(|s| s == "--version" || s == "-V");
if version {
- println!("{}", env!("CARGO_PKG_VERSION"));
+ println!("iced-builder {}", environment::formatted_version());
println!("{}", env!("CARGO_PKG_REPOSITORY"));
return Ok(());
@@ -59,10 +60,10 @@ struct App {
is_loading: bool,
project_path: Option<PathBuf>,
project: Project,
- config: Config,
+ config: Arc<Config>,
theme: Animated<Theme>,
pane_state: pane_grid::State<Panes>,
- focus: Option<Pane>,
+ focus: Option<pane_grid::Pane>,
designer_page: DesignerPane,
element_list: &'static [ElementName],
editor_content: text_editor::Content,
@@ -85,24 +86,25 @@ impl App {
},
);
- let config = config_load.unwrap_or_default();
+ let config = Arc::new(config_load.unwrap_or_default());
let theme = config.selected_theme();
- let mut task = Task::none();
-
- if let Some(path) = config.last_project.clone() {
+ let task = if let Some(path) = config.last_project.clone() {
if path.exists() && path.is_file() {
- task = Task::perform(
+ Task::perform(
Project::from_path(path, config.clone()),
Message::FileOpened,
- );
+ )
} else {
- warning_dialog(format!(
+ Task::future(warning_dialog(format!(
"The file {} does not exist, or isn't a file.",
path.to_string_lossy()
- ));
+ )))
+ .discard()
}
- }
+ } else {
+ Task::none()
+ };
(
Self {
@@ -146,32 +148,37 @@ impl App {
match message {
Message::SwitchTheme(event) => {
self.theme.update(event);
+
+ Task::none()
}
- Message::CopyCode => {
- return clipboard::write(self.editor_content.text());
+ Message::CopyCode => clipboard::write(self.editor_content.text()),
+ Message::SwitchPage(page) => {
+ self.designer_page = page;
+ Task::none()
}
- Message::SwitchPage(page) => self.designer_page = page,
Message::EditorAction(action) => {
if let text_editor::Action::Scroll { lines: _ } = action {
self.editor_content.perform(action);
}
+ Task::none()
}
Message::RefreshEditorContent => {
match self.project.app_code(&self.config) {
Ok(code) => {
self.editor_content =
text_editor::Content::with_text(&code);
+ Task::none()
}
- Err(error) => error_dialog(error),
+ Err(error) => Task::future(error_dialog(error)).discard(),
}
}
Message::DropNewElement(name, point, _) => {
- return iced_drop::zones_on_point(
+ iced_drop::zones_on_point(
move |zones| Message::HandleNew(name.clone(), zones),
point,
None,
None,
- );
+ )
}
Message::HandleNew(name, zones) => {
let ids: Vec<Id> = zones.into_iter().map(|z| z.0).collect();
@@ -182,25 +189,29 @@ impl App {
self.project.element_tree.as_mut(),
action,
);
+ self.is_dirty = true;
match result {
Ok(Some(ref element)) => {
self.project.element_tree = Some(element.clone());
}
- Err(error) => error_dialog(error),
+ Err(error) => {
+ return Task::future(error_dialog(error))
+ .map(|_| Message::RefreshEditorContent);
+ }
_ => {}
}
-
- self.is_dirty = true;
- return Task::done(Message::RefreshEditorContent);
+ Task::done(Message::RefreshEditorContent)
+ } else {
+ Task::none()
}
}
Message::MoveElement(element, point, _) => {
- return iced_drop::zones_on_point(
+ iced_drop::zones_on_point(
move |zones| Message::HandleMove(element.clone(), zones),
point,
None,
None,
- );
+ )
}
Message::HandleMove(element, zones) => {
let ids: Vec<Id> = zones.into_iter().map(|z| z.0).collect();
@@ -209,33 +220,38 @@ impl App {
let action = Action::new(
&ids,
eltree_clone.as_ref(),
- Some(element.get_id()),
+ Some(element.id()),
);
let result = element.handle_action(
self.project.element_tree.as_mut(),
action,
);
if let Err(error) = result {
- error_dialog(error);
+ return Task::future(error_dialog(error)).discard();
}
self.is_dirty = true;
- return Task::done(Message::RefreshEditorContent);
+ Task::done(Message::RefreshEditorContent)
+ } else {
+ Task::none()
}
}
Message::PaneResized(pane_grid::ResizeEvent { split, ratio }) => {
self.pane_state.resize(split, ratio);
+ Task::none()
}
Message::PaneClicked(pane) => {
self.focus = Some(pane);
+ Task::none()
}
Message::PaneDragged(pane_grid::DragEvent::Dropped {
pane,
target,
}) => {
self.pane_state.drop(pane, target);
+ Task::none()
}
- Message::PaneDragged(_) => {}
+ Message::PaneDragged(_) => Task::none(),
Message::NewFile => {
if !self.is_loading {
if !self.is_dirty {
@@ -251,26 +267,32 @@ impl App {
self.editor_content = text_editor::Content::new();
}
}
+
+ Task::none()
}
Message::OpenFile => {
if !self.is_loading {
if !self.is_dirty {
self.is_loading = true;
- return Task::perform(
+ Task::perform(
Project::from_file(self.config.clone()),
Message::FileOpened,
- );
+ )
} else if unsaved_changes_dialog(
"You have unsaved changes. Do you wish to discard these and open another project?",
) {
self.is_dirty = false;
self.is_loading = true;
- return Task::perform(
+ Task::perform(
Project::from_file(self.config.clone()),
Message::FileOpened,
- );
+ )
+ } else {
+ Task::none()
}
+ } else {
+ Task::none()
}
}
Message::FileOpened(result) => {
@@ -281,31 +303,35 @@ impl App {
Ok((path, project)) => {
self.project = project;
self.project_path = Some(path);
- return Task::done(Message::RefreshEditorContent);
+ Task::done(Message::RefreshEditorContent)
}
- Err(error) => error_dialog(error),
+ Err(error) => Task::future(error_dialog(error)).discard(),
}
}
Message::SaveFile => {
if !self.is_loading {
self.is_loading = true;
- return Task::perform(
+ Task::perform(
self.project
.clone()
.write_to_file(self.project_path.clone()),
Message::FileSaved,
- );
+ )
+ } else {
+ Task::none()
}
}
Message::SaveFileAs => {
if !self.is_loading {
self.is_loading = true;
- return Task::perform(
+ Task::perform(
self.project.clone().write_to_file(None),
Message::FileSaved,
- );
+ )
+ } else {
+ Task::none()
}
}
Message::FileSaved(result) => {
@@ -315,13 +341,12 @@ impl App {
Ok(path) => {
self.project_path = Some(path);
self.is_dirty = false;
+ Task::none()
}
- Err(error) => error_dialog(error),
+ Err(error) => Task::future(error_dialog(error)).discard(),
}
}
}
-
- Task::none()
}
fn subscription(&self) -> iced::Subscription<Message> {
@@ -354,8 +379,9 @@ impl App {
|theme| Message::SwitchTheme(theme.into())
)]
.width(200);
- let pane_grid =
- PaneGrid::new(&self.pane_state, |id, pane, _is_maximized| {
+ let pane_grid = pane_grid::PaneGrid::new(
+ &self.pane_state,
+ |id, pane, _is_maximized| {
let is_focused = Some(id) == self.focus;
match pane {
Panes::Designer => match &self.designer_page {
@@ -364,23 +390,22 @@ impl App {
self.project.get_theme(&self.config),
is_focused,
),
- DesignerPane::CodeView => code_view::view(
- &self.editor_content,
- self.theme.value().clone(),
- is_focused,
- ),
+ DesignerPane::CodeView => {
+ code_view::view(&self.editor_content, is_focused)
+ }
},
Panes::ElementList => {
element_list::view(self.element_list, is_focused)
}
}
- })
- .width(Length::Fill)
- .height(Length::Fill)
- .spacing(10)
- .on_resize(10, Message::PaneResized)
- .on_click(Message::PaneClicked)
- .on_drag(Message::PaneDragged);
+ },
+ )
+ .width(Length::Fill)
+ .height(Length::Fill)
+ .spacing(10)
+ .on_resize(10, Message::PaneResized)
+ .on_click(Message::PaneClicked)
+ .on_drag(Message::PaneDragged);
let content = Column::new()
.push(header)