Skip to content

Commit

Permalink
Add glyphkind field in new glyph window
Browse files Browse the repository at this point in the history
  • Loading branch information
epilys committed Mar 8, 2023
1 parent 9aa173b commit 5911e42
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 9 deletions.
50 changes: 43 additions & 7 deletions src/glyphs/obj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -273,18 +273,54 @@ impl GlyphMetadata {
Some("text"),
clone!(@strong self as obj => move |entry, _| {
let mut unicodes = obj.imp().unicode.borrow_mut();
let mut kinds = obj.imp().kinds.borrow_mut();
let text = entry.text();
if let Some(t) = text.strip_prefix("u+") {
unicodes.clear();
unicodes.push(Unicode::new(t.to_string()));
} else if let Some(t) = text.strip_prefix("U+") {
unicodes.clear();
unicodes.push(Unicode::new(t.to_string()));
if let Some(t) = text.strip_prefix("u+").or_else(|| text.strip_prefix("U+")) {
let val = Unicode::new(t.to_string());
// TODO show error to user
if let Ok(kind) = GlyphKind::try_from(&val) {
kinds.0 = kind;
unicodes.clear();
unicodes.push(val);
}
}
}),
);
let codepoint =
PropertyChoice::new("codepoint", gtk::RadioButton::new(), unicode_entry.upcast());
let name_entry = gtk::Entry::builder()
.visible(true)
.expand(false)
.placeholder_text("component name")
.build();
name_entry.buffer().connect_notify_local(
Some("text"),
clone!(@strong self as obj => move |entry, _| {
let mut unicodes = obj.imp().unicode.borrow_mut();
unicodes.clear();
let mut kinds = obj.imp().kinds.borrow_mut();
let text = entry.text();
kinds.0 = GlyphKind::from(text);
}),
);

let component = PropertyChoice::new(
"component",
gtk::RadioButton::from_widget(codepoint.button()),
name_entry.upcast(),
);
let kind_box = gtk::Box::builder()
.orientation(gtk::Orientation::Vertical)
.spacing(5)
.expand(true)
.visible(true)
.can_focus(true)
.build();
kind_box.pack_start(&codepoint, false, false, 5);
kind_box.pack_start(&component, false, false, 5);
kind_box.show_all();
w.add_separator();
w.add("unicode", unicode_label, unicode_entry.upcast());
w.add("unicode", unicode_label, kind_box.upcast());
}
w
}
Expand Down
39 changes: 39 additions & 0 deletions src/ufo/glif.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,45 @@ impl Unicode {
pub fn new(hex: String) -> Self {
Self { hex }
}

#[inline(always)]
pub fn hex(&self) -> &str {
self.hex.as_str()
}
}

/// ```
/// # use gerb::glyphs::GlyphKind;
/// # use gerb::ufo::glif::Unicode;
///
/// assert_eq!(GlyphKind::try_from(&Unicode::new("0062".to_string())).unwrap(), GlyphKind::from('b'));
/// assert_eq!(GlyphKind::try_from(&Unicode::new("0041".to_string())).unwrap(), GlyphKind::from('A'));
/// assert_eq!(GlyphKind::try_from(&Unicode::new("00E6".to_string())).unwrap(), GlyphKind::from('æ'));
/// assert_eq!(GlyphKind::try_from(&Unicode::new("0021".to_string())).unwrap(), GlyphKind::from('!'));
/// ```
impl TryFrom<&Unicode> for crate::glyphs::GlyphKind {
type Error = String;

fn try_from(val: &Unicode) -> Result<crate::glyphs::GlyphKind, Self::Error> {
let num = u32::from_str_radix(val.hex(), 16)
.map_err(|err| format!("{} is not a valid hex value: {err}.", val.hex()))?;
Ok(crate::glyphs::GlyphKind::Char(
char::from_u32(num)
.ok_or_else(|| format!("{} = {num} is not a valid codepoint value.", val.hex()))?,
))
}
}

impl From<char> for crate::glyphs::GlyphKind {
fn from(val: char) -> crate::glyphs::GlyphKind {
crate::glyphs::GlyphKind::Char(val)
}
}

