ScrollBars
Scrollbars are a set of components that are used to navigate through a control that has a large content. They are typically used in controls that handle a large amount of data, such as text editors, image viewers, and other controls that display a lot of information. Scrollbars are usually displayed only when the control has the focus and they are not visible when the control does not have the focus.
AppCUI provides a special structure (called ScrollBars) that can be used to create a set of scrollbars for a control. The ScrollBars structure is created by calling the ScrollBars::new method and it takes two parameters (the width and the height of the content to be displayed).
Scrollbars can only be used with controls that have a focus overlay. This means that the control must be created with the ControlBase::with_focus_overlay method.
Methods
The ScrollBars structure has the following methods:
| Method | Purpose |
|---|---|
paint(...) | Paints the scrollbars on the given surface and theme. |
process_mouse_event(...) | Processes a mouse event if it is triggered over the scrollbars and returns true in this case or false otherwise. It is a useful method to filter our scenarios where a mouse event should be pass to the parent control. |
should_repaint(...) | Returns true if the scrollbars should be repainted. |
horizontal_index() | Returns the current horizontal index of the scrollbars. |
vertical_index() | Returns the current vertical index of the scrollbars. |
offset() | Returns a point that represents from where in the current control with its current clippint the content should be drawn to the surface. This is useful when the control has a large content and it needs to be drawn in a specific area of the surface. |
set_indexes(...) | Sets the horizontal and vertical indexes of the scrollbars. |
resize(...) | Resizes the scrollbars to the given width and height. This method is often called when on_resize(...) trait from a custom control is being called. |
Usage
A typical usage of the ScrollBars structure would look like this:
-
Create a custom control (make sure it is created with
ControlBase::with_focus_overlaymethod) and add a scrollbars field to it:use appcui::prelude::*; #[CustomControl(overwrite = OnPaint+OnResize+OnMouseEvents+OnKeyPressed)] struct MyControl { sb: ScrollBars } impl MyControl { fn new(layout: Layout) -> Self { Self { base: ControlBase::with_focus_overlay(layout) sb: ScrollBars::new(/* content width */, /* contront height */), } } } -
The
on_paintmethod should look like this:impl OnPaint for MyControl { fn on_paint(&self, surface: &mut Surface, theme: &Theme) { if self.base.has_focus() { // draw the scrollbars self.sb.paint(surface, theme, self); // reduce the clip area to the size of the // control (without the overlay area) surface.reduce_clip_by(0, 0, 1, 1); } // draw the content of the control // you can use at this point the `self.sb.offset()` method to // get the offset from where the content should be drawn or // the self.sb.horizontal_index() and self.sb.vertical_index() // methods to get the current indexes and customize the drawing // of the content } } -
The
on_resizemethod should look like this:impl OnResize for MyControl { fn on_resize(&mut self, old_size: Size, new_size: Size) { self.sb.resize(/* content width */, /* content height */, &self.base); } }It is important to call the
resizemethod of the scrollbars in theon_resizemethod of the control. This will ensure that the scrollbars are resized to fit the new size of the control. -
The
on_mouse_eventmethod should look like this:impl OnMouseEvent for MyControl { fn on_mouse_event(&mut self, event: &MouseEvent) -> EventProcessStatus { // if the event can be processed by the scrollbars // then return if self.sb.process_mouse_event(event) { return EventProcessStatus::Processed; } match event { // process the event for the control } } } -
Aditionally, you can change the indexes manually (for example via an
OnKeyPressedevent) by using theself.sb.set_indexes(...)method. This is useful when you want to change the indexes of the scrollbars based on a specific event (e.g. a key pressed event).impl OnKeyPressed for Canvas { fn on_key_pressed(&mut self, key: Key, _character: char) -> EventProcessStatus { match key.value() { key!("Up") => { self.sb.set_indexes(self.sb.horizontal_index(), self.sb.vertical_index().saturating_sub(1)); return EventProcessStatus::Processed; } key!("Down") => { self.sb.set_indexes(self.sb.horizontal_index(), self.sb.vertical_index() + 1); return EventProcessStatus::Processed; } key!("Left") => { self.sb.set_indexes(self.sb.horizontal_index().saturating_sub(1), self.sb.vertical_index()); return EventProcessStatus::Processed; } key!("Right") => { self.sb.set_indexes(self.sb.horizontal_index() + 1, self.sb.vertical_index()); return EventProcessStatus::Processed; } // process other keys _ => {} } EventProcessStatus::Ignored } }
Scrollbar size
You can change the scrollbars size by using the ControlBase::set_components_toolbar_margins(left,top) method to specify:
- where on the X-axes (left parameter) the horizontal scrollbars should be drawn (relative to the control)
- where on the Y-axes (top parameter) the vertical scrollbars should be drawn (relative to the control)