Point to cursor

This commit is contained in:
daa 2018-01-03 12:04:01 +03:00
parent 83061366dd
commit c27fbff586
3 changed files with 75 additions and 36 deletions

View File

@ -11,31 +11,27 @@ use neovim_lib::Value;
use ui_model::{Attrs, ModelLayout};
use ui::UiMutex;
use render;
use render::{self, CellMetrics};
use shell;
use cursor;
pub struct Level {
model_layout: ModelLayout,
preferred_width: i32,
preferred_height: i32,
}
impl Level {
pub fn from(
content: Vec<(HashMap<String, Value>, String)>,
pos: u64,
firstc: String,
prompt: String,
indent: u64,
) -> Self {
//TODO: double width chars
pub fn from(ctx: &CmdLineContext, render_state: &shell::RenderState) -> Self {
//TODO: double width chars render, also note in text wrapping
//TODO: im
let content_line: Vec<(Option<Attrs>, Vec<char>)> = content
let content_line: Vec<(Option<Attrs>, Vec<char>)> = ctx.content
.iter()
.map(|c| (Some(Attrs::from_value_map(&c.0)), c.1.chars().collect()))
.collect();
let prompt_lines = prompt_lines(firstc, prompt, indent);
let prompt_lines = prompt_lines(&ctx.firstc, &ctx.prompt, ctx.indent);
let mut content: Vec<_> = prompt_lines.into_iter().map(|line| vec![line]).collect();
@ -45,11 +41,20 @@ impl Level {
content.last_mut().map(|line| line.extend(content_line));
}
let mut model_layout = ModelLayout::new();
// TODO: calculate width
model_layout.layout(content, 5);
let &CellMetrics {
line_height,
char_width,
..
} = render_state.font_ctx.cell_metrics();
Level { model_layout }
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 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 }
}
fn update_cache(&mut self, render_state: &shell::RenderState) {
@ -61,7 +66,7 @@ impl Level {
}
}
fn prompt_lines(firstc: String, prompt: String, indent: u64) -> Vec<(Option<Attrs>, Vec<char>)> {
fn prompt_lines(firstc: &str, prompt: &str, indent: u64) -> Vec<(Option<Attrs>, Vec<char>)> {
if !firstc.is_empty() {
vec![(None, firstc.chars().chain((0..indent).map(|_| ' ')).collect())]
} else if !prompt.is_empty() {
@ -103,7 +108,7 @@ impl CmdLine {
pub fn new(drawing: &gtk::DrawingArea, render_state: Rc<RefCell<shell::RenderState>>) -> Self {
let popover = gtk::Popover::new(Some(drawing));
popover.set_modal(false);
popover.set_position(gtk::PositionType::Top);
popover.set_position(gtk::PositionType::Right);
let edit_frame = gtk::Frame::new(None);
edit_frame.set_shadow_type(gtk::ShadowType::In);
@ -131,31 +136,25 @@ impl CmdLine {
pub fn show_level(
&mut self,
content: Vec<(HashMap<String, Value>, String)>,
pos: u64,
firstc: String,
prompt: String,
indent: u64,
level_idx: u64,
ctx: &CmdLineContext,
) {
let mut state = self.state.borrow_mut();
let mut level = Level::from(content, pos, firstc, prompt, indent);
let mut level = Level::from(ctx, &*state.render_state.borrow());
level.update_cache(&*state.render_state.borrow());
if level_idx as usize == state.levels.len() {
if ctx.level_idx as usize == state.levels.len() {
// TODO: update level
state.levels.pop();
}
state.levels.push(level);
if !self.displyed {
self.displyed = true;
let allocation = self.popover.get_relative_to().unwrap().get_allocation();
self.popover.set_pointing_to(&gtk::Rectangle {
x: allocation.width / 2,
y: allocation.height / 2,
width: 1,
height: 1,
x: ctx.x,
y: ctx.y,
width: ctx.width,
height: ctx.height,
});
self.popover.popup();
@ -200,3 +199,17 @@ fn gtk_draw(
}
Inhibit(false)
}
pub struct CmdLineContext {
pub content: Vec<(HashMap<String, Value>, String)>,
pub pos: u64,
pub firstc: String,
pub prompt: String,
pub indent: u64,
pub level_idx: u64,
pub x: i32,
pub y: i32,
pub width: i32,
pub height: i32,
pub max_width: i32,
}

View File

@ -30,7 +30,7 @@ use cursor::{Cursor, CursorRedrawCb};
use ui::UiMutex;
use popup_menu::{self, PopupMenu};
use tabline::Tabline;
use cmd_line::CmdLine;
use cmd_line::{CmdLine, CmdLineContext};
use error;
use mode;
use render;
@ -1186,7 +1186,24 @@ impl RedrawEvents for State {
indent: u64,
level: u64,
) -> RepaintMode {
self.cmd_line.show_level(content, pos, firstc, prompt, indent, level);
let cursor = self.model.cur_point();
let render_state = self.render_state.borrow();
let (x, y, width, height) = cursor.to_area(render_state.font_ctx.cell_metrics());
let ctx = CmdLineContext {
content,
pos,
firstc,
prompt,
indent,
level_idx: level,
x,
y,
width,
height,
max_width: self.drawing_area.get_allocated_width() - 20,
};
self.cmd_line.show_level(&ctx);
RepaintMode::Nothing
}

View File

@ -13,9 +13,11 @@ impl ModelLayout {
}
/// Wrap all lines into model
pub fn layout(&mut self, lines: Vec<Vec<(Option<Attrs>, Vec<char>)>>, columns: u64) {
if lines.len() > self.model.rows || columns as usize > self.model.columns {
let model_cols = ((columns / ModelLayout::COLUMNS_STEP) + 1) *
///
/// returns actual width
pub fn layout(&mut self, lines: Vec<Vec<(Option<Attrs>, Vec<char>)>>, max_columns: u64) -> (u64, u64) {
if lines.len() > self.model.rows || max_columns as usize > self.model.columns {
let model_cols = ((max_columns / ModelLayout::COLUMNS_STEP) + 1) *
ModelLayout::COLUMNS_STEP;
let model_rows = ((lines.len() as u64 / ModelLayout::ROWS_STEP) + 1) *
ModelLayout::ROWS_STEP;
@ -24,16 +26,21 @@ impl ModelLayout {
}
let mut max_col_idx = 0;
let mut col_idx = 0;
let mut row_idx = 0;
for content in lines {
for (attr, ch_list) in content {
for ch in ch_list {
if col_idx >= columns {
if col_idx >= max_columns {
col_idx = 0;
row_idx += 1;
}
if max_col_idx < col_idx {
max_col_idx = col_idx;
}
self.model.set_cursor(row_idx, col_idx as usize);
self.model.put(ch, false, attr.as_ref());
col_idx += 1;
@ -41,5 +48,7 @@ impl ModelLayout {
}
row_idx += 1;
}
(max_col_idx + 1, row_idx as u64)
}
}