summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpml68 <contact@pml68.me>2024-10-28 01:00:07 +0100
committerpml68 <contact@pml68.me>2024-10-28 01:00:12 +0100
commit726e9023c4629d70410174ddbd1e6d43f7583fe5 (patch)
tree569c3d25033f06ca708279565eafba76b0ca52ec
parentMerge pull request #3 from pml68/refactor/internal-restructuring (diff)
downloadiced-builder-726e9023c4629d70410174ddbd1e6d43f7583fe5.tar.gz
feat: implement very basic playground
fix: `is_dirty` was never checked for in the main update fn, allowing unsaved work to easily be overwritten
Diffstat (limited to '')
-rw-r--r--iced_builder/src/lib.rs14
-rw-r--r--iced_builder/src/main.rs14
-rw-r--r--iced_builder/src/types/element_name.rs1
-rw-r--r--iced_builder/src/types/mod.rs4
-rwxr-xr-xiced_builder/src/types/rendered_element.rs67
-rw-r--r--iced_builder/src/views/designer_view.rs8
-rw-r--r--iced_builder/src/views/element_list.rs2
7 files changed, 89 insertions, 21 deletions
diff --git a/iced_builder/src/lib.rs b/iced_builder/src/lib.rs
index 14a044e..c6f3616 100644
--- a/iced_builder/src/lib.rs
+++ b/iced_builder/src/lib.rs
@@ -1,7 +1,7 @@
pub mod types;
pub mod views;
-use std::path::PathBuf;
+use std::{io, path::PathBuf};
use iced::widget::{pane_grid, text_editor};
use types::{
@@ -12,7 +12,7 @@ use thiserror::Error;
#[derive(Debug, Clone, Error)]
pub enum Error {
- #[error("an IO error accured: {0}")]
+ #[error("an I/O error accured: {0}")]
IOError(String),
#[error("a Serde error accured: {0}")]
SerdeError(String),
@@ -23,11 +23,11 @@ pub enum Error {
#[error("the file dialog has been closed without selecting a valid option")]
DialogClosed,
#[error("{0}")]
- String(String),
+ Other(String),
}
-impl From<std::io::Error> for Error {
- fn from(value: std::io::Error) -> Self {
+impl From<io::Error> for Error {
+ fn from(value: io::Error) -> Self {
Self::IOError(value.to_string())
}
}
@@ -46,13 +46,13 @@ impl From<rust_format::Error> for Error {
impl From<&'static str> for Error {
fn from(value: &'static str) -> Self {
- Self::String(value.to_owned())
+ Self::Other(value.to_owned())
}
}
#[derive(Debug, Clone)]
pub enum Message {
- ToggleTheme,
+ ToggleDarkMode,
CopyCode,
SwitchPage(DesignerPage),
EditorAction(text_editor::Action),
diff --git a/iced_builder/src/main.rs b/iced_builder/src/main.rs
index ed3f264..d022f29 100644
--- a/iced_builder/src/main.rs
+++ b/iced_builder/src/main.rs
@@ -11,7 +11,7 @@ use iced::{
Alignment, Element, Length, Settings, Task, Theme,
};
use iced_builder::{
- types::{element_name::ElementName, project::Project, rendered_element::Action, DesignerPage},
+ types::{Action, DesignerPage, ElementName, Project},
views::{code_view, designer_view, element_list},
Message,
};
@@ -101,7 +101,7 @@ impl App {
fn update(&mut self, message: Message) -> Task<Message> {
match message {
- Message::ToggleTheme => self.dark_theme = !self.dark_theme,
+ Message::ToggleDarkMode => self.dark_theme = !self.dark_theme,
Message::CopyCode => return clipboard::write(self.editor_content.text()),
Message::SwitchPage(page) => self.designer_page = page,
Message::EditorAction(action) => {
@@ -134,6 +134,8 @@ impl App {
if let Ok(Some(ref element)) = result {
self.project.element_tree = Some(element.clone());
}
+
+ self.is_dirty = true;
}
return Task::done(Message::RefreshEditorContent);
@@ -156,6 +158,8 @@ impl App {
Some(element.get_id()),
);
let _ = element.handle_action(self.project.element_tree.as_mut(), action);
+
+ self.is_dirty = true;
}
return Task::done(Message::RefreshEditorContent);
@@ -178,7 +182,7 @@ impl App {
}
}
Message::OpenFile => {
- if !self.is_loading {
+ if !self.is_loading && !self.is_dirty {
self.is_loading = true;
return Task::perform(Project::from_file(), Message::FileOpened);
@@ -247,8 +251,8 @@ impl App {
}
fn view(&self) -> Element<Message> {
- let header = row![button("Toggle Theme")
- .on_press(Message::ToggleTheme)
+ let header = row![button("Toggle Dark Mode")
+ .on_press(Message::ToggleDarkMode)
.padding(5)]
.width(200);
let pane_grid = PaneGrid::new(&self.pane_state, |id, pane, _is_maximized| {
diff --git a/iced_builder/src/types/element_name.rs b/iced_builder/src/types/element_name.rs
index 93e12a1..bf38120 100644
--- a/iced_builder/src/types/element_name.rs
+++ b/iced_builder/src/types/element_name.rs
@@ -44,6 +44,7 @@ impl ElementName {
};
match action {
Action::Stop => Ok(None),
+ Action::Drop => Ok(None),
Action::AddNew => Ok(Some(element)),
Action::PushFront(id) => {
element_tree
diff --git a/iced_builder/src/types/mod.rs b/iced_builder/src/types/mod.rs
index a48a2d8..0012905 100644
--- a/iced_builder/src/types/mod.rs
+++ b/iced_builder/src/types/mod.rs
@@ -2,6 +2,10 @@ pub mod element_name;
pub mod project;
pub mod rendered_element;
+pub use element_name::ElementName;
+pub use project::Project;
+pub use rendered_element::*;
+
#[derive(Debug, Clone)]
pub enum DesignerPage {
Designer,
diff --git a/iced_builder/src/types/rendered_element.rs b/iced_builder/src/types/rendered_element.rs
index 08d7ba3..3dad8e7 100755
--- a/iced_builder/src/types/rendered_element.rs
+++ b/iced_builder/src/types/rendered_element.rs
@@ -7,14 +7,14 @@ use unique_id::{string::StringGenerator, Generator};
use crate::{Error, Message};
-use super::element_name::ElementName;
+use super::ElementName;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RenderedElement {
id: String,
- pub child_elements: Option<Vec<RenderedElement>>,
- pub name: ElementName,
- pub options: IndexMap<String, Option<String>>,
+ child_elements: Option<Vec<RenderedElement>>,
+ name: ElementName,
+ options: IndexMap<String, Option<String>>,
}
impl RenderedElement {
@@ -126,6 +126,12 @@ impl RenderedElement {
match action {
Action::Stop => Ok(()),
+ Action::Drop => {
+ let parent = element_tree.find_parent(self).unwrap();
+ parent.remove(self);
+
+ Ok(())
+ }
Action::AddNew => Err(
"the action was of kind `AddNew`, but invoking it on an existing element tree is not possible".into(),
),
@@ -299,11 +305,62 @@ impl std::fmt::Display for RenderedElement {
}
}
+impl<'a> From<RenderedElement> for Element<'a, Message> {
+ fn from(value: RenderedElement) -> Self {
+ let child_elements = match value.child_elements {
+ Some(ref elements) => elements.clone(),
+ None => vec![],
+ };
+
+ let content: Element<'a, Message> = match value.name.clone() {
+ ElementName::Text(s) => {
+ if s == String::new() {
+ widget::text("New Text").into()
+ } else {
+ widget::text(s).into()
+ }
+ }
+ ElementName::Button(s) => {
+ if s == String::new() {
+ widget::button(widget::text("New Button")).into()
+ } else {
+ widget::button(widget::text(s)).into()
+ }
+ }
+ ElementName::SVG(p) => widget::svg(p).into(),
+ ElementName::Image(p) => widget::image(p).into(),
+ ElementName::Container => widget::container(if child_elements.len() == 1 {
+ child_elements[0].clone().into()
+ } else {
+ Element::from("")
+ })
+ .padding(20)
+ .into(),
+ ElementName::Row => {
+ widget::Row::from_iter(child_elements.into_iter().map(|el| el.into()))
+ .padding(20)
+ .into()
+ }
+ ElementName::Column => {
+ widget::Column::from_iter(child_elements.into_iter().map(|el| el.into()))
+ .padding(20)
+ .into()
+ }
+ };
+ iced_drop::droppable(content)
+ .id(value.get_id())
+ .drag_hide(true)
+ .on_drop(move |point, rect| Message::MoveElement(value.clone(), point, rect))
+ .into()
+ }
+}
+
#[derive(Debug, Clone)]
pub enum Action {
AddNew,
PushFront(Id),
InsertAfter(Id, Id),
+ Drop,
Stop,
}
@@ -317,6 +374,8 @@ impl Action {
if ids.len() == 1 {
if element_tree.is_none() {
action = Self::AddNew;
+ } else {
+ action = Self::Drop;
}
} else {
let id: Id = match source_id {
diff --git a/iced_builder/src/views/designer_view.rs b/iced_builder/src/views/designer_view.rs
index 6f31a51..2d88493 100644
--- a/iced_builder/src/views/designer_view.rs
+++ b/iced_builder/src/views/designer_view.rs
@@ -1,11 +1,11 @@
use super::style;
use crate::{
- types::{rendered_element::RenderedElement, DesignerPage},
+ types::{DesignerPage, RenderedElement},
Message,
};
use iced::{
widget::{button, container, pane_grid, row, text, themer, Space},
- Alignment, Length,
+ Alignment, Element, Length,
};
pub fn view<'a>(
@@ -13,8 +13,8 @@ pub fn view<'a>(
designer_theme: iced::Theme,
is_focused: bool,
) -> pane_grid::Content<'a, Message> {
- let el_tree = match element_tree {
- Some(tree) => tree.clone().as_element(),
+ let el_tree: Element<'a, Message> = match element_tree {
+ Some(tree) => tree.clone().into(),
None => text("Open a project or begin creating one").into(),
};
let content = container(themer(designer_theme, el_tree))
diff --git a/iced_builder/src/views/element_list.rs b/iced_builder/src/views/element_list.rs
index f0fdd2f..a9aeb1f 100644
--- a/iced_builder/src/views/element_list.rs
+++ b/iced_builder/src/views/element_list.rs
@@ -1,5 +1,5 @@
use super::style;
-use crate::{types::element_name::ElementName, Message};
+use crate::{types::ElementName, Message};
use iced::{
widget::{column, container, pane_grid, text, Column},
Alignment, Element, Length,