Point to cursor
This commit is contained in:
parent
83061366dd
commit
c27fbff586
@ -11,31 +11,27 @@ use neovim_lib::Value;
|
|||||||
|
|
||||||
use ui_model::{Attrs, ModelLayout};
|
use ui_model::{Attrs, ModelLayout};
|
||||||
use ui::UiMutex;
|
use ui::UiMutex;
|
||||||
use render;
|
use render::{self, CellMetrics};
|
||||||
use shell;
|
use shell;
|
||||||
use cursor;
|
use cursor;
|
||||||
|
|
||||||
pub struct Level {
|
pub struct Level {
|
||||||
model_layout: ModelLayout,
|
model_layout: ModelLayout,
|
||||||
|
preferred_width: i32,
|
||||||
|
preferred_height: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Level {
|
impl Level {
|
||||||
|
|
||||||
pub fn from(
|
pub fn from(ctx: &CmdLineContext, render_state: &shell::RenderState) -> Self {
|
||||||
content: Vec<(HashMap<String, Value>, String)>,
|
//TODO: double width chars render, also note in text wrapping
|
||||||
pos: u64,
|
|
||||||
firstc: String,
|
|
||||||
prompt: String,
|
|
||||||
indent: u64,
|
|
||||||
) -> Self {
|
|
||||||
//TODO: double width chars
|
|
||||||
//TODO: im
|
//TODO: im
|
||||||
|
|
||||||
let content_line: Vec<(Option<Attrs>, Vec<char>)> = content
|
let content_line: Vec<(Option<Attrs>, Vec<char>)> = ctx.content
|
||||||
.iter()
|
.iter()
|
||||||
.map(|c| (Some(Attrs::from_value_map(&c.0)), c.1.chars().collect()))
|
.map(|c| (Some(Attrs::from_value_map(&c.0)), c.1.chars().collect()))
|
||||||
.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();
|
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));
|
content.last_mut().map(|line| line.extend(content_line));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut model_layout = ModelLayout::new();
|
let &CellMetrics {
|
||||||
// TODO: calculate width
|
line_height,
|
||||||
model_layout.layout(content, 5);
|
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) {
|
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() {
|
if !firstc.is_empty() {
|
||||||
vec![(None, firstc.chars().chain((0..indent).map(|_| ' ')).collect())]
|
vec![(None, firstc.chars().chain((0..indent).map(|_| ' ')).collect())]
|
||||||
} else if !prompt.is_empty() {
|
} else if !prompt.is_empty() {
|
||||||
@ -103,7 +108,7 @@ impl CmdLine {
|
|||||||
pub fn new(drawing: >k::DrawingArea, render_state: Rc<RefCell<shell::RenderState>>) -> Self {
|
pub fn new(drawing: >k::DrawingArea, render_state: Rc<RefCell<shell::RenderState>>) -> Self {
|
||||||
let popover = gtk::Popover::new(Some(drawing));
|
let popover = gtk::Popover::new(Some(drawing));
|
||||||
popover.set_modal(false);
|
popover.set_modal(false);
|
||||||
popover.set_position(gtk::PositionType::Top);
|
popover.set_position(gtk::PositionType::Right);
|
||||||
|
|
||||||
let edit_frame = gtk::Frame::new(None);
|
let edit_frame = gtk::Frame::new(None);
|
||||||
edit_frame.set_shadow_type(gtk::ShadowType::In);
|
edit_frame.set_shadow_type(gtk::ShadowType::In);
|
||||||
@ -131,31 +136,25 @@ impl CmdLine {
|
|||||||
|
|
||||||
pub fn show_level(
|
pub fn show_level(
|
||||||
&mut self,
|
&mut self,
|
||||||
content: Vec<(HashMap<String, Value>, String)>,
|
ctx: &CmdLineContext,
|
||||||
pos: u64,
|
|
||||||
firstc: String,
|
|
||||||
prompt: String,
|
|
||||||
indent: u64,
|
|
||||||
level_idx: u64,
|
|
||||||
) {
|
) {
|
||||||
let mut state = self.state.borrow_mut();
|
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());
|
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
|
// TODO: update level
|
||||||
state.levels.pop();
|
state.levels.pop();
|
||||||
}
|
}
|
||||||
state.levels.push(level);
|
state.levels.push(level);
|
||||||
if !self.displyed {
|
if !self.displyed {
|
||||||
self.displyed = true;
|
self.displyed = true;
|
||||||
let allocation = self.popover.get_relative_to().unwrap().get_allocation();
|
|
||||||
self.popover.set_pointing_to(>k::Rectangle {
|
self.popover.set_pointing_to(>k::Rectangle {
|
||||||
x: allocation.width / 2,
|
x: ctx.x,
|
||||||
y: allocation.height / 2,
|
y: ctx.y,
|
||||||
width: 1,
|
width: ctx.width,
|
||||||
height: 1,
|
height: ctx.height,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.popover.popup();
|
self.popover.popup();
|
||||||
@ -200,3 +199,17 @@ fn gtk_draw(
|
|||||||
}
|
}
|
||||||
Inhibit(false)
|
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,
|
||||||
|
}
|
||||||
|
21
src/shell.rs
21
src/shell.rs
@ -30,7 +30,7 @@ use cursor::{Cursor, CursorRedrawCb};
|
|||||||
use ui::UiMutex;
|
use ui::UiMutex;
|
||||||
use popup_menu::{self, PopupMenu};
|
use popup_menu::{self, PopupMenu};
|
||||||
use tabline::Tabline;
|
use tabline::Tabline;
|
||||||
use cmd_line::CmdLine;
|
use cmd_line::{CmdLine, CmdLineContext};
|
||||||
use error;
|
use error;
|
||||||
use mode;
|
use mode;
|
||||||
use render;
|
use render;
|
||||||
@ -1186,7 +1186,24 @@ impl RedrawEvents for State {
|
|||||||
indent: u64,
|
indent: u64,
|
||||||
level: u64,
|
level: u64,
|
||||||
) -> RepaintMode {
|
) -> 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
|
RepaintMode::Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,9 +13,11 @@ impl ModelLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Wrap all lines into model
|
/// 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 {
|
/// returns actual width
|
||||||
let model_cols = ((columns / ModelLayout::COLUMNS_STEP) + 1) *
|
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;
|
ModelLayout::COLUMNS_STEP;
|
||||||
let model_rows = ((lines.len() as u64 / ModelLayout::ROWS_STEP) + 1) *
|
let model_rows = ((lines.len() as u64 / ModelLayout::ROWS_STEP) + 1) *
|
||||||
ModelLayout::ROWS_STEP;
|
ModelLayout::ROWS_STEP;
|
||||||
@ -24,16 +26,21 @@ impl ModelLayout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let mut max_col_idx = 0;
|
||||||
let mut col_idx = 0;
|
let mut col_idx = 0;
|
||||||
let mut row_idx = 0;
|
let mut row_idx = 0;
|
||||||
for content in lines {
|
for content in lines {
|
||||||
for (attr, ch_list) in content {
|
for (attr, ch_list) in content {
|
||||||
for ch in ch_list {
|
for ch in ch_list {
|
||||||
if col_idx >= columns {
|
if col_idx >= max_columns {
|
||||||
col_idx = 0;
|
col_idx = 0;
|
||||||
row_idx += 1;
|
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.set_cursor(row_idx, col_idx as usize);
|
||||||
self.model.put(ch, false, attr.as_ref());
|
self.model.put(ch, false, attr.as_ref());
|
||||||
col_idx += 1;
|
col_idx += 1;
|
||||||
@ -41,5 +48,7 @@ impl ModelLayout {
|
|||||||
}
|
}
|
||||||
row_idx += 1;
|
row_idx += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(max_col_idx + 1, row_idx as u64)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user