Skip to content

Commit

Permalink
update UIs to use CharmAddrEntry instead of GtkEntry where appropriate
Browse files Browse the repository at this point in the history
  • Loading branch information
misson20000 committed Nov 29, 2024
1 parent fedd6de commit 2d3bfa5
Show file tree
Hide file tree
Showing 19 changed files with 286 additions and 236 deletions.
2 changes: 1 addition & 1 deletion gir/Charm-0.1.gir
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<class name="AddrEntry" parent="Gtk.Entry" glib:type-name="CharmAddrEntry" glib:get-type="charm_addr_entry_get_type">
<glib:signal name="addr-changed">
<return-value transfer-ownership="none">
<type name="none" c:type="void"/>
<type name="none"/>
</return-value>
</glib:signal>
</class>
Expand Down
6 changes: 3 additions & 3 deletions src/model/addr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ impl<Kind> Address<Kind> {
radix = 16;
}

let mut byte_portion = i.next().ok_or(AddressParseError::MissingBytes)?;
let mut byte_portion = i.next().ok_or(AddressParseError::EmptyString)?;

if let Some(bp) = byte_portion.strip_prefix("0x") {
radix = 16;
Expand Down Expand Up @@ -182,9 +182,9 @@ pub struct ExtentTriplet<Kind> {
pub after: ExtentTripletEnding<Kind>,
}

#[derive(Debug, PartialEq, Eq)]
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum AddressParseError {
MissingBytes,
EmptyString,
MalformedBytes(std::num::ParseIntError),
MalformedBits(std::num::ParseIntError),
TooManyBits,
Expand Down
12 changes: 8 additions & 4 deletions src/view/action/listing/goto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::model::addr;
use crate::model::document;
use crate::model::document::search;
use crate::model::listing::cursor;
use crate::view::addr_entry;
use crate::view::helpers;
use crate::view::listing;
use crate::view::window;
Expand All @@ -25,7 +26,7 @@ struct GotoAction {
lw: listing::ListingWidget,

dialog: gtk::ApplicationWindow,
entry: gtk::Entry,
entry: addr_entry::AddrEntry,

model: gtk::SingleSelection,
store: gio::ListStore,
Expand All @@ -37,7 +38,7 @@ struct GotoAction {
pub fn add_action(window_context: &window::WindowContext) {
let builder = gtk::Builder::from_string(include_str!("goto.ui"));

let entry: gtk::Entry = builder.object("entry").unwrap();
let entry: addr_entry::AddrEntry = builder.object("entry").unwrap();
let list: gtk::ListView = builder.object("list").unwrap();
//let cancel_button: gtk::Button = builder.object("cancel_button").unwrap();

Expand Down Expand Up @@ -74,7 +75,7 @@ pub fn add_action(window_context: &window::WindowContext) {
action.do_goto(action.model.item(position));
}));

action.entry.connect_changed(clone!(#[weak] action, move |_| catch_panic! {
action.entry.connect_addr_changed(clone!(#[weak] action, move |_, _| catch_panic! {
action.refresh_results(None, false);
}));

Expand Down Expand Up @@ -105,7 +106,10 @@ impl GotoAction {
}

fn refresh_results(&self, new_document: Option<sync::Arc<document::Document>>, force: bool) {
let new_addr = addr::AbsoluteAddress::parse(self.entry.text().as_str(), false).ok().and_then(|na| if na == self.current_addr.get() { None } else { Some(na) });
let new_addr = self.entry.addr()
.ok()
.map(|a| addr::AbsoluteAddress::ZERO + a)
.and_then(|na| if na == self.current_addr.get() { None } else { Some(na) });

if new_addr.is_some() || new_document.is_some() || force {
if let Some(new_document) = new_document {
Expand Down
6 changes: 4 additions & 2 deletions src/view/action/listing/goto.ui
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Created with Cambalache 0.92.2 -->
<!-- Created with Cambalache 0.93.0 -->
<interface>
<requires lib="gtk" version="4.0"/>
<requires lib="charm" version="0.1"/>
<object class="GtkBox" id="toplevel">
<property name="margin-bottom">15</property>
<property name="margin-end">15</property>
Expand All @@ -17,7 +18,8 @@
</object>
</child>
<child>
<object class="GtkEntry" id="entry">
<object class="CharmAddrEntry" id="entry">
<property name="hexpand">True</property>
<property name="margin-bottom">10</property>
</object>
</child>
Expand Down
37 changes: 18 additions & 19 deletions src/view/action/listing/insert-node.ui
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Created with Cambalache 0.92.2 -->
<!-- Created with Cambalache 0.93.0 -->
<interface>
<requires lib="gtk" version="4.0"/>
<requires lib="charm" version="0.1"/>
<object class="GtkBox" id="toplevel">
<property name="margin-bottom">15</property>
<property name="margin-end">15</property>
Expand Down Expand Up @@ -128,18 +129,6 @@
</layout>
</object>
</child>
<child>
<object class="GtkEntry" id="size_entry">
<property name="activates-default">True</property>
<property name="hexpand">True</property>
<layout>
<property name="column">1</property>
<property name="column-span">2</property>
<property name="row">2</property>
<property name="row-span">1</property>
</layout>
</object>
</child>
<child>
<object class="GtkCheckButton" id="nest_enable">
<property name="halign">start</property>
Expand All @@ -165,8 +154,17 @@
</object>
</child>
<child>
<object class="GtkEntry" id="offset_entry">
<property name="activates-default">True</property>
<object class="GtkLabel">
<property name="halign">start</property>
<property name="label">Size</property>
<layout>
<property name="column">0</property>
<property name="row">2</property>
</layout>
</object>
</child>
<child>
<object class="CharmAddrEntry" id="offset_entry">
<property name="hexpand">True</property>
<layout>
<property name="column">1</property>
Expand All @@ -177,12 +175,13 @@
</object>
</child>
<child>
<object class="GtkLabel">
<property name="halign">start</property>
<property name="label">Size</property>
<object class="CharmAddrEntry" id="size_entry">
<property name="hexpand">True</property>
<layout>
<property name="column">0</property>
<property name="column">1</property>
<property name="column-span">2</property>
<property name="row">2</property>
<property name="row-span">1</property>
</layout>
</object>
</child>
Expand Down
42 changes: 32 additions & 10 deletions src/view/action/listing/insert_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::model::addr;
use crate::model::document;
use crate::model::document::structure;
use crate::model::selection;
use crate::view::addr_entry;
use crate::view::error;
use crate::view::helpers;
use crate::view::listing;
Expand All @@ -28,12 +29,13 @@ struct InsertNodeAction {
dialog: gtk::ApplicationWindow,

name_entry: gtk::Entry,
size_entry: gtk::Entry,
offset_entry: gtk::Entry,
size_entry: addr_entry::AddrEntry,
offset_entry: addr_entry::AddrEntry,
order_entry: gtk::DropDown,
path_display: gtk::Entry,
nest_enable: gtk::CheckButton,
nest_entry: gtk::DropDown,
insert_button: gtk::Button,
}

struct InsertActivation {
Expand All @@ -58,8 +60,8 @@ impl InsertNodeAction {
let builder = gtk::Builder::from_string(include_str!("insert-node.ui"));

let name_entry: gtk::Entry = builder.object("name_entry").unwrap();
let size_entry: gtk::Entry = builder.object("size_entry").unwrap();
let offset_entry: gtk::Entry = builder.object("offset_entry").unwrap();
let size_entry: addr_entry::AddrEntry = builder.object("size_entry").unwrap();
let offset_entry: addr_entry::AddrEntry = builder.object("offset_entry").unwrap();
let order_entry: gtk::DropDown = builder.object("order_entry").unwrap();
let path_display: gtk::Entry = builder.object("path_display").unwrap();
let nest_enable: gtk::CheckButton = builder.object("nest_enable").unwrap();
Expand Down Expand Up @@ -93,6 +95,7 @@ impl InsertNodeAction {
path_display,
nest_enable,
nest_entry,
insert_button,
});

helpers::bind_simple_action(&action, &action.dialog, "cancel", |action| {
Expand All @@ -104,6 +107,14 @@ impl InsertNodeAction {
action.deactivate();
});

action.size_entry.connect_addr_changed(clone!(#[weak] action, move |_, _| {
action.update_dialog_preconditions();
}));

action.offset_entry.connect_addr_changed(clone!(#[weak] action, move |_, _| {
action.update_dialog_preconditions();
}));

dialog.connect_close_request(clone!(#[weak] action, #[upgrade_or] glib::Propagation::Proceed, move |_| {
catch_panic! {
action.deactivate();
Expand All @@ -114,31 +125,37 @@ impl InsertNodeAction {
action
}

fn update_dialog_preconditions(&self) {
let ok = self.size_entry.addr().is_ok()
&& self.offset_entry.addr().is_ok()
&& self.activation.borrow().is_some();

self.insert_button.set_sensitive(ok);
}

fn change(&self) -> Result<document::change::Change, error::Error> {
let name = self.name_entry.text().as_str().to_string();

let size_text = self.size_entry.text();
let size = match addr::Offset::parse(size_text.as_str(), false) {
let size = match self.size_entry.addr() {
Ok(a) => a,
Err(e) => return Err(error::Error {
while_attempting: error::Action::InsertNodeParseSize,
trouble: error::Trouble::AddressParseFailed {
error: e,
address: size_text.to_string(),
address: self.size_entry.text().to_string(),
},
level: error::Level::Error,
is_bug: false,
})
};

let offset_text = self.offset_entry.text();
let offset = match addr::Offset::parse(offset_text.as_str(), false) {
let offset = match self.offset_entry.addr() {
Ok(a) => a,
Err(e) => return Err(error::Error {
while_attempting: error::Action::InsertNodeParseOffset,
trouble: error::Trouble::AddressParseFailed {
error: e,
address: offset_text.to_string(),
address: self.offset_entry.text().to_string(),
},
level: error::Level::Error,
is_bug: false,
Expand All @@ -152,6 +169,8 @@ impl InsertNodeAction {
panic!("Insert node action running without activation");
}
};

self.update_dialog_preconditions();

let parent_node = activation.document.lookup_node(&activation.path).0;
let props = parent_node.props.clone_rename(name);
Expand Down Expand Up @@ -281,6 +300,8 @@ impl InsertNodeAction {
}

self.activation.replace(Some(activation));

self.update_dialog_preconditions();

self.name_entry.grab_focus();
self.dialog.present();
Expand All @@ -289,6 +310,7 @@ impl InsertNodeAction {
fn deactivate(&self) {
self.order_entry.set_model(gio::ListModel::NONE);
self.activation.take();
self.update_dialog_preconditions();
self.dialog.hide();
}
}
Expand Down
33 changes: 25 additions & 8 deletions src/view/addr_entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,18 @@ impl AddrEntry {
glib::Object::builder().build()
}

pub fn addr(&self) -> Option<addr::Offset> {
self.imp().addr.get()
pub fn addr(&self) -> Result<addr::Offset, addr::AddressParseError> {
(*self.imp().addr.borrow()).clone()
}

pub fn connect_addr_changed<F: Fn(&Self, Result<addr::Offset, addr::AddressParseError>) + 'static>(&self, f: F) -> glib::SignalHandlerId {
self.connect_closure(
"addr-changed",
false,
glib::closure_local!(move |entry: &AddrEntry| {
let a = entry.addr();
f(entry, a)
}))
}
}

Expand All @@ -33,9 +43,16 @@ pub unsafe extern "C" fn charm_addr_entry_get_type() -> <glib::Type as IntoGlib>
mod imp {
use super::*;

#[derive(Default)]
pub struct AddrEntry {
pub addr: cell::Cell<Option<addr::Offset>>,
pub addr: cell::RefCell<Result<addr::Offset, addr::AddressParseError>>,
}

impl Default for AddrEntry {
fn default() -> Self {
Self {
addr: cell::RefCell::new(Err(addr::AddressParseError::EmptyString)),
}
}
}

#[glib::object_subclass]
Expand Down Expand Up @@ -75,21 +92,21 @@ mod imp {
self.obj().set_css_classes(&[]);
self.obj().set_icon_from_icon_name(gtk::EntryIconPosition::Secondary, None);
self.obj().set_icon_tooltip_text(gtk::EntryIconPosition::Secondary, None);
self.addr.set(Some(addr));
*self.addr.borrow_mut() = Ok(addr);
}
Err(e) => {
self.obj().set_css_classes(&["error"]);
self.obj().set_icon_from_icon_name(gtk::EntryIconPosition::Secondary, Some("dialog-error"));

let error_string = match e {
addr::AddressParseError::MissingBytes => "cannot be empty".to_string(),
let error_string = match &e {
addr::AddressParseError::EmptyString => "cannot be empty".to_string(),
addr::AddressParseError::MalformedBytes(pie) => format!("failed to parse bytes: {}", pie),
addr::AddressParseError::MalformedBits(pie) => format!("failed to parse bits: {}", pie),
addr::AddressParseError::TooManyBits => "bit offset too large".to_string(),
};

self.obj().set_icon_tooltip_text(gtk::EntryIconPosition::Secondary, Some(&error_string));
self.addr.set(None);
*self.addr.borrow_mut() = Err(e);
}
}

Expand Down
Loading

0 comments on commit 2d3bfa5

Please sign in to comment.