summaryrefslogtreecommitdiff
path: root/iced_builder/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'iced_builder/src/main.rs')
-rw-r--r--iced_builder/src/main.rs382
1 files changed, 0 insertions, 382 deletions
diff --git a/iced_builder/src/main.rs b/iced_builder/src/main.rs
deleted file mode 100644
index 5b95b94..0000000
--- a/iced_builder/src/main.rs
+++ /dev/null
@@ -1,382 +0,0 @@
-#![feature(test)]
-mod config;
-mod dialogs;
-mod environment;
-mod error;
-mod icon;
-mod panes;
-mod theme;
-mod types;
-mod widget;
-
-use std::path::PathBuf;
-
-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::{container, pick_list, row, text_editor, Column};
-use iced::{clipboard, keyboard, Alignment, Element, Length, Task, Theme};
-use iced_anim::transition::Easing;
-use iced_anim::{Animated, Animation};
-use panes::{code_view, designer_view, element_list};
-use tokio::runtime;
-use types::{Action, DesignerPage, ElementName, Message, Project};
-
-//pub(crate) type Result<T> = core::result::Result<T, Error>;
-
-fn main() -> Result<(), Box<dyn std::error::Error>> {
- let config_load = {
- let rt = runtime::Builder::new_current_thread()
- .enable_all()
- .build()?;
-
- rt.block_on(Config::load())
- };
-
- iced::application(App::title, App::update, App::view)
- .font(icon::FONT)
- .theme(|state| state.theme.value().clone())
- .subscription(App::subscription)
- .run_with(move || App::new(config_load))?;
-
- Ok(())
-}
-
-struct App {
- is_dirty: bool,
- is_loading: bool,
- project_path: Option<PathBuf>,
- project: Project,
- config: Config,
- theme: Animated<Theme>,
- pane_state: pane_grid::State<Panes>,
- focus: Option<Pane>,
- designer_page: DesignerPage,
- element_list: &'static [ElementName],
- editor_content: text_editor::Content,
-}
-
-#[derive(Clone, Copy, Debug)]
-enum Panes {
- Designer,
- ElementList,
-}
-
-impl App {
- fn new(config_load: Result<Config, Error>) -> (Self, Task<Message>) {
- let state = pane_grid::State::with_configuration(
- pane_grid::Configuration::Split {
- axis: pane_grid::Axis::Vertical,
- ratio: 0.8,
- a: Box::new(pane_grid::Configuration::Pane(Panes::Designer)),
- b: Box::new(pane_grid::Configuration::Pane(Panes::ElementList)),
- },
- );
-
- let config = config_load.unwrap_or_default();
- let theme = config.selected_theme();
-
- let mut task = Task::none();
-
- if let Some(path) = config.last_project.clone() {
- if path.exists() && path.is_file() {
- task = Task::perform(
- Project::from_path(path, config.clone()),
- Message::FileOpened,
- );
- } else {
- warning_dialog(format!(
- "The file {} does not exist, or isn't a file.",
- path.to_string_lossy()
- ));
- }
- }
-
- (
- Self {
- is_dirty: false,
- is_loading: false,
- project_path: None,
- project: Project::new(),
- config,
- theme: Animated::new(theme, Easing::EASE_IN),
- pane_state: state,
- focus: None,
- designer_page: DesignerPage::DesignerView,
- element_list: ElementName::ALL,
- editor_content: text_editor::Content::new(),
- },
- task,
- )
- }
-
- fn title(&self) -> String {
- let saved_state = if self.is_dirty { " *" } else { "" };
-
- let project_name = match &self.project.title {
- Some(n) => {
- format!(
- " - {}",
- if n.len() > 60 {
- format!("...{}", &n[n.len() - 40..])
- } else {
- n.to_owned()
- }
- )
- }
- None => String::new(),
- };
-
- format!("iced Builder{project_name}{saved_state}")
- }
-
- fn update(&mut self, message: Message) -> Task<Message> {
- match message {
- Message::ToggleTheme(event) => {
- self.theme.update(event);
- }
- Message::CopyCode => {
- return clipboard::write(self.editor_content.text())
- }
- Message::SwitchPage(page) => self.designer_page = page,
- Message::EditorAction(action) => {
- if let text_editor::Action::Scroll { lines: _ } = action {
- self.editor_content.perform(action);
- }
- }
- Message::RefreshEditorContent => {
- match self.project.app_code(&self.config) {
- Ok(code) => {
- self.editor_content =
- text_editor::Content::with_text(&code);
- }
- Err(error) => error_dialog(error.to_string()),
- }
- }
- Message::DropNewElement(name, point, _) => {
- return 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();
- if !ids.is_empty() {
- let eltree_clone = self.project.element_tree.clone();
- let action = Action::new(&ids, &eltree_clone, None);
- let result = name.handle_action(
- self.project.element_tree.as_mut(),
- action,
- );
- match result {
- Ok(Some(ref element)) => {
- self.project.element_tree = Some(element.clone());
- }
- Err(error) => error_dialog(error.to_string()),
- _ => {}
- }
-
- self.is_dirty = true;
- return Task::done(Message::RefreshEditorContent);
- }
- }
- Message::MoveElement(element, point, _) => {
- return 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();
- if !ids.is_empty() {
- let eltree_clone = self.project.element_tree.clone();
- let action = Action::new(
- &ids,
- &eltree_clone,
- Some(element.get_id()),
- );
- let result = element.handle_action(
- self.project.element_tree.as_mut(),
- action,
- );
- if let Err(error) = result {
- error_dialog(error.to_string());
- }
-
- self.is_dirty = true;
- return Task::done(Message::RefreshEditorContent);
- }
- }
- Message::PaneResized(pane_grid::ResizeEvent { split, ratio }) => {
- self.pane_state.resize(split, ratio);
- }
- Message::PaneClicked(pane) => {
- self.focus = Some(pane);
- }
- Message::PaneDragged(pane_grid::DragEvent::Dropped {
- pane,
- target,
- }) => {
- self.pane_state.drop(pane, target);
- }
- Message::PaneDragged(_) => {}
- Message::NewFile => {
- if !self.is_loading {
- if !self.is_dirty {
- self.project = Project::new();
- self.project_path = None;
- self.editor_content = text_editor::Content::new();
- } else if unsaved_changes_dialog("You have unsaved changes. Do you wish to discard these and create a new project?") {
- self.is_dirty = false;
- self.project = Project::new();
- self.project_path = None;
- self.editor_content = text_editor::Content::new();
- }
- }
- }
- Message::OpenFile => {
- if !self.is_loading {
- if !self.is_dirty {
- self.is_loading = true;
-
- return 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(Project::from_file(self.config.clone()), Message::FileOpened);
- }
- }
- }
- Message::FileOpened(result) => {
- self.is_loading = false;
- self.is_dirty = false;
-
- match result {
- Ok((path, project)) => {
- self.project = project;
- self.project_path = Some(path);
- self.editor_content = text_editor::Content::with_text(
- &self
- .project
- .app_code(&self.config)
- .unwrap_or_else(|err| err.to_string()),
- );
- }
- Err(error) => error_dialog(error.to_string()),
- }
- }
- Message::SaveFile => {
- if !self.is_loading {
- self.is_loading = true;
-
- return Task::perform(
- self.project
- .clone()
- .write_to_file(self.project_path.clone()),
- Message::FileSaved,
- );
- }
- }
- Message::SaveFileAs => {
- if !self.is_loading {
- self.is_loading = true;
-
- return Task::perform(
- self.project.clone().write_to_file(None),
- Message::FileSaved,
- );
- }
- }
- Message::FileSaved(result) => {
- self.is_loading = false;
-
- match result {
- Ok(path) => {
- self.project_path = Some(path);
- self.is_dirty = false;
- }
- Err(error) => error_dialog(error.to_string()),
- }
- }
- }
-
- Task::none()
- }
-
- fn subscription(&self) -> iced::Subscription<Message> {
- keyboard::on_key_press(|key, modifiers| {
- if modifiers.command() {
- match key.as_ref() {
- keyboard::Key::Character("o") => Some(Message::OpenFile),
- keyboard::Key::Character("s") => {
- Some(if modifiers.shift() {
- Message::SaveFileAs
- } else {
- Message::SaveFile
- })
- }
- keyboard::Key::Character("n") => Some(Message::NewFile),
- _ => None,
- }
- } else {
- None
- }
- })
- }
-
- fn view(&self) -> Element<'_, Message> {
- let header = row![pick_list(
- self.config.theme.all.clone(),
- Some(self.theme.target().clone()),
- |theme| { Message::ToggleTheme(theme.into()) }
- )]
- .width(200);
- let 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 {
- DesignerPage::DesignerView => designer_view::view(
- &self.project.element_tree,
- self.project.get_theme(&self.config),
- is_focused,
- ),
- DesignerPage::CodeView => code_view::view(
- &self.editor_content,
- self.theme.target().clone(),
- 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);
-
- let content = Column::new()
- .push(header)
- .push(pane_grid)
- .spacing(5)
- .align_x(Alignment::Center)
- .width(Length::Fill);
-
- Animation::new(&self.theme, container(content).height(Length::Fill))
- .on_update(Message::ToggleTheme)
- .into()
- }
-}