impl From<String> for crate::glyphs::GlyphKind {
fn from(val: String) -> crate::glyphs::GlyphKind {
crate::glyphs::GlyphKind::Component(val)
}
}

#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Default)]
Expand Down
13 changes: 13 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,16 @@ macro_rules! impl_modified {
}
};
}

#[macro_export]
macro_rules! impl_deref {
($ty:ty, $inner:ty) => {
impl std::ops::Deref for $ty {
type Target = $inner;

fn deref(&self) -> &Self::Target {
self.imp()
}
}
};
}
77 changes: 76 additions & 1 deletion src/utils/property_window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -547,7 +547,7 @@ pub fn get_widget_for_value(
.sensitive(readwrite)
.visible(true)
.halign(gtk::Align::Start)
.valign(gtk::Align::Start)
.valign(gtk::Align::Center)
.use_alpha(true)
.show_editor(true)
.build();
Expand Down Expand Up @@ -828,3 +828,78 @@ pub fn new_property_window(
w.set_child(Some(&scrolled_window));
w
}

#[derive(Default, Debug)]
pub struct PropertyChoiceInner {
pub btn: OnceCell<gtk::RadioButton>,
pub widget: OnceCell<gtk::Widget>,
}

#[glib::object_subclass]
impl ObjectSubclass for PropertyChoiceInner {
const NAME: &'static str = "PropertyChoice";
type Type = PropertyChoice;
type ParentType = gtk::Box;
}

impl ObjectImpl for PropertyChoiceInner {
fn constructed(&self, obj: &Self::Type) {
self.parent_constructed(obj);
obj.upcast_ref::<gtk::Box>()
.set_orientation(gtk::Orientation::Horizontal);
obj.set_spacing(1);
obj.set_expand(false);
obj.set_visible(true);
obj.set_can_focus(true);
}
}

impl WidgetImpl for PropertyChoiceInner {}
impl ContainerImpl for PropertyChoiceInner {}
impl BoxImpl for PropertyChoiceInner {}

glib::wrapper! {
pub struct PropertyChoice(ObjectSubclass<PropertyChoiceInner>)
@extends gtk::Widget, gtk::Container, gtk::Box;
}

impl PropertyChoice {
pub fn new(label: &str, btn: gtk::RadioButton, widget: gtk::Widget) -> Self {
let ret: PropertyChoice = glib::Object::new(&[]).unwrap();
let label = gtk::Label::builder()
.label(label)
.visible(true)
.selectable(false)
.max_width_chars(30)
.halign(gtk::Align::Start)
.wrap(true)
.expand(false)
.build();
let event_box = gtk::EventBox::builder()
.events(gtk::gdk::EventMask::BUTTON_PRESS_MASK)
.above_child(true)
.child(&label)
.visible(true)
.build();
ret.pack_start(&event_box, false, false, 5);
ret.pack_start(&btn, false, false, 5);
ret.pack_start(&widget, false, false, 5);
btn.bind_property("active", &widget, "sensitive")
.flags(glib::BindingFlags::SYNC_CREATE)
.build();
event_box.connect_button_press_event(clone!(@weak btn => @default-return Inhibit(false), move |_, event| {
if event.button() == gtk::gdk::BUTTON_PRIMARY && event.event_type() == gtk::gdk::EventType::ButtonPress {
btn.set_active(true);
}
Inhibit(false)
}));
ret.btn.set(btn).unwrap();
ret
}

pub fn button(&self) -> &gtk::RadioButton {
self.btn.get().unwrap()
}
}

impl_deref!(PropertyChoice, PropertyChoiceInner);
1 change: 0 additions & 1 deletion src/views/collection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,6 @@ impl ObjectImpl for CollectionInner {
save.connect_clicked(clone!(@weak metadata, @weak w, @weak obj => move |_| {
let project = obj.project();
let name = metadata.name().to_string();
//FIXME: set GlyphKind
let glyph = Rc::new(RefCell::new(metadata.clone().into()));
metadata.glyph_ref.set(glyph.clone()).unwrap();
//FIXME: show err msg
Expand Down

0 comments on commit 5911e42

Please sign in to comment.