use crate::render::rectangle::param::RectParam;
use crate::render::{RenderParam, WrcRender};
use crate::size::border::Border;
use crate::size::pos::Pos;
use crate::size::radius::Radius;
use crate::size::rect::Rect;
use crate::style::color::Color;
use crate::style::ClickStyle;
use crate::text::cchar::CChar;
use crate::ui::Ui;
use crate::widgets::textedit::buffer::CharBuffer;
use crate::Offset;
pub struct EditCursor {
pub(crate) min_pos: Pos,
pub(crate) max_pos: Pos,
pub(crate) horiz: usize,
pub(crate) vert: usize,
render: RenderParam<RectParam>,
pub(crate) offset: Offset,
line_height: f32,
pub(crate) changed: bool,
}
impl EditCursor {
pub fn new() -> EditCursor {
let mut cursor_style = ClickStyle::new();
cursor_style.fill.inactive = Color::rgb(0, 83, 125);
cursor_style.fill.hovered = Color::rgb(0, 83, 125);
cursor_style.fill.clicked = Color::rgb(0, 83, 125);
cursor_style.border.inactive = Border::new(0.0).radius(Radius::same(0));
cursor_style.border.hovered = Border::new(0.0).radius(Radius::same(0));
cursor_style.border.clicked = Border::new(0.0).radius(Radius::same(0));
EditCursor {
min_pos: Pos::new(),
max_pos: Pos::new(),
horiz: 0,
vert: 0,
render: RenderParam::new(RectParam::new(Rect::new(), cursor_style)),
offset: Offset::new(Pos::new()),
line_height: 0.0,
changed: false,
}
}
pub fn init(&mut self, cchar: &CharBuffer, ui: &mut Ui, init: bool) {
if init {
self.line_height = cchar.buffer.text.height;
self.vert = cchar.buffer.lines.len();
self.horiz = cchar.buffer.lines.last().unwrap().len();
}
self.render.init_rectangle(ui, false, false);
}
pub fn reset_x(&mut self, cchar: &CharBuffer) {
self.offset.x = cchar.buffer.lines[self.vert].get_width_in_char(self.horiz);
self.changed = true;
}
pub fn update(&mut self, ui: &mut Ui) {
if !self.changed { return; }
self.changed = false;
self.render.param.rect.offset(&self.offset);
self.render.update(ui, false, false);
}
pub fn render(&mut self, ui: &mut Ui) {
let pass = ui.pass.as_mut().unwrap();
ui.context.render.rectangle.render(&self.render, pass);
}
pub fn update_position(&mut self, ui: &mut Ui, rect: Rect, cchar: &CharBuffer) {
self.render.param.rect = rect;
self.render.param.rect.offset(&self.offset);
self.render.update(ui, false, false);
self.min_pos.x = cchar.buffer.rect.dx().min;
self.min_pos.y = cchar.buffer.rect.dy().min;
self.max_pos.x = cchar.buffer.rect.dx().max;
self.max_pos.y = cchar.buffer.rect.dy().max;
}
pub fn move_left(&mut self, cchar: &CharBuffer) {
println!("move left-{}-{}", self.horiz, self.vert);
if self.horiz == 0 && self.vert == 0 { return; }
if self.horiz == 0 {
self.vert -= 1;
self.horiz = cchar.buffer.lines[self.vert].len();
self.offset.y -= self.line_height;
self.offset.x = cchar.buffer.lines[self.vert].width + cchar.offset.x;
} else {
self.horiz -= 1;
self.offset.x = cchar.buffer.lines[self.vert].get_width_in_char(self.horiz) + cchar.offset.x;
}
self.changed = true;
}
pub fn delete_before(&mut self, cchar: &mut CharBuffer) -> CChar {
self.changed = true;
if self.horiz == 0 {
self.vert -= 1;
let line = &mut cchar.buffer.lines[self.vert];
self.horiz = if line.auto_wrap { line.chars.len() - 1 } else { line.chars.len() };
let c = if line.auto_wrap { line.chars.remove(self.horiz) } else { CChar::new('\n', 0.0) };
line.auto_wrap = true;
self.offset.x = line.width - c.width;
self.offset.y -= self.line_height;
c
} else {
let line = &mut cchar.buffer.lines[self.vert];
let c = line.chars.remove(self.horiz - 1);
cchar.offset.x += c.width;
if cchar.offset.x >= 0.0 { cchar.offset.x = 0.0; }
self.horiz -= 1;
self.offset.x = line.get_width_in_char(self.horiz) + cchar.offset.x;
c
}
}
pub fn delete_after(&mut self, cchar: &mut CharBuffer) -> CChar {
let len = cchar.buffer.lines.len();
let line = &mut cchar.buffer.lines[self.vert];
let c = if self.horiz == line.len() && self.vert < len {
let wrap = line.auto_wrap;
line.auto_wrap = true;
if wrap && self.vert + 1 < len { cchar.buffer.lines[self.vert + 1].chars.remove(0) } else { CChar::new('\n', 0.0) }
} else if self.horiz < line.len() {
let c = line.chars.remove(self.horiz);
cchar.offset.x += c.width;
if cchar.offset.x >= 0.0 { cchar.offset.x = 0.0; }
c
} else { CChar::new(' ', 0.0) };
self.changed = true;
c
}
pub fn move_right(&mut self, cchar: &CharBuffer) {
println!("move right-{}-{}", self.horiz, self.vert);
let line = &cchar.buffer.lines[self.vert];
if self.horiz == line.len() {
if self.vert == cchar.buffer.lines.len() - 1 { return; }
self.vert += 1;
self.horiz = 0;
self.offset.x = 0.0;
self.offset.y += self.line_height;
} else {
self.horiz += 1;
self.offset.x = line.get_width_in_char(self.horiz) + cchar.offset.x;
}
self.changed = true;
}
fn up_down_offset(&mut self, cchar: &CharBuffer) {
let line = &cchar.buffer.lines[self.vert];
let mut sum_width = 0.0;
self.horiz = 0;
for c in line.chars.iter() {
self.horiz += 1;
if self.offset.x < sum_width || self.offset.x > sum_width + c.width {
sum_width += c.width;
continue;
}
self.offset.x = if self.offset.x > sum_width + c.width / 2.0 { sum_width + c.width } else { sum_width };
self.changed = true;
break;
}
if self.offset.x == 0.0 {
self.horiz -= 1;
}
if self.horiz >= line.len() {
self.offset.x = line.width;
}
}
pub fn move_up(&mut self, cchar: &CharBuffer) {
if self.vert == 0 { return; }
self.vert -= 1;
self.up_down_offset(cchar);
println!("current cursor {}-{}", self.vert, self.horiz);
self.offset.y -= self.line_height;
self.changed = true;
}
pub fn move_down(&mut self, cchar: &CharBuffer) {
if self.vert == cchar.buffer.lines.len() - 1 { return; }
self.vert += 1;
self.up_down_offset(cchar);
println!("current cursor {} {}", self.vert, self.horiz);
self.offset.y += self.line_height;
self.changed = true;
}
pub fn update_by_pos(&mut self, pos: Pos, cchar: &mut CharBuffer) {
let clip_height = pos.y + cchar.offset.y - self.min_pos.y;
let mut line_index = (clip_height / self.line_height) as usize;
if line_index >= cchar.buffer.lines.len() { line_index = cchar.buffer.lines.len() - 1; }
self.vert = line_index;
let line = &cchar.buffer.lines[self.vert];
if pos.x > self.max_pos.x && self.min_pos.x + line.width > self.max_pos.x {
if self.horiz < line.len() {
self.horiz += 1;
let char = &line.chars[self.horiz - 1];
cchar.offset.x -= char.width;
self.offset.x = line.get_width_in_char(self.horiz) + cchar.offset.x;
} else {
self.horiz = line.len();
let mo = self.min_pos.x + line.width - self.max_pos.x;
cchar.offset.x = -mo;
self.offset.x = line.width + cchar.offset.x;
}
return;
} else if pos.x < self.min_pos.x && self.min_pos.x + line.width > self.max_pos.x {
if self.horiz > 0 { self.horiz -= 1; }
let char = &line.chars[self.horiz];
self.offset.x -= char.width;
if self.offset.x <= 0.0 { self.offset.x = 0.0; }
cchar.offset.x += char.width;
if cchar.offset.x >= 0.0 { cchar.offset.x = 0.0; }
return;
}
let mut sum_width = 0.0;
let mut horiz = 0;
let mut char_width = 0.0;
for cc in line.chars.iter() {
let char_min = self.min_pos.x + sum_width + cchar.offset.x;
let char_max = self.min_pos.x + sum_width + cchar.offset.x + cc.width;
if pos.x >= char_min && pos.x <= char_max {
char_width = cc.width;
break;
}
sum_width += cc.width;
horiz += 1;
}
let char_min = self.min_pos.x + sum_width + cchar.offset.x;
println!("{}-{}-{}-{}-{}", pos.x, self.min_pos.x, char_min + char_width / 2.0, horiz, sum_width);
if pos.x < self.min_pos.x {
self.horiz = 0;
self.offset.x = 0.0;
} else if pos.x > char_min + char_width / 2.0 {
if horiz >= line.len() { self.horiz = line.chars.len() } else { self.horiz = horiz + 1; }
self.offset.x = sum_width + char_width + cchar.offset.x;
} else {
self.horiz = horiz;
self.offset.x = sum_width + cchar.offset.x;
}
self.offset.y = self.line_height * line_index as f32;
if self.offset.x + self.min_pos.x > self.max_pos.x { self.offset.x = self.max_pos.x - self.min_pos.x; }
if self.offset.y + self.min_pos.y > self.max_pos.y { self.offset.y = self.max_pos.y - self.min_pos.y; }
println!("1111111111111111111111111111-{}-{}", self.vert, self.horiz);
self.changed = true;
}
pub fn cursor_min(&self) -> f32 {
self.min_pos.x + self.offset.x
}
pub fn set_cursor(&mut self, horiz: usize, vert: usize, cchar: &CharBuffer) {
println!("remove-cursor-{}-{}", horiz, vert);
self.horiz = horiz;
self.vert = vert;
self.offset.x = cchar.buffer.lines[vert].get_width_in_char(horiz) + cchar.offset.x;
self.offset.y = vert as f32 * self.line_height;
self.changed = true;
}
}