diff --git a/docs/navigation.md b/docs/navigation.md index 54ba0ea..dff745e 100644 --- a/docs/navigation.md +++ b/docs/navigation.md @@ -29,6 +29,7 @@ will clear the numeric prefix if you want to cancel it. **Modifying the Sheet or Cells** * `e` or `i` will enter CellEdit mode for the current cell. +* 'I' will toggle italic on the cell. 'B' will toggle bold. * `Ctrl-h` will shorten the width of the column you are on. * `Ctrl-l` will lengthen the width of the column you are on. diff --git a/examples/test.xlsx b/examples/test.xlsx index ac5e7f9..3276b32 100644 Binary files a/examples/test.xlsx and b/examples/test.xlsx differ diff --git a/result b/result deleted file mode 120000 index 774cfe9..0000000 --- a/result +++ /dev/null @@ -1 +0,0 @@ -/nix/store/mvnsm5ndvx4psah2d3y6yd2vwkypy9m7-sheetui-0.1.0 \ No newline at end of file diff --git a/src/book/mod.rs b/src/book/mod.rs index 6651a82..9f9225f 100644 --- a/src/book/mod.rs +++ b/src/book/mod.rs @@ -343,12 +343,6 @@ impl Book { sheet: u32, col_idx: usize, ) -> Result<()> { - // TODO(jeremy): This is a little hacky and the underlying model - // supports a better mechanism but UserModel doesn't support it yet. - // https://github.com/ironcalc/IronCalc/issues/273 - // https://github.com/ironcalc/IronCalc/pull/276 is the coming fix. - // NOTE(jwall): Because of the number of cells required to modify - // this is crazy slow let area = self.get_col_range(sheet, col_idx); self.set_cell_style(style, &area)?; Ok(()) @@ -373,10 +367,6 @@ impl Book { sheet: u32, row_idx: usize, ) -> Result<()> { - // TODO(jeremy): This is a little hacky and the underlying model - // supports a better mechanism but UserModel doesn't support it yet. - // https://github.com/ironcalc/IronCalc/issues/273 - // https://github.com/ironcalc/IronCalc/pull/276 is the coming fix. let area = self.get_row_range(sheet, row_idx); self.set_cell_style(style, &area)?; Ok(()) diff --git a/src/ui/mod.rs b/src/ui/mod.rs index 662426d..6e872b3 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -669,6 +669,16 @@ impl<'ws> Workspace<'ws> { self.state.reset_n_prefix(); self.state.char_queue.clear(); } + KeyCode::Char('B') => { + let address = self.book.location.clone(); + let style = self.book.get_cell_style(self.book.current_sheet, &address).map(|s| s.font.b); + self.toggle_bool_style(style, "font.b", &address)?; + } + KeyCode::Char('I') => { + let address = self.book.location.clone(); + let style = self.book.get_cell_style(self.book.current_sheet, &address).map(|s| s.font.i); + self.toggle_bool_style(style, "font.i", &address)?; + } KeyCode::Char(d) if d.is_ascii_digit() => { self.handle_numeric_prefix(d); } @@ -840,6 +850,24 @@ impl<'ws> Workspace<'ws> { return Ok(None); } + fn toggle_bool_style(&mut self, current_val: Option, path: &str, address: &Address) -> Result<(), anyhow::Error> { + let value = if let Some(b_val) = current_val { + if b_val { "false" } else { "true" } + } else { + "true" + }; + self.book.set_cell_style( + &[(path, value)], + &Area { + sheet: self.book.current_sheet, + row: address.row as i32, + column: address.col as i32, + width: 1, + height: 1, + })?; + Ok(()) + } + fn paste_range(&mut self) -> Result<(), anyhow::Error> { match &self.state.clipboard { Some(ClipboardContents::Cell(contents)) => { diff --git a/src/ui/render/viewport.rs b/src/ui/render/viewport.rs index e3bf60e..847951a 100644 --- a/src/ui/render/viewport.rs +++ b/src/ui/render/viewport.rs @@ -193,15 +193,28 @@ impl<'ws> Viewport<'ws> { ci: usize, mut cell: Cell<'widget>, ) -> Cell<'widget> { - let style = self + // TODO(zaphar): Should probably create somekind of formatter abstraction. + if let Some(style) = self .book - .get_cell_style(self.book.current_sheet, &Address { row: ri, col: ci }); + .get_cell_style(self.book.current_sheet, &Address { row: ri, col: ci }) { + cell = self.compute_cell_colors(&style, ri, ci, cell); + cell = if style.font.b { + cell.bold() + } else { cell }; + cell = if style.font.i { + cell.italic() + } else { cell }; + } + cell + } + + fn compute_cell_colors<'widget>(&self, style: &ironcalc::base::types::Style, ri: usize, ci: usize, mut cell: Cell<'widget>) -> Cell<'widget> { let bg_color = map_color( - style.as_ref().map(|s| s.fill.bg_color.as_ref()).flatten(), + style.fill.bg_color.as_ref(), Color::Rgb(35, 33, 54), ); let fg_color = map_color( - style.as_ref().map(|s| s.fill.fg_color.as_ref()).flatten(), + style.fill.fg_color.as_ref(), Color::White, ); if let Some((start, end)) = &self.range_selection.map_or(None, |r| r.get_range()) { @@ -212,12 +225,12 @@ impl<'ws> Viewport<'ws> { } else { cell = cell.bg(bg_color).fg(fg_color); } - match (self.book.location.row == ri, self.book.location.col == ci) { + cell = match (self.book.location.row == ri, self.book.location.col == ci) { (true, true) => cell.fg(Color::White).bg(Color::Rgb(57, 61, 71)), // TODO(zaphar): Support ironcalc style options _ => cell, - } - .bold() + }; + cell } } diff --git a/src/ui/test.rs b/src/ui/test.rs index 356b695..64a7c9a 100644 --- a/src/ui/test.rs +++ b/src/ui/test.rs @@ -320,7 +320,7 @@ fn test_input_navitation_enter_key() { #[test] fn test_input_navitation_tab_key() { let mut ws = new_workspace(); - let col = dbg!(ws.book.location.col); + let col = ws.book.location.col; assert_eq!(Some(&Modality::Navigate), ws.state.modality_stack.last()); script() .tab() @@ -352,7 +352,7 @@ fn test_input_navitation_shift_enter_key() { #[test] fn test_input_navitation_shift_tab_key() { let mut ws = new_workspace(); - let col = dbg!(ws.book.location.col); + let col = ws.book.location.col; assert_eq!(Some(&Modality::Navigate), ws.state.modality_stack.last()); script() .tab() @@ -931,7 +931,6 @@ fn test_edit_mode_paste() { assert_eq!(Some(&Modality::Navigate), ws.state.modality_stack.last()); ws.state.range_select.start = Some(Address { row: 1, col: 1 }); ws.state.range_select.end = Some(Address { row: 2, col: 2 }); - dbg!(ws.selected_range_to_string()); script() .char('e') .ctrl('p') @@ -1130,7 +1129,6 @@ macro_rules! assert_range_copy { Some(&Modality::RangeSelect), ws.state.modality_stack.iter().last() ); - dbg!(ws.state.range_select.get_range()); $script.run(&mut ws).expect("failed to run script"); assert!(ws.state.clipboard.is_some()); match ws.state.clipboard.unwrap() { @@ -1234,7 +1232,13 @@ fn test_color_row() { for ci in [1, book::LAST_COLUMN] { let style = ws .book - .get_cell_style(ws.book.current_sheet, &Address { row: 1, col: ci as usize }) + .get_cell_style( + ws.book.current_sheet, + &Address { + row: 1, + col: ci as usize, + }, + ) .expect("failed to get style"); assert_eq!( "#800000", @@ -1259,7 +1263,13 @@ fn test_color_col() { for ri in [1, book::LAST_ROW] { let style = ws .book - .get_cell_style(ws.book.current_sheet, &Address { row: ri as usize, col: 1 }) + .get_cell_style( + ws.book.current_sheet, + &Address { + row: ri as usize, + col: 1, + }, + ) .expect("failed to get style"); assert_eq!( "#800000", @@ -1272,6 +1282,53 @@ fn test_color_col() { } } +#[test] +fn test_bold_text() { + let mut ws = new_workspace(); + let before_style = ws + .book + .get_cell_style(0, &Address { row: 1, col: 1 }) + .expect("Failed to get style"); + assert!(!before_style.font.b); + script() + .char('B') + .run(&mut ws) + .expect("Unable to run script"); + let style = ws + .book + .get_cell_style(0, &Address { row: 1, col: 1 }) + .expect("Failed to get style"); + assert!(style.font.b); + script() + .char('B') + .run(&mut ws) + .expect("Unable to run script"); + assert!(!before_style.font.b); +} + +#[test] +fn test_italic_text() { + let mut ws = new_workspace(); + let before_style = ws + .book + .get_cell_style(0, &Address { row: 1, col: 1 }) + .expect("Failed to get style"); + assert!(!before_style.font.i); + script() + .char('I') + .run(&mut ws) + .expect("Unable to run script"); + let style = ws + .book + .get_cell_style(0, &Address { row: 1, col: 1 }) + .expect("Failed to get style"); + assert!(style.font.i); + script() + .char('I') + .run(&mut ws) + .expect("Unable to run script"); + assert!(!before_style.font.i); +} fn new_workspace<'a>() -> Workspace<'a> { Workspace::new_empty("en", "America/New_York").expect("Failed to get empty workbook")