bugs
This commit is contained in:
parent
a5d5f01674
commit
3645df0dac
|
|
@ -10,13 +10,13 @@ pub(crate) fn format_spice(n: f64, unit: &str) -> String {
|
|||
let (prefix, scale): (&str, f64) = if abs_n >= 1.0 {
|
||||
("", 1.0)
|
||||
} else if abs_n >= 1e-3 {
|
||||
("M", 1e-3)
|
||||
("m", 1e-3)
|
||||
} else if abs_n >= 1e-6 {
|
||||
("U", 1e-6)
|
||||
} else if abs_n >= 1e-9 {
|
||||
("N", 1e-9)
|
||||
} else {
|
||||
("P", 1e-12)
|
||||
("p", 1e-12)
|
||||
};
|
||||
let mantissa = n / scale;
|
||||
let mag = mantissa.abs().log10().floor() as i32;
|
||||
|
|
|
|||
|
|
@ -2,10 +2,15 @@ pub(crate) const SPICE_UNITS: &[&str] = &["F", "H", "HZ", "V", "A", "W", "R", "O
|
|||
|
||||
pub(crate) fn spice_prefix_scale(c: char) -> Option<f64> {
|
||||
match c {
|
||||
'm' | 'M' => Some(1e-3),
|
||||
'P' => Some(1e15),
|
||||
't' | 'T' => Some(1e12),
|
||||
'b' | 'B' => Some(1e9),
|
||||
'M' => Some(1e6),
|
||||
'k' | 'K' => Some(1e3),
|
||||
'm' => Some(1e-3),
|
||||
'u' | 'U' | 'µ' | 'μ' => Some(1e-6),
|
||||
'n' | 'N' => Some(1e-9),
|
||||
'p' | 'P' => Some(1e-12),
|
||||
'p' => Some(1e-12),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,7 +87,28 @@ use super::helpers::*;
|
|||
let mut i = Interpreter::new();
|
||||
i.exec("use spice").unwrap();
|
||||
let v = i.eval("0.5nF").unwrap();
|
||||
assert_eq!(v.display(), "500PF");
|
||||
assert_eq!(v.display(), "500pF");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn spice_large_prefixes_case_sensitive() {
|
||||
let mut i = Interpreter::new();
|
||||
i.exec("use spice").unwrap();
|
||||
let mut scale = |src: &str| match i.eval(src).unwrap() {
|
||||
Value::Spice(n, _) => n,
|
||||
Value::Number(n) => n,
|
||||
other => panic!("expected scalar, got {:?}", other),
|
||||
};
|
||||
assert!(approx(scale("100kHz"), 1e5));
|
||||
assert!(approx(scale("100KHz"), 1e5));
|
||||
assert!(approx(scale("100Mhz"), 1e8));
|
||||
assert!(approx(scale("100mhz"), 0.1));
|
||||
assert!(approx(scale("2bHz"), 2e9));
|
||||
assert!(approx(scale("2BHz"), 2e9));
|
||||
assert!(approx(scale("3THz"), 3e12));
|
||||
assert!(approx(scale("3tHz"), 3e12));
|
||||
assert!(approx(scale("5PHz"), 5e15));
|
||||
assert!(approx(scale("5pHz"), 5e-12));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -397,7 +397,7 @@ impl super::EditorState {
|
|||
let Some(inner) = inner_opt else { continue };
|
||||
|
||||
let is_active = self.active_free.as_ref() == Some(id);
|
||||
let band = (self.font_size * 1.3) * 0.5;
|
||||
let band = (self.font_size * 1.3).max(18.0);
|
||||
let body: Element<'_, Message, Theme, iced_wgpu::Renderer> = if is_active {
|
||||
let right = self.build_resize_band(
|
||||
id.clone(),
|
||||
|
|
|
|||
|
|
@ -85,12 +85,18 @@ impl EditorState {
|
|||
.into()
|
||||
} else {
|
||||
let editor = self.view_blocks();
|
||||
match self.build_free_overlay() {
|
||||
Some(overlay) => iced_widget::stack![editor, overlay]
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.into(),
|
||||
None => editor,
|
||||
let mut layers: Vec<Element<'_, Message, Theme, iced_wgpu::Renderer>> = vec![editor];
|
||||
if let Some(overlay) = self.build_free_overlay() {
|
||||
layers.push(overlay);
|
||||
}
|
||||
// context menu renders above the free overlay
|
||||
if let Some(menu_state) = &self.context_menu {
|
||||
layers.push(self.context_menu_view(menu_state));
|
||||
}
|
||||
if layers.len() == 1 {
|
||||
layers.pop().unwrap()
|
||||
} else {
|
||||
iced_widget::stack(layers).width(Length::Fill).height(Length::Fill).into()
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -167,12 +173,9 @@ impl EditorState {
|
|||
}
|
||||
|
||||
fn view_blocks(&self) -> Element<'_, Message, Theme, iced_wgpu::Renderer> {
|
||||
let has_computed_layers = !self.eval_results.is_empty()
|
||||
|| !self.computed_tables.is_empty()
|
||||
|| !self.computed_trees.is_empty();
|
||||
// a lone text block always renders through the compositor
|
||||
let single_text_block = self.block_count() == 1
|
||||
&& self.block_at(0).map(|b| b.as_any().is::<TextBlock>()).unwrap_or(false)
|
||||
&& !has_computed_layers;
|
||||
&& self.block_at(0).map(|b| b.as_any().is::<TextBlock>()).unwrap_or(false);
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "windows"))]
|
||||
let title_bar_h = 0.0_f32;
|
||||
|
|
@ -379,15 +382,11 @@ impl EditorState {
|
|||
};
|
||||
|
||||
let minimap_layer = self.minimap_overlay().unwrap_or_else(empty_layer);
|
||||
let ctx_layer = match &self.context_menu {
|
||||
Some(menu_state) => self.context_menu_view(menu_state),
|
||||
None => empty_layer(),
|
||||
};
|
||||
let spillover_layer = self.spillover_view().unwrap_or_else(empty_layer);
|
||||
|
||||
// the document scrollable stays at stack layer 0, never re-wrapped by an overlay.
|
||||
// a Fill stack gives the scrollable the viewport height, not the zero intrinsic of a Shrink stack
|
||||
iced_widget::stack![inner, selection_tint, minimap_layer, ctx_layer, spillover_layer]
|
||||
iced_widget::stack![inner, selection_tint, minimap_layer, spillover_layer]
|
||||
.width(Length::Fill)
|
||||
.height(Length::Fill)
|
||||
.into()
|
||||
|
|
@ -867,7 +866,7 @@ impl EditorState {
|
|||
CtxTarget::Object(node_id) => {
|
||||
let placed = self.free_placements.contains_key(node_id);
|
||||
let mode = self.object_mode(node_id);
|
||||
// a bulleted radio row that sets this object's mode
|
||||
// one object-mode option, bulleted when active
|
||||
let mode_item = |label: &str, m: LayoutMode| -> Element<'_, Message, Theme, iced_wgpu::Renderer> {
|
||||
item(
|
||||
&format!("{} {}", if mode == m { "•" } else { " " }, label),
|
||||
|
|
|
|||
Loading…
Reference in New Issue