Implement scrollbar
This commit is contained in:
parent
ee3cc21ece
commit
f9f7904117
3 changed files with 46 additions and 37 deletions
|
|
@ -199,9 +199,13 @@ impl cosmic::Application for App {
|
||||||
|
|
||||||
/// Creates a view after each update.
|
/// Creates a view after each update.
|
||||||
fn view(&self) -> Element<Self::Message> {
|
fn view(&self) -> Element<Self::Message> {
|
||||||
let cosmic_theme::Spacing { space_xxs, .. } = self.core().system_theme().cosmic().spacing;
|
let cosmic_theme::Spacing {
|
||||||
|
space_none,
|
||||||
|
space_xxs,
|
||||||
|
..
|
||||||
|
} = self.core().system_theme().cosmic().spacing;
|
||||||
|
|
||||||
let mut tab_column = widget::column::with_capacity(1);
|
let mut tab_column = widget::column::with_capacity(1).padding([space_none, space_xxs]);
|
||||||
|
|
||||||
tab_column = tab_column.push(
|
tab_column = tab_column.push(
|
||||||
row![
|
row![
|
||||||
|
|
|
||||||
|
|
@ -324,12 +324,24 @@ impl Terminal {
|
||||||
self.term.lock().scroll_display(scroll);
|
self.term.lock().scroll_display(scroll);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn scroll_to(&self, ratio: f32) {
|
||||||
|
let mut term = self.term.lock();
|
||||||
|
let grid = term.grid();
|
||||||
|
let total = grid.history_size() + grid.screen_lines();
|
||||||
|
let old_display_offset = grid.display_offset() as i32;
|
||||||
|
let new_display_offset =
|
||||||
|
((total as f32) * (1.0 - ratio)) as i32 - grid.screen_lines() as i32;
|
||||||
|
term.scroll_display(TerminalScroll::Delta(
|
||||||
|
new_display_offset - old_display_offset,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn scrollbar(&self) -> (f32, f32) {
|
pub fn scrollbar(&self) -> (f32, f32) {
|
||||||
let term = self.term.lock();
|
let term = self.term.lock();
|
||||||
let grid = term.grid();
|
let grid = term.grid();
|
||||||
let total = grid.history_size() + grid.screen_lines();
|
let total = grid.history_size() + grid.screen_lines();
|
||||||
let start = total - grid.display_offset();
|
let start = total - grid.display_offset() - grid.screen_lines();
|
||||||
let end = total - (grid.display_offset() + grid.screen_lines());
|
let end = total - grid.display_offset();
|
||||||
(
|
(
|
||||||
(start as f32) / (total as f32),
|
(start as f32) / (total as f32),
|
||||||
(end as f32) / (total as f32),
|
(end as f32) / (total as f32),
|
||||||
|
|
|
||||||
|
|
@ -188,10 +188,10 @@ where
|
||||||
let view_position =
|
let view_position =
|
||||||
layout.position() + [self.padding.left as f32, self.padding.top as f32].into();
|
layout.position() + [self.padding.left as f32, self.padding.top as f32].into();
|
||||||
let view_w = cmp::min(viewport.width as i32, layout.bounds().width as i32)
|
let view_w = cmp::min(viewport.width as i32, layout.bounds().width as i32)
|
||||||
- self.padding.horizontal() as i32;
|
- self.padding.horizontal() as i32
|
||||||
let view_h = cmp::min(viewport.height as i32, layout.bounds().height as i32)
|
|
||||||
- self.padding.vertical() as i32
|
|
||||||
- scrollbar_w as i32;
|
- scrollbar_w as i32;
|
||||||
|
let view_h = cmp::min(viewport.height as i32, layout.bounds().height as i32)
|
||||||
|
- self.padding.vertical() as i32;
|
||||||
let scale_factor = style.scale_factor as f32;
|
let scale_factor = style.scale_factor as f32;
|
||||||
|
|
||||||
if view_w <= 0 || view_h <= 0 {
|
if view_w <= 0 || view_h <= 0 {
|
||||||
|
|
@ -270,22 +270,24 @@ where
|
||||||
let (start, end) = terminal.scrollbar();
|
let (start, end) = terminal.scrollbar();
|
||||||
let scrollbar_y = start * view_h as f32;
|
let scrollbar_y = start * view_h as f32;
|
||||||
let scrollbar_h = end * view_h as f32 - scrollbar_y;
|
let scrollbar_h = end * view_h as f32 - scrollbar_y;
|
||||||
|
let scrollbar_rect = Rectangle::new(
|
||||||
|
[view_w as f32, scrollbar_y].into(),
|
||||||
|
Size::new(scrollbar_w, scrollbar_h),
|
||||||
|
);
|
||||||
let scrollbar_alpha = match &state.dragging {
|
let scrollbar_alpha = match &state.dragging {
|
||||||
Some(Dragging::Scrollbar { .. }) => 0.5,
|
Some(Dragging::Scrollbar { .. }) => 0.5,
|
||||||
_ => 0.25,
|
_ => 0.25,
|
||||||
};
|
};
|
||||||
renderer.fill_quad(
|
renderer.fill_quad(
|
||||||
Quad {
|
Quad {
|
||||||
bounds: Rectangle::new(
|
bounds: scrollbar_rect + Vector::new(view_position.x, view_position.y),
|
||||||
view_position + Vector::new(view_w as f32, scrollbar_y),
|
|
||||||
Size::new(scrollbar_w, scrollbar_h),
|
|
||||||
),
|
|
||||||
border_radius: 0.0.into(),
|
border_radius: 0.0.into(),
|
||||||
border_width: 0.0,
|
border_width: 0.0,
|
||||||
border_color: Color::TRANSPARENT,
|
border_color: Color::TRANSPARENT,
|
||||||
},
|
},
|
||||||
Color::new(1.0, 1.0, 1.0, scrollbar_alpha),
|
Color::new(1.0, 1.0, 1.0, scrollbar_alpha),
|
||||||
);
|
);
|
||||||
|
state.scrollbar_rect.set(scrollbar_rect);
|
||||||
|
|
||||||
let duration = instant.elapsed();
|
let duration = instant.elapsed();
|
||||||
log::debug!("redraw {}, {}: {:?}", view_w, view_h, duration);
|
log::debug!("redraw {}, {}: {:?}", view_w, view_h, duration);
|
||||||
|
|
@ -434,7 +436,6 @@ where
|
||||||
}
|
}
|
||||||
status = Status::Captured;
|
status = Status::Captured;
|
||||||
}
|
}
|
||||||
/*TODO
|
|
||||||
Event::Mouse(MouseEvent::ButtonPressed(button)) => {
|
Event::Mouse(MouseEvent::ButtonPressed(button)) => {
|
||||||
if let Some(p) = cursor_position.position_in(layout.bounds()) {
|
if let Some(p) = cursor_position.position_in(layout.bounds()) {
|
||||||
// Handle left click drag
|
// Handle left click drag
|
||||||
|
|
@ -458,6 +459,7 @@ where
|
||||||
} else {
|
} else {
|
||||||
ClickKind::Single
|
ClickKind::Single
|
||||||
};
|
};
|
||||||
|
/*TODO
|
||||||
match click_kind {
|
match click_kind {
|
||||||
ClickKind::Single => editor.action(Action::Click {
|
ClickKind::Single => editor.action(Action::Click {
|
||||||
x: x as i32,
|
x: x as i32,
|
||||||
|
|
@ -472,27 +474,22 @@ where
|
||||||
y: y as i32,
|
y: y as i32,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
state.click = Some((click_kind, Instant::now()));
|
state.click = Some((click_kind, Instant::now()));
|
||||||
state.dragging = Some(Dragging::Buffer);
|
state.dragging = Some(Dragging::Buffer);
|
||||||
} else if scrollbar_rect.contains(Point::new(x_logical, y_logical)) {
|
} else if scrollbar_rect.contains(Point::new(x_logical, y_logical)) {
|
||||||
state.dragging = Some(Dragging::Scrollbar {
|
state.dragging = Some(Dragging::Scrollbar {
|
||||||
start_y: y,
|
start_y: y,
|
||||||
start_scroll: editor.with_buffer(|buffer| buffer.scroll()),
|
start_scroll: terminal.scrollbar(),
|
||||||
});
|
});
|
||||||
} else if x_logical >= scrollbar_rect.x
|
} else if x_logical >= scrollbar_rect.x
|
||||||
&& x_logical < (scrollbar_rect.x + scrollbar_rect.width)
|
&& x_logical < (scrollbar_rect.x + scrollbar_rect.width)
|
||||||
{
|
{
|
||||||
editor.with_buffer_mut(|buffer| {
|
let scroll_ratio = terminal.with_buffer(|buffer| y / buffer.size().1);
|
||||||
let scroll_line =
|
terminal.scroll_to(scroll_ratio);
|
||||||
((y / buffer.size().1) * buffer.lines.len() as f32) as i32;
|
state.dragging = Some(Dragging::Scrollbar {
|
||||||
buffer.set_scroll(Scroll::new(
|
start_y: y,
|
||||||
scroll_line.try_into().unwrap_or_default(),
|
start_scroll: terminal.scrollbar(),
|
||||||
0,
|
|
||||||
));
|
|
||||||
state.dragging = Some(Dragging::Scrollbar {
|
|
||||||
start_y: y,
|
|
||||||
start_scroll: buffer.scroll(),
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -524,33 +521,26 @@ where
|
||||||
let y = y_logical * scale_factor;
|
let y = y_logical * scale_factor;
|
||||||
match dragging {
|
match dragging {
|
||||||
Dragging::Buffer => {
|
Dragging::Buffer => {
|
||||||
|
/*TODO
|
||||||
editor.action(Action::Drag {
|
editor.action(Action::Drag {
|
||||||
x: x as i32,
|
x: x as i32,
|
||||||
y: y as i32,
|
y: y as i32,
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
Dragging::Scrollbar {
|
Dragging::Scrollbar {
|
||||||
start_y,
|
start_y,
|
||||||
start_scroll,
|
start_scroll,
|
||||||
} => {
|
} => {
|
||||||
editor.with_buffer_mut(|buffer| {
|
let scroll_offset = terminal
|
||||||
let scroll_offset = (((y - start_y) / buffer.size().1)
|
.with_buffer(|buffer| ((y - start_y) / buffer.size().1));
|
||||||
* buffer.lines.len() as f32)
|
terminal.scroll_to(start_scroll.0 + scroll_offset);
|
||||||
as i32;
|
|
||||||
buffer.set_scroll(Scroll::new(
|
|
||||||
(start_scroll.line as i32 + scroll_offset)
|
|
||||||
.try_into()
|
|
||||||
.unwrap_or_default(),
|
|
||||||
0,
|
|
||||||
));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
status = Status::Captured;
|
status = Status::Captured;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
Event::Mouse(MouseEvent::WheelScrolled { delta }) => {
|
Event::Mouse(MouseEvent::WheelScrolled { delta }) => {
|
||||||
if let Some(_p) = cursor_position.position_in(layout.bounds()) {
|
if let Some(_p) = cursor_position.position_in(layout.bounds()) {
|
||||||
match delta {
|
match delta {
|
||||||
|
|
@ -610,7 +600,10 @@ enum ClickKind {
|
||||||
|
|
||||||
enum Dragging {
|
enum Dragging {
|
||||||
Buffer,
|
Buffer,
|
||||||
Scrollbar { start_y: f32, start_scroll: Scroll },
|
Scrollbar {
|
||||||
|
start_y: f32,
|
||||||
|
start_scroll: (f32, f32),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct State {
|
pub struct State {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue