diff --git a/src/cmd_line.rs b/src/cmd_line.rs index 6be50ee..99c3871 100644 --- a/src/cmd_line.rs +++ b/src/cmd_line.rs @@ -23,11 +23,65 @@ pub struct Level { } impl Level { - pub fn from_ctx(ctx: &CmdLineContext, render_state: &shell::RenderState) -> Self { - //TODO: double width chars render, also note in text wrapping - //TODO: im - //TODO: cursor + //TODO: double width chars render, also note in text wrapping + //TODO: im + //TODO: cursor + + pub fn append_line(&mut self, + content: &Vec, String)>>) { + // TODO: implement + } + + pub fn from_multiline_content( + content: &Vec, String)>>, + 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) + } + + pub fn from_lines( + lines: Vec, Vec)>>, + max_width: i32, + render_state: &shell::RenderState, + ) -> Self { + let &CellMetrics { + line_height, + char_width, + .. + } = render_state.font_ctx.cell_metrics(); + + 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 columns = max(columns, 5); + + let preferred_width = (char_width * columns as f64) as i32; + let preferred_height = (line_height * rows as f64) as i32; + + Level { + model_layout, + preferred_width, + preferred_height, + } + } + + pub fn from_ctx(ctx: &CmdLineContext, render_state: &shell::RenderState) -> Self { let content_line: Vec<(Option, Vec)> = ctx.content .iter() .map(|c| { @@ -44,27 +98,7 @@ impl Level { content.last_mut().map(|line| line.extend(content_line)); } - let &CellMetrics { - line_height, - char_width, - .. - } = render_state.font_ctx.cell_metrics(); - - let max_width_chars = (ctx.max_width as f64 / char_width) as u64; - - let mut model_layout = ModelLayout::new(); - let (columns, rows) = model_layout.layout(content, max_width_chars); - - let columns = max(columns, 5); - - let preferred_width = (char_width * columns as f64) as i32; - let preferred_height = (line_height * rows as f64) as i32; - - Level { - model_layout, - preferred_width, - preferred_height, - } + Level::from_lines(content, ctx.max_width, render_state) } fn update_cache(&mut self, render_state: &shell::RenderState) { @@ -81,7 +115,7 @@ fn prompt_lines(firstc: &str, prompt: &str, indent: u64) -> Vec<(Option, vec![ ( None, - firstc.chars().chain((0..indent).map(|_| ' ')).collect() + firstc.chars().chain((0..indent).map(|_| ' ')).collect(), ), ] } else if !prompt.is_empty() { @@ -138,9 +172,7 @@ impl CmdLine { let weak_cb = Arc::downgrade(&state); let cursor = cursor::Cursor::new(weak_cb); - drawing_area.connect_draw( - clone!(state => move |_, ctx| gtk_draw(ctx, &state, &cursor)), - ); + drawing_area.connect_draw(clone!(state => move |_, ctx| gtk_draw(ctx, &state, &cursor))); CmdLine { popover, @@ -155,7 +187,10 @@ impl CmdLine { let mut level = Level::from_ctx(ctx, &*state.render_state.borrow()); level.update_cache(&*state.render_state.borrow()); - state.drawing_area.set_size_request(level.preferred_width, max(level.preferred_height, 40)); + // TODO: request size depends on leve size + block size + state + .drawing_area + .set_size_request(level.preferred_width, max(level.preferred_height, 40)); if ctx.level_idx as usize == state.levels.len() { // TODO: update level @@ -190,8 +225,31 @@ impl CmdLine { } } + pub fn show_block( + &mut self, + content: &Vec, String)>>, + max_width: i32, + ) { + let mut state = self.state.borrow_mut(); + 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); + } - pub fn show_block(&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()); + } + + pub fn block_hide(&mut self) { + self.state.borrow_mut().block = None; } } @@ -203,6 +261,7 @@ fn gtk_draw( let state = state.borrow(); let level = state.levels.last(); + //TODO: draw block if let Some(level) = level { let render_state = state.render_state.borrow(); let gap = state.drawing_area.get_allocated_height() - level.preferred_height; diff --git a/src/nvim/redraw_handler.rs b/src/nvim/redraw_handler.rs index 1b6883b..3db3da2 100644 --- a/src/nvim/redraw_handler.rs +++ b/src/nvim/redraw_handler.rs @@ -88,6 +88,8 @@ pub trait RedrawEvents { &mut self, content: Vec, String)>>, ) -> RepaintMode; + + fn cmdline_block_hide(&mut self) -> RepaintMode; } pub trait GuiApi { @@ -271,6 +273,7 @@ pub fn call( "cmdline_block_show" => call!(ui->cmdline_block_show(args: ext)), "cmdline_block_append" => call!(ui->cmdline_block_append(args: ext)), "cmdline_hide" => call!(ui->cmdline_hide(args: uint)), + "cmdline_block_hide" => ui.cmdline_block_hide(), _ => { println!("Event {}({:?})", method, args); RepaintMode::Nothing diff --git a/src/shell.rs b/src/shell.rs index b2fd4fb..2b94aed 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -391,6 +391,10 @@ impl State { } } + + fn max_popup_width(&self) -> i32 { + self.drawing_area.get_allocated_width() - 20 + } } pub struct UiState { @@ -1138,7 +1142,7 @@ impl RedrawEvents for State { y, width, height, - max_width: self.drawing_area.get_allocated_width() - 20, + max_width: self.max_popup_width(), }; self.popup_menu.show(context); @@ -1200,7 +1204,7 @@ impl RedrawEvents for State { y, width, height, - max_width: self.drawing_area.get_allocated_width() - 20, + max_width: self.max_popup_width(), }; self.cmd_line.show_level(&ctx); @@ -1216,7 +1220,8 @@ impl RedrawEvents for State { &mut self, content: Vec, String)>>, ) -> RepaintMode { - self.cmd_line.show_block(content); + let max_width = self.max_popup_width(); + self.cmd_line.show_block(&content, max_width); RepaintMode::Nothing } @@ -1224,6 +1229,12 @@ impl RedrawEvents for State { &mut self, content: Vec, String)>>, ) -> RepaintMode { + self.cmd_line.block_append(&content); + RepaintMode::Nothing + } + + fn cmdline_block_hide(&mut self) -> RepaintMode { + self.cmd_line.block_hide(); RepaintMode::Nothing } }