~vpzom/savg

fe28215e92ec73b6966ad48c29bf21ecc9c6e566 — Colin Reeder 5 years ago cc6ae72
Add sidebar & color selection
3 files changed, 150 insertions(+), 1 deletions(-)

M src/color.rs
M src/document.rs
M src/main.rs
M src/color.rs => src/color.rs +54 -0
@@ 18,3 18,57 @@ pub struct RGB {
    pub g: u8,
    pub b: u8,
}

impl Color {
    pub fn to_gdk_rgba(&self) -> gdk::RGBA {
        match self {
            Color::RGBA(rgba) => rgba.to_gdk_rgba(),
            Color::RGB(rgb) => rgb.to_gdk_rgba(),
        }
    }

    pub fn from_gdk_rgba(src: &gdk::RGBA) -> Color {
        let r = (src.red * 255.0) as u8;
        let g = (src.green * 255.0) as u8;
        let b = (src.blue * 255.0) as u8;
        let a = src.alpha as f32;

        if a < 1.0 {
            Color::RGBA(RGBA {
                r,
                g,
                b,
                a,
            })
        }
        else {
            Color::RGB(RGB {
                r,
                g,
                b,
            })
        }
    }
}

impl RGBA {
    pub fn to_gdk_rgba(&self) -> gdk::RGBA {
        gdk::RGBA {
            red: f64::from(self.r) / 255.0,
            green: f64::from(self.g) / 255.0,
            blue: f64::from(self.b) / 255.0,
            alpha: f64::from(self.a) / 255.0,
        }
    }
}

impl RGB {
    pub fn to_gdk_rgba(&self) -> gdk::RGBA {
        gdk::RGBA {
            red: f64::from(self.r) / 255.0,
            green: f64::from(self.g) / 255.0,
            blue: f64::from(self.b) / 255.0,
            alpha: 1.0,
        }
    }
}

M src/document.rs => src/document.rs +14 -0
@@ 79,6 79,20 @@ impl Element {
            }
        }
    }
    pub fn presentation(&self) -> Option<&Presentation> {
        match self {
            Element::Rect(rect) => {
                Some(&rect.presentation)
            }
        }
    }
    pub fn presentation_mut(&mut self) -> Option<&mut Presentation> {
        match self {
            Element::Rect(rect) => {
                Some(&mut rect.presentation)
            }
        }
    }
}

pub trait ScalableElement {

M src/main.rs => src/main.rs +82 -1
@@ 35,6 35,7 @@ fn main() {
        }),
        repaint: AtomicBool::new(false),
        selection: RwLock::new(None),
        update_sidebar: AtomicBool::new(true),
        tool: RwLock::new(ToolMode::Select),
    });



@@ 72,9 73,40 @@ fn main() {
        }
    }

    let fill_btn = gtk::ColorButton::new();
    fill_btn.set_use_alpha(true);
    {
        let instance = instance.clone();
        let fill_btn_a = &fill_btn;
        let fill_btn = fill_btn.clone();
        fill_btn_a.connect_color_set(move |_| {
            let new_color = fill_btn.get_rgba();
            let new_color = color::Color::from_gdk_rgba(&new_color);

            let mut document = instance.document.write().unwrap();
            let selection = instance.selection.read().unwrap();
            for elem in &mut document.content {
                if selection.as_ref() == Some(&elem.id()) {
                    if let Some(presentation) = elem.as_mut().presentation_mut() {
                        presentation.fill = Some(Paint::Color(new_color));
                        instance.queue_repaint();
                    }
                    else {
                        eprintln!("Tried to color a non-presentation element!");
                    }
                    break;
                }
            }
        });
    }

    let sidebar = gtk::Box::new(gtk::Orientation::Vertical, 2);
    sidebar.pack_start(&fill_btn, false, false, 0);

    let content_box = gtk::Box::new(gtk::Orientation::Horizontal, 2);
    content_box.pack_start(&toolbar, false, false, 0);
    content_box.pack_end(&area, true, true, 0);
    content_box.pack_start(&area, true, true, 0);
    content_box.pack_end(&sidebar, false, false, 0);

    let save_item = gtk::MenuItem::new_with_label("Save");



@@ 230,6 262,7 @@ fn main() {
                    }));

                    *instance.selection.write().unwrap() = Some(obj.id());
                    instance.queue_update_sidebar();
                    *instance.drag_state.write().unwrap() = Some(DragState::ScaleBoth {
                        start_pos: position,
                    });


@@ 286,6 319,7 @@ fn main() {
                        Some(e) => Some(e.id()),
                        None => None
                    };
                    instance.queue_update_sidebar();

                    instance.queue_repaint();
                },


@@ 402,6 436,7 @@ fn main() {

                if removed {
                    *selection = None;
                    instance.queue_update_sidebar();
                    instance.queue_repaint();
                }
            }


@@ 450,6 485,8 @@ fn main() {
    });

    let area = Arc::new(fragile::Fragile::new(area));
    let sidebar = Arc::new(fragile::Fragile::new(sidebar));
    let fill_btn = Arc::new(fragile::Fragile::new(fill_btn));

    std::thread::spawn(move || {
        loop {


@@ 462,6 499,46 @@ fn main() {
                    Continue(false)
                });
            }
            {
                let instance = instance.clone();
                if instance.update_sidebar.compare_and_swap(true, false, std::sync::atomic::Ordering::Acquire) {
                    let sidebar = sidebar.clone();
                    let fill_btn = fill_btn.clone();
                    glib::idle_add(move || {
                        let sidebar = sidebar.get();
                        let fill_btn = fill_btn.get();

                        let document = instance.document.read().unwrap();

                        let new_selection = instance.selection.read().unwrap();
                        let new_selection: &Option<u64> = &new_selection;
                        let new_selection = if let Some(new_selection) = new_selection {
                            document.content.iter().find(|elem| elem.id() == *new_selection)
                        }
                        else {
                            None
                        };

                        if let Some(obj) = new_selection {
                            if let Some(presentation) = obj.as_ref().presentation() {
                                if let Some(Paint::Color(ref color)) = presentation.fill {
                                    fill_btn.set_rgba(&color.to_gdk_rgba());
                                    fill_btn.show();
                                }
                            }
                            else {
                                fill_btn.hide();
                            }
                            sidebar.show();
                        }
                        else {
                            sidebar.hide();
                        }

                        Continue(false)
                    });
                }
            }
        }
    });



@@ 472,6 549,7 @@ struct EditInstance {
    document: RwLock<Document>,
    repaint: AtomicBool,
    selection: RwLock<Option<u64>>,
    update_sidebar: AtomicBool,
    tool: RwLock<ToolMode>,
    drag_state: RwLock<Option<DragState>>,
    last_mouse_pos: RwLock<Point2>,


@@ 481,6 559,9 @@ impl EditInstance {
    pub fn queue_repaint(&self) {
        self.repaint.store(true, std::sync::atomic::Ordering::Release);
    }
    pub fn queue_update_sidebar(&self) {
        self.update_sidebar.store(true, std::sync::atomic::Ordering::Release);
    }
}

#[derive(Clone, Copy, PartialEq, Eq)]