diff --git a/src/cmd_line.rs b/src/cmd_line.rs index 19ee4d4..a431cec 100644 --- a/src/cmd_line.rs +++ b/src/cmd_line.rs @@ -27,10 +27,38 @@ impl Level { //TODO: im //TODO: cursor + pub fn replace_from_ctx(&mut self, ctx: &CmdLineContext, render_state: &shell::RenderState) { + self.replace_line(&ctx.get_lines(), render_state, false); + } - pub fn append_line(&mut self, - content: &Vec, String)>>) { - let lines: Vec, Vec)>> = content + fn replace_line( + &mut self, + lines: &Vec, Vec)>>, + render_state: &shell::RenderState, + append: bool, + ) { + let &CellMetrics { + line_height, + char_width, + .. + } = render_state.font_ctx.cell_metrics(); + + let (columns, rows) = if append { + self.model_layout.layout_append(lines) + } else { + self.model_layout.layout(lines) + }; + + let columns = max(columns, 5); + + self.preferred_width = (char_width * columns as f64) as i32; + self.preferred_height = (line_height * rows as f64) as i32; + } + + fn to_attributed_content( + content: &Vec, String)>>, + ) -> Vec, Vec)>> { + content .iter() .map(|line_chars| { line_chars @@ -40,8 +68,7 @@ impl Level { }) .collect() }) - .collect(); - //TODO: implement + .collect() } pub fn from_multiline_content( @@ -49,23 +76,15 @@ impl Level { max_width: i32, render_state: &shell::RenderState, ) -> Self { - let lines: Vec, Vec)>> = content - .iter() - .map(|line_chars| { - line_chars - .iter() - .map(|c| { - (Some(Attrs::from_value_map(&c.0)), c.1.chars().collect()) - }) - .collect() - }) - .collect(); - - Level::from_lines(lines, max_width, render_state) + Level::from_lines( + &Level::to_attributed_content(content), + max_width, + render_state, + ) } pub fn from_lines( - lines: Vec, Vec)>>, + lines: &Vec, Vec)>>, max_width: i32, render_state: &shell::RenderState, ) -> Self { @@ -75,10 +94,10 @@ impl Level { .. } = render_state.font_ctx.cell_metrics(); - let max_width_chars = (max_width as f64 / char_width) as usize; + let max_width_chars = (max_width as f64 / char_width) as u64; - let mut model_layout = ModelLayout::new(); - let (columns, rows) = model_layout.layout(lines, max_width_chars); + let mut model_layout = ModelLayout::new(max_width_chars); + let (columns, rows) = model_layout.layout(lines); let columns = max(columns, 5); @@ -93,23 +112,7 @@ impl Level { } pub fn from_ctx(ctx: &CmdLineContext, render_state: &shell::RenderState) -> Self { - let content_line: Vec<(Option, Vec)> = ctx.content - .iter() - .map(|c| { - (Some(Attrs::from_value_map(&c.0)), c.1.chars().collect()) - }) - .collect(); - let prompt_lines = prompt_lines(&ctx.firstc, &ctx.prompt, ctx.indent); - - let mut content: Vec<_> = prompt_lines.into_iter().map(|line| vec![line]).collect(); - - if content.is_empty() { - content.push(content_line); - } else { - content.last_mut().map(|line| line.extend(content_line)); - } - - Level::from_lines(content, ctx.max_width, render_state) + Level::from_lines(&ctx.get_lines(), ctx.max_width, render_state) } fn update_cache(&mut self, render_state: &shell::RenderState) { @@ -194,20 +197,36 @@ impl CmdLine { pub fn show_level(&mut self, ctx: &CmdLineContext) { let mut state = self.state.borrow_mut(); - - let mut level = Level::from_ctx(ctx, &*state.render_state.borrow()); - level.update_cache(&*state.render_state.borrow()); - - // TODO: request size depends on leve size + block size - state - .drawing_area - .set_size_request(level.preferred_width, max(level.preferred_height, 40)); + let render_state = state.render_state.clone(); + let render_state = render_state.borrow(); if ctx.level_idx as usize == state.levels.len() { - // TODO: update level - state.levels.pop(); + state + .levels + .last_mut() + .unwrap() + .replace_from_ctx(ctx, &*render_state); + } else { + let level = Level::from_ctx(ctx, &*render_state); + state.levels.push(level); } - state.levels.push(level); + + + + let drawing_area = state.drawing_area.clone(); + let block_height = state + .block + .as_ref() + .map(|b| b.preferred_height) + .unwrap_or(0); + let level = state.levels.last_mut().unwrap(); + + level.update_cache(&*render_state); + drawing_area.set_size_request( + level.preferred_width, + max(block_height + level.preferred_height, 40), + ); + if !self.displyed { self.displyed = true; self.popover.set_pointing_to(>k::Rectangle { @@ -219,7 +238,7 @@ impl CmdLine { self.popover.popup(); } else { - state.drawing_area.queue_draw() + drawing_area.queue_draw() } } @@ -242,21 +261,25 @@ impl CmdLine { max_width: i32, ) { let mut state = self.state.borrow_mut(); - let mut block = Level::from_multiline_content(content, max_width, &*state.render_state.borrow()); + let mut block = + Level::from_multiline_content(content, max_width, &*state.render_state.borrow()); block.update_cache(&*state.render_state.borrow()); state.block = Some(block); + //TODO: drawing size update } - pub fn block_append( - &mut self, - content: &Vec, String)>>, - ) { + pub fn block_append(&mut self, content: &Vec, String)>>) { let mut state = self.state.borrow_mut(); let render_state = state.render_state.clone(); let block = state.block.as_mut().unwrap(); - block.append_line(content); - block.update_cache(& *render_state.borrow()); + block.replace_line( + &Level::to_attributed_content(content), + &*render_state.borrow(), + true, + ); + block.update_cache(&*render_state.borrow()); + //TODO: drawing size update } pub fn block_hide(&mut self) { @@ -280,6 +303,7 @@ fn gtk_draw( ctx.translate(0.0, gap as f64 / 2.0); } + //TODO: limit model to row filled render::render( ctx, cursor, @@ -305,3 +329,25 @@ pub struct CmdLineContext { pub height: i32, pub max_width: i32, } + +impl CmdLineContext { + fn get_lines(&self) -> Vec, Vec)>> { + let content_line: Vec<(Option, Vec)> = self.content + .iter() + .map(|c| { + (Some(Attrs::from_value_map(&c.0)), c.1.chars().collect()) + }) + .collect(); + let prompt_lines = prompt_lines(&self.firstc, &self.prompt, self.indent); + + let mut content: Vec<_> = prompt_lines.into_iter().map(|line| vec![line]).collect(); + + if content.is_empty() { + content.push(content_line); + } else { + content.last_mut().map(|line| line.extend(content_line)); + } + + content + } +} diff --git a/src/input.rs b/src/input.rs index b650258..e0785f1 100644 --- a/src/input.rs +++ b/src/input.rs @@ -5,8 +5,6 @@ use gdk::EventKey; use phf; use neovim_lib::{Neovim, NeovimApi}; -use std::ascii::AsciiExt; - include!(concat!(env!("OUT_DIR"), "/key_map_table.rs")); diff --git a/src/ui_model/model_layout.rs b/src/ui_model/model_layout.rs index 04a9b0d..5494865 100644 --- a/src/ui_model/model_layout.rs +++ b/src/ui_model/model_layout.rs @@ -6,21 +6,29 @@ pub struct ModelLayout { } impl ModelLayout { - const COLUMNS_STEP: usize = 50; const ROWS_STEP: usize = 10; - pub fn new() -> Self { + pub fn new(columns: u64) -> Self { ModelLayout { - model: UiModel::new(ModelLayout::ROWS_STEP as u64, ModelLayout::COLUMNS_STEP as u64), + model: UiModel::new(ModelLayout::ROWS_STEP as u64, columns), rows_filled: 0, } } - fn check_model_size(&mut self, rows: usize, columns: usize) { - if rows > self.model.rows || columns > self.model.columns { - let model_cols = - ((columns / ModelLayout::COLUMNS_STEP) + 1) * ModelLayout::COLUMNS_STEP; + pub fn layout_append(&mut self, lines: &Vec, Vec)>>) -> (usize, usize) { + let rows_filled = self.rows_filled; + self.layout_replace(rows_filled, lines) + } + pub fn layout(&mut self, + lines: &Vec, Vec)>>, + ) -> (usize, usize) { + self.layout_replace(0, lines) + } + + fn check_model_size(&mut self, rows: usize) { + if rows > self.model.rows { + let model_cols = self.model.columns; let model_rows = ((rows / ModelLayout::ROWS_STEP) + 1) * ModelLayout::ROWS_STEP; let mut model = UiModel::new(model_rows as u64, model_cols as u64); @@ -31,23 +39,23 @@ impl ModelLayout { /// Wrap all lines into model /// /// returns actual width - pub fn layout( + fn layout_replace( &mut self, - lines: Vec, Vec)>>, - max_columns: usize, + row_offset: usize, + lines: &Vec, Vec)>>, ) -> (usize, usize) { - let rows = ModelLayout::count_lines(&lines, max_columns); + let rows = ModelLayout::count_lines(&lines, self.model.columns); - self.check_model_size(rows, max_columns); - self.rows_filled = rows; + self.check_model_size(rows + row_offset); + self.rows_filled = rows + row_offset; let mut max_col_idx = 0; let mut col_idx = 0; - let mut row_idx = 0; + let mut row_idx = row_offset; for content in lines { - for (attr, ch_list) in content { + for &(ref attr, ref ch_list) in content { for ch in ch_list { - if col_idx >= max_columns { + if col_idx >= self.model.columns { col_idx = 0; row_idx += 1; } else { @@ -59,7 +67,7 @@ impl ModelLayout { } self.model.set_cursor(row_idx, col_idx as usize); - self.model.put(ch, false, attr.as_ref()); + self.model.put(*ch, false, attr.as_ref()); } } row_idx += 1;