diff --git a/viewport/src/editor.rs b/viewport/src/editor.rs index 5454c6e..be36175 100644 --- a/viewport/src/editor.rs +++ b/viewport/src/editor.rs @@ -334,12 +334,6 @@ impl EditorState { } pub fn set_text(&mut self, text: &str) { - if text.is_empty() && !self.blocks.is_empty() { - // Swift sends empty text for untitled docs — keep initial content if present - if self.blocks.len() > 1 || !self.blocks[0].content.text().is_empty() { - return; - } - } if self.blocks.is_empty() { self.blocks = crate::blocks::parse_blocks(text); } else { @@ -412,12 +406,12 @@ impl EditorState { if self.focused_block >= self.blocks.len() { self.focused_block = self.blocks.len().saturating_sub(1); } - // If structure changed, try to restore cursor position if self.blocks.len() != old_count { if let Some(bi) = crate::blocks::block_at_line(&self.blocks, cursor.position.line) { self.focused_block = bi; } } + self.sync_table_states(); } #[allow(dead_code)] @@ -1025,6 +1019,7 @@ impl EditorState { } } + let mut global_line = 0usize; for (bi, block) in self.blocks.iter().enumerate() { match block.kind { BlockKind::Text => { @@ -1072,6 +1067,7 @@ impl EditorState { let gutter = Gutter { line_count: block.content.line_count(), source_line_count, + global_line_offset: 0, font_size: self.font_size, scroll_offset: self.scroll_offset, cursor_line: block.content.cursor().position.line, @@ -1137,6 +1133,7 @@ impl EditorState { let gutter = Gutter { line_count: block.content.line_count(), source_line_count, + global_line_offset: global_line, font_size: self.font_size, scroll_offset: self.scroll_offset, cursor_line: block.content.cursor().position.line, @@ -1144,6 +1141,7 @@ impl EditorState { result_mask, line_decors: decors, }; + global_line += source_line_count; let gw = gutter.gutter_width(); let gutter_canvas: Element<'_, Message, Theme, iced_wgpu::Renderer> = @@ -1171,9 +1169,11 @@ impl EditorState { block_elements.push( crate::heading_block::view(level, &block.heading_text, self.font_size) ); + global_line += 1; } BlockKind::HorizontalRule => { block_elements.push(crate::hr_block::view()); + global_line += 1; } BlockKind::Table => { if let Some(ts) = self.table_states.get(&block.id) { @@ -1184,11 +1184,13 @@ impl EditorState { ) ); } + global_line += block.line_count; } BlockKind::EvalResult => { block_elements.push( crate::eval_block::view::(&block.eval_text) ); + global_line += 1; } BlockKind::Tree => { if let Some(ref data) = block.tree_data { @@ -1196,6 +1198,7 @@ impl EditorState { crate::tree_block::view::(data) ); } + global_line += 1; } } } @@ -1208,10 +1211,12 @@ impl EditorState { } else if single_text_block { block_elements.remove(0) } else { - iced_widget::column(block_elements) - .width(Length::Fill) - .height(Length::Fill) - .into() + iced_widget::scrollable( + iced_widget::column(block_elements) + .width(Length::Fill) + ) + .height(Length::Fill) + .into() } } @@ -1450,6 +1455,7 @@ fn find_btn_style( struct Gutter { line_count: usize, source_line_count: usize, + global_line_offset: usize, font_size: f32, scroll_offset: f32, cursor_line: usize, @@ -1460,7 +1466,8 @@ struct Gutter { impl Gutter { fn gutter_width(&self) -> f32 { - let count = if self.source_line_count == 0 { 1 } else { self.source_line_count }; + let total = self.global_line_offset + self.source_line_count; + let count = if total == 0 { 1 } else { total }; let digits = (count as f32).log10().floor() as usize + 1; let char_width = self.font_size * 0.6; (digits.max(2) as f32 * char_width + 16.0).ceil() @@ -1493,7 +1500,7 @@ impl canvas::Program for Gutter { let gw = self.gutter_width(); - let mut source_num = 0usize; + let mut source_num = self.global_line_offset; for idx in 0..first_visible { if idx < self.result_mask.len() && !self.result_mask[idx] { source_num += 1;