mirror of
https://github.com/zaphar/sheetsui.git
synced 2025-07-26 23:09:50 -04:00
Compare commits
1 Commits
e798350cd2
...
a299d5e806
Author | SHA1 | Date | |
---|---|---|---|
a299d5e806 |
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -841,7 +841,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ironcalc"
|
name = "ironcalc"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/ironcalc/IronCalc?rev=264fcac63cc93b08a4b4a6764815e0c0adf6a53c#99125f1fea1c8c72c61f8cba94d847ed3471a4af"
|
source = "git+https://github.com/ironcalc/IronCalc?rev=264fcac63cc93b08a4b4a6764815e0c0adf6a53c#42d557d48567851102725bf3f7bef39a0baecb72"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitcode",
|
"bitcode",
|
||||||
"chrono",
|
"chrono",
|
||||||
@ -857,7 +857,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "ironcalc_base"
|
name = "ironcalc_base"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
source = "git+https://github.com/ironcalc/IronCalc?rev=264fcac63cc93b08a4b4a6764815e0c0adf6a53c#99125f1fea1c8c72c61f8cba94d847ed3471a4af"
|
source = "git+https://github.com/ironcalc/IronCalc?rev=264fcac63cc93b08a4b4a6764815e0c0adf6a53c#42d557d48567851102725bf3f7bef39a0baecb72"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitcode",
|
"bitcode",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
117
src/book/mod.rs
117
src/book/mod.rs
@ -3,7 +3,10 @@ use std::cmp::max;
|
|||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use ironcalc::{
|
use ironcalc::{
|
||||||
base::{
|
base::{
|
||||||
expressions::types::Area, types::{Border, Col, Fill, Font, Row, SheetData, Style, Worksheet}, worksheet::WorksheetDimension, Model, UserModel
|
expressions::types::Area,
|
||||||
|
types::{Border, Col, Fill, Font, Row, SheetData, Style, Worksheet},
|
||||||
|
worksheet::WorksheetDimension,
|
||||||
|
Model, UserModel,
|
||||||
},
|
},
|
||||||
export::save_xlsx_to_writer,
|
export::save_xlsx_to_writer,
|
||||||
import::load_from_xlsx,
|
import::load_from_xlsx,
|
||||||
@ -110,6 +113,7 @@ impl Book {
|
|||||||
self.model.evaluate();
|
self.model.evaluate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(zaphar): Should I support ICalc?
|
||||||
/// Construct a new book from a path.
|
/// Construct a new book from a path.
|
||||||
pub fn new_from_xlsx_with_locale(path: &str, locale: &str, tz: &str) -> Result<Self> {
|
pub fn new_from_xlsx_with_locale(path: &str, locale: &str, tz: &str) -> Result<Self> {
|
||||||
Ok(Self::from_model(load_from_xlsx(path, locale, tz)?))
|
Ok(Self::from_model(load_from_xlsx(path, locale, tz)?))
|
||||||
@ -140,19 +144,18 @@ impl Book {
|
|||||||
Ok(&self.get_sheet()?.name)
|
Ok(&self.get_sheet()?.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_sheet_name(&mut self, idx: u32, sheet_name: &str) -> Result<()> {
|
pub fn set_sheet_name(&mut self, idx: usize, sheet_name: &str) -> Result<()> {
|
||||||
self.model.rename_sheet(idx, sheet_name).map_err(|e| anyhow!(e))?;
|
self.get_sheet_by_idx_mut(idx)?.set_name(sheet_name);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_sheet(&mut self, sheet_name: Option<&str>) -> Result<()> {
|
pub fn new_sheet(&mut self, sheet_name: Option<&str>) -> Result<()> {
|
||||||
self.model.new_sheet().map_err(|e| anyhow!(e))?;
|
todo!("We need to figure out how to find the new sheet index so we can rename it");
|
||||||
let idx = self.model.get_selected_sheet();
|
//let (_, idx) = self.model.new_sheet();
|
||||||
if let Some(name) = sheet_name {
|
//if let Some(name) = sheet_name {
|
||||||
self.set_sheet_name(idx, name)?;
|
// self.set_sheet_name(idx as usize, name)?;
|
||||||
}
|
//}
|
||||||
self.model.set_selected_sheet(self.current_sheet).map_err(|e| anyhow!(e))?;
|
//Ok(())
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the sheet data for the current worksheet.
|
/// Get the sheet data for the current worksheet.
|
||||||
@ -179,8 +182,6 @@ impl Book {
|
|||||||
.skip(1)
|
.skip(1)
|
||||||
{
|
{
|
||||||
// TODO(jeremy): Is there a better way to do this using UserModel?
|
// TODO(jeremy): Is there a better way to do this using UserModel?
|
||||||
// Looks like this is the recommended way:
|
|
||||||
// https://docs.rs/ironcalc_base/latest/ironcalc_base/struct.UserModel.html#method.auto_fill_columns
|
|
||||||
let contents = self
|
let contents = self
|
||||||
.model
|
.model
|
||||||
.get_model()
|
.get_model()
|
||||||
@ -227,7 +228,13 @@ impl Book {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_cell_range(&mut self, sheet: u32, start: Address, end: Address) -> Result<()> {
|
pub fn clear_cell_range(&mut self, sheet: u32, start: Address, end: Address) -> Result<()> {
|
||||||
let area = calculate_area(sheet, start, end);
|
let area = Area {
|
||||||
|
sheet,
|
||||||
|
row: start.row as i32,
|
||||||
|
column: start.col as i32,
|
||||||
|
width: (end.row - start.row) as i32,
|
||||||
|
height: (end.col - end.row) as i32,
|
||||||
|
};
|
||||||
self.model
|
self.model
|
||||||
.range_clear_contents(&area)
|
.range_clear_contents(&area)
|
||||||
.map_err(|s| anyhow!("Unable to clear cell contents {}", s))?;
|
.map_err(|s| anyhow!("Unable to clear cell contents {}", s))?;
|
||||||
@ -248,7 +255,13 @@ impl Book {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear_cell_range_all(&mut self, sheet: u32, start: Address, end: Address) -> Result<()> {
|
pub fn clear_cell_range_all(&mut self, sheet: u32, start: Address, end: Address) -> Result<()> {
|
||||||
let area = calculate_area(sheet, start, end);
|
let area = Area {
|
||||||
|
sheet,
|
||||||
|
row: start.row as i32,
|
||||||
|
column: start.col as i32,
|
||||||
|
width: (end.row - start.row) as i32,
|
||||||
|
height: (end.col - end.row) as i32,
|
||||||
|
};
|
||||||
self.model.range_clear_all(&area)
|
self.model.range_clear_all(&area)
|
||||||
.map_err(|s| anyhow!("Unable to clear cell contents {}", s))?;
|
.map_err(|s| anyhow!("Unable to clear cell contents {}", s))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -334,15 +347,14 @@ impl Book {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_cell_style(&mut self, style: &[(&str, &str)], area: &Area) -> Result<()> {
|
pub fn set_cell_style(&mut self, style: &Style, sheet: u32, cell: &Address) -> Result<()> {
|
||||||
for (path, val) in style {
|
todo!()
|
||||||
self.model.update_range_style(area, path, val)
|
//self.model.set_cell_style(sheet, cell.row as i32, cell.col as i32, style)
|
||||||
.map_err(|s| anyhow!("Unable to format cell {}", s))?;
|
// .map_err(|s| anyhow!("Unable to format cell {}", s))?;
|
||||||
}
|
//Ok(())
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_col_style(&mut self, style: &[(&str, &str)], sheet: u32, col: usize) -> Result<()> {
|
pub fn set_col_style(&mut self, style: &Style, sheet: u32, col: usize) -> Result<()> {
|
||||||
todo!()
|
todo!()
|
||||||
//let idx = self.create_or_get_style_idx(style);
|
//let idx = self.create_or_get_style_idx(style);
|
||||||
//let sheet = self.model.workbook.worksheet_mut(sheet)
|
//let sheet = self.model.workbook.worksheet_mut(sheet)
|
||||||
@ -356,7 +368,7 @@ impl Book {
|
|||||||
//Ok(())
|
//Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_row_style(&mut self, style: &[(&str, &str)], sheet: u32, row: usize) -> Result<()> {
|
pub fn set_row_style(&mut self, style: &Style, sheet: u32, row: usize) -> Result<()> {
|
||||||
todo!()
|
todo!()
|
||||||
//let idx = self.create_or_get_style_idx(style);
|
//let idx = self.create_or_get_style_idx(style);
|
||||||
//self.model.workbook.worksheet_mut(sheet)
|
//self.model.workbook.worksheet_mut(sheet)
|
||||||
@ -396,21 +408,21 @@ impl Book {
|
|||||||
|
|
||||||
/// Update the current cell in a book.
|
/// Update the current cell in a book.
|
||||||
/// This update won't be reflected until you call `Book::evaluate`.
|
/// This update won't be reflected until you call `Book::evaluate`.
|
||||||
pub fn edit_current_cell<S: AsRef<str>>(&mut self, value: S) -> Result<()> {
|
pub fn edit_current_cell<S: Into<String>>(&mut self, value: S) -> Result<()> {
|
||||||
self.update_cell(&self.location.clone(), value)?;
|
self.update_cell(&self.location.clone(), value)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update an entry in the current sheet for a book.
|
/// Update an entry in the current sheet for a book.
|
||||||
/// This update won't be reflected until you call `Book::evaluate`.
|
/// This update won't be reflected until you call `Book::evaluate`.
|
||||||
pub fn update_cell<S: AsRef<str>>(&mut self, location: &Address, value: S) -> Result<()> {
|
pub fn update_cell<S: Into<String>>(&mut self, location: &Address, value: S) -> Result<()> {
|
||||||
self.model
|
self.model
|
||||||
.set_user_input(
|
.set_user_input(
|
||||||
self.current_sheet,
|
self.current_sheet,
|
||||||
location.row as i32,
|
location.row as i32,
|
||||||
location.col as i32,
|
location.col as i32,
|
||||||
// TODO(jwall): This could probably be made more efficient
|
// TODO(jwall): This could probably be made more efficient
|
||||||
value.as_ref(),
|
&value.into(),
|
||||||
)
|
)
|
||||||
.map_err(|e| anyhow!("Invalid cell contents: {}", e))?;
|
.map_err(|e| anyhow!("Invalid cell contents: {}", e))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -455,21 +467,16 @@ impl Book {
|
|||||||
|
|
||||||
/// Get column size
|
/// Get column size
|
||||||
pub fn get_col_size(&self, idx: usize) -> Result<usize> {
|
pub fn get_col_size(&self, idx: usize) -> Result<usize> {
|
||||||
self.get_column_size_for_sheet(self.current_sheet, idx)
|
Ok((self
|
||||||
}
|
.get_sheet()?
|
||||||
|
.get_column_width(idx as i32)
|
||||||
pub fn get_column_size_for_sheet(&self, sheet: u32, idx: usize) -> std::result::Result<usize, anyhow::Error> {
|
|
||||||
Ok((self.model.get_column_width(sheet, idx as i32)
|
|
||||||
.map_err(|e| anyhow!("Error getting column width: {:?}", e))?
|
.map_err(|e| anyhow!("Error getting column width: {:?}", e))?
|
||||||
/ COL_PIXELS) as usize)
|
/ COL_PIXELS) as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_col_size(&mut self, col: usize, width: usize) -> Result<()> {
|
pub fn set_col_size(&mut self, idx: usize, cols: usize) -> Result<()> {
|
||||||
self.set_column_size_for_sheet(self.current_sheet, col, width)
|
self.get_sheet_mut()?
|
||||||
}
|
.set_column_width(idx as i32, cols as f64 * COL_PIXELS)
|
||||||
|
|
||||||
pub fn set_column_size_for_sheet(&mut self, sheet: u32, col: usize, width: usize) -> std::result::Result<(), anyhow::Error> {
|
|
||||||
self.model.set_column_width(sheet, col as i32, width as f64 * COL_PIXELS)
|
|
||||||
.map_err(|e| anyhow!("Error setting column width: {:?}", e))?;
|
.map_err(|e| anyhow!("Error setting column width: {:?}", e))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -510,28 +517,29 @@ impl Book {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_next_sheet(&mut self) {
|
pub fn select_next_sheet(&mut self) {
|
||||||
|
// TODO(jwall): Is there a cleaner way to do this with UserModel?
|
||||||
let len = self.model.get_model().workbook.worksheets.len() as u32;
|
let len = self.model.get_model().workbook.worksheets.len() as u32;
|
||||||
let mut next = self.current_sheet + 1;
|
let mut next = self.current_sheet + 1;
|
||||||
if next == len {
|
if next == len {
|
||||||
next = 0;
|
next = 0;
|
||||||
}
|
}
|
||||||
self.model.set_selected_sheet(next).expect("Unexpected error selecting sheet");
|
|
||||||
self.current_sheet = next;
|
self.current_sheet = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn select_prev_sheet(&mut self) {
|
pub fn select_prev_sheet(&mut self) {
|
||||||
|
// TODO(jwall): Is there a cleaner way to do this with UserModel?
|
||||||
let len = self.model.get_model().workbook.worksheets.len() as u32;
|
let len = self.model.get_model().workbook.worksheets.len() as u32;
|
||||||
let next = if self.current_sheet == 0 {
|
let next = if self.current_sheet == 0 {
|
||||||
len - 1
|
len - 1
|
||||||
} else {
|
} else {
|
||||||
self.current_sheet - 1
|
self.current_sheet - 1
|
||||||
};
|
};
|
||||||
self.model.set_selected_sheet(next).expect("Unexpected error selecting sheet");
|
|
||||||
self.current_sheet = next;
|
self.current_sheet = next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Select a sheet by id.
|
/// Select a sheet by id.
|
||||||
pub fn select_sheet_by_id(&mut self, id: u32) -> bool {
|
pub fn select_sheet_by_id(&mut self, id: u32) -> bool {
|
||||||
|
// TODO(jwall): Is there a cleaner way to do this with UserModel?
|
||||||
if let Some((idx, _sheet)) = self
|
if let Some((idx, _sheet)) = self
|
||||||
.model.get_model()
|
.model.get_model()
|
||||||
.workbook
|
.workbook
|
||||||
@ -540,7 +548,6 @@ impl Book {
|
|||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|(_idx, sheet)| sheet.sheet_id == id)
|
.find(|(_idx, sheet)| sheet.sheet_id == id)
|
||||||
{
|
{
|
||||||
self.model.set_selected_sheet(idx as u32).expect("Unexpected error selecting sheet");
|
|
||||||
self.current_sheet = idx as u32;
|
self.current_sheet = idx as u32;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -550,8 +557,6 @@ impl Book {
|
|||||||
/// Get the current `Worksheet`.
|
/// Get the current `Worksheet`.
|
||||||
pub(crate) fn get_sheet(&self) -> Result<&Worksheet> {
|
pub(crate) fn get_sheet(&self) -> Result<&Worksheet> {
|
||||||
// TODO(jwall): Is there a cleaner way to do this with UserModel?
|
// TODO(jwall): Is there a cleaner way to do this with UserModel?
|
||||||
// Looks like it should be done with:
|
|
||||||
// https://docs.rs/ironcalc_base/latest/ironcalc_base/struct.UserModel.html#method.get_worksheets_properties
|
|
||||||
Ok(self
|
Ok(self
|
||||||
.model.get_model()
|
.model.get_model()
|
||||||
.workbook
|
.workbook
|
||||||
@ -559,10 +564,17 @@ impl Book {
|
|||||||
.map_err(|s| anyhow!("Invalid Worksheet id: {}: error: {}", self.current_sheet, s))?)
|
.map_err(|s| anyhow!("Invalid Worksheet id: {}: error: {}", self.current_sheet, s))?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_sheet_mut(&mut self) -> Result<&mut Worksheet> {
|
||||||
|
todo!("Is there a clean way to do this with UserModel?")
|
||||||
|
//Ok(self
|
||||||
|
// .model.get_model()
|
||||||
|
// .workbook
|
||||||
|
// .worksheet_mut(self.current_sheet)
|
||||||
|
// .map_err(|s| anyhow!("Invalid Worksheet: {}", s))?)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn get_sheet_name_by_idx(&self, idx: usize) -> Result<&str> {
|
pub(crate) fn get_sheet_name_by_idx(&self, idx: usize) -> Result<&str> {
|
||||||
// TODO(jwall): Is there a cleaner way to do this with UserModel?
|
// TODO(jwall): Is there a cleaner way to do this with UserModel?
|
||||||
// Looks like it should be done with:
|
|
||||||
// https://docs.rs/ironcalc_base/latest/ironcalc_base/struct.UserModel.html#method.get_worksheets_properties
|
|
||||||
Ok(&self
|
Ok(&self
|
||||||
.model.get_model()
|
.model.get_model()
|
||||||
.workbook
|
.workbook
|
||||||
@ -570,17 +582,14 @@ impl Book {
|
|||||||
.map_err(|s| anyhow!("Invalid Worksheet: {}", s))?
|
.map_err(|s| anyhow!("Invalid Worksheet: {}", s))?
|
||||||
.name)
|
.name)
|
||||||
}
|
}
|
||||||
}
|
pub(crate) fn get_sheet_by_idx_mut(&mut self, idx: usize) -> Result<&mut Worksheet> {
|
||||||
|
todo!("Is there a clean way to do this with UserModel?")
|
||||||
fn calculate_area(sheet: u32, start: Address, end: Address) -> Area {
|
//Ok(self
|
||||||
let area = Area {
|
// .model
|
||||||
sheet,
|
// .workbook
|
||||||
row: start.row as i32,
|
// .worksheet_mut(idx as u32)
|
||||||
column: start.col as i32,
|
// .map_err(|s| anyhow!("Invalid Worksheet: {}", s))?)
|
||||||
height: (end.row - start.row + 1) as i32,
|
}
|
||||||
width: (end.col - start.col + 1) as i32,
|
|
||||||
};
|
|
||||||
area
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Book {
|
impl Default for Book {
|
||||||
|
@ -5,7 +5,7 @@ use crate::book::{AddressRange, Book};
|
|||||||
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
use crossterm::event::{self, Event, KeyCode, KeyEventKind, KeyModifiers};
|
use crossterm::event::{self, Event, KeyCode, KeyEventKind, KeyModifiers};
|
||||||
use ironcalc::base::{expressions::types::Area, Model};
|
use ironcalc::base::Model;
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
buffer::Buffer,
|
buffer::Buffer,
|
||||||
layout::{Constraint, Flex, Layout},
|
layout::{Constraint, Flex, Layout},
|
||||||
@ -131,7 +131,7 @@ impl<'ws> AppState<'ws> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(jwall): Should we just be using `Area` for this?.
|
// TODO(jwall): This should probably move to a different module.
|
||||||
/// The Address in a Table.
|
/// The Address in a Table.
|
||||||
#[derive(Debug, PartialEq, PartialOrd, Ord, Eq, Clone)]
|
#[derive(Debug, PartialEq, PartialOrd, Ord, Eq, Clone)]
|
||||||
pub struct Address {
|
pub struct Address {
|
||||||
@ -445,11 +445,11 @@ impl<'ws> Workspace<'ws> {
|
|||||||
Ok(Some(Cmd::RenameSheet(idx, name))) => {
|
Ok(Some(Cmd::RenameSheet(idx, name))) => {
|
||||||
match idx {
|
match idx {
|
||||||
Some(idx) => {
|
Some(idx) => {
|
||||||
self.book.set_sheet_name(idx as u32, name)?;
|
self.book.set_sheet_name(idx, name)?;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
self.book
|
self.book
|
||||||
.set_sheet_name(self.book.current_sheet, name)?;
|
.set_sheet_name(self.book.current_sheet as usize, name)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
@ -469,7 +469,13 @@ impl<'ws> Workspace<'ws> {
|
|||||||
let row_count = _count.unwrap_or(1);
|
let row_count = _count.unwrap_or(1);
|
||||||
let row = self.book.location.row;
|
let row = self.book.location.row;
|
||||||
for r in row..(row+row_count) {
|
for r in row..(row+row_count) {
|
||||||
self.book.set_row_style(&[("fill.bg_color", color)], self.book.current_sheet, r)?;
|
let mut style = if let Some(style) = self.book.get_row_style(self.book.current_sheet, r)? {
|
||||||
|
style
|
||||||
|
} else {
|
||||||
|
self.book.create_style()
|
||||||
|
};
|
||||||
|
style.fill.bg_color = Some(color.to_string());
|
||||||
|
self.book.set_row_style(&style, self.book.current_sheet, r)?;
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
@ -477,31 +483,36 @@ impl<'ws> Workspace<'ws> {
|
|||||||
let col_count = _count.unwrap_or(1);
|
let col_count = _count.unwrap_or(1);
|
||||||
let col = self.book.location.col;
|
let col = self.book.location.col;
|
||||||
for c in col..(col+col_count) {
|
for c in col..(col+col_count) {
|
||||||
self.book.set_col_style(&[("fill.bg_color", color)], self.book.current_sheet, c)?;
|
let mut style = if let Some(style) = self.book.get_column_style(self.book.current_sheet, c)? {
|
||||||
|
style
|
||||||
|
} else {
|
||||||
|
self.book.create_style()
|
||||||
|
};
|
||||||
|
style.fill.bg_color = Some(color.to_string());
|
||||||
|
self.book.set_col_style(&style, self.book.current_sheet, c)?;
|
||||||
}
|
}
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
Ok(Some(Cmd::ColorCell(color))) => {
|
Ok(Some(Cmd::ColorCell(color))) => {
|
||||||
let sheet = self.book.current_sheet;
|
if let Some((start, end)) = self.state.range_select.get_range() {
|
||||||
let area = if let Some((start, end)) = self.state.range_select.get_range() {
|
for ri in start.row..=end.row {
|
||||||
Area {
|
for ci in start.col..=end.col {
|
||||||
sheet,
|
let address = Address { row: ri, col: ci };
|
||||||
row: start.row as i32,
|
let sheet = self.book.current_sheet;
|
||||||
column: start.col as i32,
|
let mut style = self.book.get_cell_style(sheet, &address)
|
||||||
width: (end.col - start.col) as i32,
|
.expect("I think this should be impossible.").clone();
|
||||||
height: (end.row - start.row) as i32
|
style.fill.bg_color = Some(color.to_string());
|
||||||
|
self.book.set_cell_style(&style, sheet, &address)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let address = self.book.location.clone();
|
let address = self.book.location.clone();
|
||||||
Area {
|
let sheet = self.book.current_sheet;
|
||||||
sheet,
|
let mut style = self.book.get_cell_style(sheet, &address)
|
||||||
row: address.row as i32,
|
.expect("I think this should be impossible.").clone();
|
||||||
column: address.col as i32,
|
style.fill.bg_color = Some(color.to_string());
|
||||||
width: 1,
|
self.book.set_cell_style(&style, sheet, &address)?;
|
||||||
height: 1
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
self.book.set_cell_style(&[("fill.bg_color", color)], &area)?;
|
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
@ -539,7 +550,7 @@ impl<'ws> Workspace<'ws> {
|
|||||||
self.handle_numeric_prefix(d);
|
self.handle_numeric_prefix(d);
|
||||||
}
|
}
|
||||||
KeyCode::Char('D') => {
|
KeyCode::Char('D') => {
|
||||||
if let Some((start, end)) = dbg!(self.state.range_select.get_range()) {
|
if let Some((start, end)) = self.state.range_select.get_range() {
|
||||||
self.book.clear_cell_range_all(
|
self.book.clear_cell_range_all(
|
||||||
self.state
|
self.state
|
||||||
.range_select
|
.range_select
|
||||||
@ -616,6 +627,7 @@ impl<'ws> Workspace<'ws> {
|
|||||||
.modifiers
|
.modifiers
|
||||||
.contains(KeyModifiers::CONTROL) =>
|
.contains(KeyModifiers::CONTROL) =>
|
||||||
{
|
{
|
||||||
|
// TODO(zaphar): Share the algorithm below between both copies
|
||||||
self.copy_range(true)?;
|
self.copy_range(true)?;
|
||||||
self.exit_range_select_mode()?;
|
self.exit_range_select_mode()?;
|
||||||
}
|
}
|
||||||
|
@ -248,6 +248,7 @@ pub(crate) fn map_color(color: Option<&String>, otherwise: Color) -> Color {
|
|||||||
candidate => {
|
candidate => {
|
||||||
// TODO(jeremy): Should we support more syntaxes than hex string?
|
// TODO(jeremy): Should we support more syntaxes than hex string?
|
||||||
// hsl(...) ??
|
// hsl(...) ??
|
||||||
|
// rgb(...) ??
|
||||||
if candidate.starts_with("#") {
|
if candidate.starts_with("#") {
|
||||||
if let Ok(rgb) = colorsys::Rgb::from_hex_str(candidate) {
|
if let Ok(rgb) = colorsys::Rgb::from_hex_str(candidate) {
|
||||||
// Note that the colorsys rgb model clamps the f64 values to no more
|
// Note that the colorsys rgb model clamps the f64 values to no more
|
||||||
|
Loading…
x
Reference in New Issue
Block a user