feat: update editor UI to use CompositeIcon
This commit is contained in:
+62
-34
@@ -1,19 +1,18 @@
|
|||||||
use crate::color_scheme::ColorScheme;
|
use crate::composite_icon::CompositeIcon;
|
||||||
use anyhow::Result;
|
|
||||||
use gtk::glib;
|
use gtk::glib;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{
|
use gtk::{
|
||||||
Box as GtkBox, ColorDialog, ColorDialogButton, InfoBar, Label, MessageType, Orientation,
|
Box as GtkBox, ColorDialog, ColorDialogButton, Label, Orientation, Picture, ScrolledWindow,
|
||||||
Picture, ScrolledWindow,
|
|
||||||
};
|
};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::path::Path;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub fn build_editor_page(icon_path: &Path, on_back: impl Fn() + 'static) -> Result<gtk::Widget> {
|
pub fn build_editor_page(
|
||||||
let scheme = ColorScheme::load(icon_path)?;
|
composite: Rc<RefCell<CompositeIcon>>,
|
||||||
let scheme = Rc::new(RefCell::new(scheme));
|
on_back: impl Fn() + 'static,
|
||||||
|
on_add_emblem: impl Fn() + 'static,
|
||||||
|
on_save_as: impl Fn() + 'static,
|
||||||
|
) -> gtk::Widget {
|
||||||
let root = GtkBox::new(Orientation::Vertical, 8);
|
let root = GtkBox::new(Orientation::Vertical, 8);
|
||||||
root.set_margin_top(8);
|
root.set_margin_top(8);
|
||||||
root.set_margin_bottom(8);
|
root.set_margin_bottom(8);
|
||||||
@@ -25,29 +24,36 @@ pub fn build_editor_page(icon_path: &Path, on_back: impl Fn() + 'static) -> Resu
|
|||||||
back_button.connect_clicked(move |_| on_back());
|
back_button.connect_clicked(move |_| on_back());
|
||||||
toolbar.append(&back_button);
|
toolbar.append(&back_button);
|
||||||
|
|
||||||
|
let add_emblem_button = gtk::Button::with_label("Add Emblem");
|
||||||
|
add_emblem_button.connect_clicked(move |_| on_add_emblem());
|
||||||
|
toolbar.append(&add_emblem_button);
|
||||||
|
|
||||||
|
let save_as_button = gtk::Button::with_label("Save As...");
|
||||||
|
save_as_button.connect_clicked(move |_| on_save_as());
|
||||||
|
toolbar.append(&save_as_button);
|
||||||
|
|
||||||
let undo_button = gtk::Button::with_label("Undo");
|
let undo_button = gtk::Button::with_label("Undo");
|
||||||
let redo_button = gtk::Button::with_label("Redo");
|
let redo_button = gtk::Button::with_label("Redo");
|
||||||
toolbar.append(&undo_button);
|
toolbar.append(&undo_button);
|
||||||
toolbar.append(&redo_button);
|
toolbar.append(&redo_button);
|
||||||
root.append(&toolbar);
|
root.append(&toolbar);
|
||||||
|
|
||||||
if scheme.borrow().colors.is_empty() {
|
|
||||||
let info = InfoBar::new();
|
|
||||||
info.set_message_type(MessageType::Warning);
|
|
||||||
info.add_child(&Label::new(Some(
|
|
||||||
"No ColorScheme tags were found in this SVG.",
|
|
||||||
)));
|
|
||||||
root.append(&info);
|
|
||||||
}
|
|
||||||
|
|
||||||
let content = GtkBox::new(Orientation::Horizontal, 8);
|
let content = GtkBox::new(Orientation::Horizontal, 8);
|
||||||
content.set_vexpand(true);
|
content.set_vexpand(true);
|
||||||
|
|
||||||
|
let side_panel = GtkBox::new(Orientation::Vertical, 8);
|
||||||
let swatches_scroller = ScrolledWindow::new();
|
let swatches_scroller = ScrolledWindow::new();
|
||||||
swatches_scroller.set_min_content_width(300);
|
swatches_scroller.set_min_content_width(300);
|
||||||
|
swatches_scroller.set_vexpand(true);
|
||||||
let swatches_box = GtkBox::new(Orientation::Vertical, 4);
|
let swatches_box = GtkBox::new(Orientation::Vertical, 4);
|
||||||
swatches_scroller.set_child(Some(&swatches_box));
|
swatches_scroller.set_child(Some(&swatches_box));
|
||||||
content.append(&swatches_scroller);
|
side_panel.append(&swatches_scroller);
|
||||||
|
|
||||||
|
// Geometry sliders will go here in Task 4
|
||||||
|
let geometry_box = GtkBox::new(Orientation::Vertical, 4);
|
||||||
|
side_panel.append(&geometry_box);
|
||||||
|
|
||||||
|
content.append(&side_panel);
|
||||||
|
|
||||||
let preview = Picture::new();
|
let preview = Picture::new();
|
||||||
preview.set_hexpand(true);
|
preview.set_hexpand(true);
|
||||||
@@ -56,10 +62,10 @@ pub fn build_editor_page(icon_path: &Path, on_back: impl Fn() + 'static) -> Resu
|
|||||||
root.append(&content);
|
root.append(&content);
|
||||||
|
|
||||||
let refresh_preview = {
|
let refresh_preview = {
|
||||||
let scheme = Rc::clone(&scheme);
|
let composite = Rc::clone(&composite);
|
||||||
let preview = preview.clone();
|
let preview = preview.clone();
|
||||||
move || {
|
move || {
|
||||||
let bytes = glib::Bytes::from_owned(scheme.borrow().content.clone().into_bytes());
|
let bytes = glib::Bytes::from_owned(composite.borrow().render().into_bytes());
|
||||||
match gtk::gdk::Texture::from_bytes(&bytes) {
|
match gtk::gdk::Texture::from_bytes(&bytes) {
|
||||||
Ok(texture) => preview.set_paintable(Some(&texture)),
|
Ok(texture) => preview.set_paintable(Some(&texture)),
|
||||||
Err(_) => preview.set_paintable(gtk::gdk::Paintable::NONE),
|
Err(_) => preview.set_paintable(gtk::gdk::Paintable::NONE),
|
||||||
@@ -70,7 +76,7 @@ pub fn build_editor_page(icon_path: &Path, on_back: impl Fn() + 'static) -> Resu
|
|||||||
|
|
||||||
let rebuild_swatches: Rc<RefCell<Box<dyn Fn()>>> = Rc::new(RefCell::new(Box::new(|| {})));
|
let rebuild_swatches: Rc<RefCell<Box<dyn Fn()>>> = Rc::new(RefCell::new(Box::new(|| {})));
|
||||||
{
|
{
|
||||||
let scheme = Rc::clone(&scheme);
|
let composite = Rc::clone(&composite);
|
||||||
let swatches_box = swatches_box.clone();
|
let swatches_box = swatches_box.clone();
|
||||||
let refresh_preview = refresh_preview.clone();
|
let refresh_preview = refresh_preview.clone();
|
||||||
let rebuild_swatches_for_closure = Rc::clone(&rebuild_swatches);
|
let rebuild_swatches_for_closure = Rc::clone(&rebuild_swatches);
|
||||||
@@ -80,8 +86,18 @@ pub fn build_editor_page(icon_path: &Path, on_back: impl Fn() + 'static) -> Resu
|
|||||||
swatches_box.remove(&child);
|
swatches_box.remove(&child);
|
||||||
}
|
}
|
||||||
|
|
||||||
let tags: Vec<(String, String)> = scheme.borrow().colors.clone();
|
let comp = composite.borrow();
|
||||||
for (tag, hex) in tags {
|
let mut all_colors = Vec::new();
|
||||||
|
for c in &comp.bg.colors {
|
||||||
|
all_colors.push((c.0.clone(), c.1.clone(), false));
|
||||||
|
}
|
||||||
|
if let Some(emblem) = &comp.emblem {
|
||||||
|
for c in &emblem.colors {
|
||||||
|
all_colors.push((c.0.clone(), c.1.clone(), true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (tag, hex, is_emblem) in all_colors {
|
||||||
let row = GtkBox::new(Orientation::Horizontal, 8);
|
let row = GtkBox::new(Orientation::Horizontal, 8);
|
||||||
let label = Label::new(Some(&tag));
|
let label = Label::new(Some(&tag));
|
||||||
label.set_hexpand(true);
|
label.set_hexpand(true);
|
||||||
@@ -93,7 +109,7 @@ pub fn build_editor_page(icon_path: &Path, on_back: impl Fn() + 'static) -> Resu
|
|||||||
button.set_rgba(&rgba);
|
button.set_rgba(&rgba);
|
||||||
|
|
||||||
{
|
{
|
||||||
let scheme = Rc::clone(&scheme);
|
let composite = Rc::clone(&composite);
|
||||||
let tag = tag.clone();
|
let tag = tag.clone();
|
||||||
let refresh_preview = refresh_preview.clone();
|
let refresh_preview = refresh_preview.clone();
|
||||||
let rebuild_swatches_for_closure = Rc::clone(&rebuild_swatches_for_closure);
|
let rebuild_swatches_for_closure = Rc::clone(&rebuild_swatches_for_closure);
|
||||||
@@ -105,10 +121,12 @@ pub fn build_editor_page(icon_path: &Path, on_back: impl Fn() + 'static) -> Resu
|
|||||||
(new_rgba.green() * 255.0).round() as u8,
|
(new_rgba.green() * 255.0).round() as u8,
|
||||||
(new_rgba.blue() * 255.0).round() as u8,
|
(new_rgba.blue() * 255.0).round() as u8,
|
||||||
);
|
);
|
||||||
let changed = scheme
|
let mut comp = composite.borrow_mut();
|
||||||
.borrow_mut()
|
let changed = if is_emblem {
|
||||||
.update_color(&tag, &new_hex)
|
comp.emblem.as_mut().unwrap().update_color(&tag, &new_hex).unwrap_or(false)
|
||||||
.unwrap_or(false);
|
} else {
|
||||||
|
comp.bg.update_color(&tag, &new_hex).unwrap_or(false)
|
||||||
|
};
|
||||||
if changed {
|
if changed {
|
||||||
refresh_preview();
|
refresh_preview();
|
||||||
(rebuild_swatches_for_closure.borrow())();
|
(rebuild_swatches_for_closure.borrow())();
|
||||||
@@ -127,27 +145,37 @@ pub fn build_editor_page(icon_path: &Path, on_back: impl Fn() + 'static) -> Resu
|
|||||||
(rebuild_swatches.borrow())();
|
(rebuild_swatches.borrow())();
|
||||||
|
|
||||||
{
|
{
|
||||||
let scheme = Rc::clone(&scheme);
|
let composite = Rc::clone(&composite);
|
||||||
let refresh_preview = refresh_preview.clone();
|
let refresh_preview = refresh_preview.clone();
|
||||||
let rebuild_swatches = Rc::clone(&rebuild_swatches);
|
let rebuild_swatches = Rc::clone(&rebuild_swatches);
|
||||||
undo_button.connect_clicked(move |_| {
|
undo_button.connect_clicked(move |_| {
|
||||||
if scheme.borrow_mut().undo().unwrap_or(false) {
|
let mut comp = composite.borrow_mut();
|
||||||
|
let mut changed = comp.bg.undo().unwrap_or(false);
|
||||||
|
if let Some(emblem) = &mut comp.emblem {
|
||||||
|
changed |= emblem.undo().unwrap_or(false);
|
||||||
|
}
|
||||||
|
if changed {
|
||||||
refresh_preview();
|
refresh_preview();
|
||||||
(rebuild_swatches.borrow())();
|
(rebuild_swatches.borrow())();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
let scheme = Rc::clone(&scheme);
|
let composite = Rc::clone(&composite);
|
||||||
let refresh_preview = refresh_preview.clone();
|
let refresh_preview = refresh_preview.clone();
|
||||||
let rebuild_swatches = Rc::clone(&rebuild_swatches);
|
let rebuild_swatches = Rc::clone(&rebuild_swatches);
|
||||||
redo_button.connect_clicked(move |_| {
|
redo_button.connect_clicked(move |_| {
|
||||||
if scheme.borrow_mut().redo().unwrap_or(false) {
|
let mut comp = composite.borrow_mut();
|
||||||
|
let mut changed = comp.bg.redo().unwrap_or(false);
|
||||||
|
if let Some(emblem) = &mut comp.emblem {
|
||||||
|
changed |= emblem.redo().unwrap_or(false);
|
||||||
|
}
|
||||||
|
if changed {
|
||||||
refresh_preview();
|
refresh_preview();
|
||||||
(rebuild_swatches.borrow())();
|
(rebuild_swatches.borrow())();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(root.upcast())
|
root.upcast()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user