Model

Struct Model 

Source
pub struct Model {
    pub paginator_type: Type,
    pub page: usize,
    pub per_page: usize,
    pub total_pages: usize,
    pub active_dot: String,
    pub inactive_dot: String,
    pub arabic_format: String,
    pub keymap: PaginatorKeyMap,
}
Expand description

A paginator model for handling pagination state and rendering.

This component manages pagination state including current page, total pages, and pagination display style. It can render pagination in two modes:

  • Arabic: Shows page numbers (e.g., “3/10”)
  • Dots: Shows dots representing pages (e.g., “○ ○ ● ○ ○”)

The paginator handles key bindings for navigation and provides helper methods for calculating slice bounds and page information.

§Examples

§Basic Usage

use bubbletea_widgets::paginator::{Model, Type};

let mut paginator = Model::new()
    .with_per_page(10)
    .with_total_items(150); // Creates 15 pages

assert_eq!(paginator.total_pages, 15);
assert!(paginator.on_first_page());

paginator.next_page();
assert_eq!(paginator.page, 1);

§Different Display Types

use bubbletea_widgets::paginator::{Model, Type};

let mut paginator = Model::new()
    .with_total_items(50)
    .with_per_page(10);

// Arabic mode (default): "1/5"
paginator.paginator_type = Type::Arabic;
let arabic_view = paginator.view();

// Dots mode: "● ○ ○ ○ ○"
paginator.paginator_type = Type::Dots;
let dots_view = paginator.view();

§Integration with bubbletea-rs

use bubbletea_widgets::paginator::Model as Paginator;
use bubbletea_rs::{Model, Cmd, Msg};

struct App {
    paginator: Paginator,
    items: Vec<String>,
}

impl Model for App {
    fn init() -> (Self, Option<Cmd>) {
        let items: Vec<String> = (1..=100).map(|i| format!("Item {}", i)).collect();
        let paginator = Paginator::new()
            .with_per_page(10)
            .with_total_items(items.len());
             
        (Self { paginator, items }, None)
    }

    fn update(&mut self, msg: Msg) -> Option<Cmd> {
        self.paginator.update(&msg);
        None
    }

    fn view(&self) -> String {
        let (start, end) = self.paginator.get_slice_bounds(self.items.len());
        let page_items: Vec<String> = self.items[start..end].to_vec();
         
        format!(
            "Items:\n{}\n\nPage: {}",
            page_items.join("\n"),
            self.paginator.view()
        )
    }
}

Fields§

§paginator_type: Type

The type of pagination to display (Dots or Arabic).

§page: usize

The current page.

§per_page: usize

The number of items per page.

§total_pages: usize

The total number of pages.

§active_dot: String

The character to use for the active page in Dots mode.

§inactive_dot: String

The character to use for inactive pages in Dots mode.

§arabic_format: String

The format string for Arabic mode (e.g., “%d/%d”).

§keymap: PaginatorKeyMap

Key bindings.

Implementations§

Source§

impl Model

Source

pub fn new() -> Self

Creates a new paginator model with default settings.

This is equivalent to calling Model::default() but provides a more conventional constructor-style API.

§Examples
use bubbletea_widgets::paginator::Model;

let paginator = Model::new();
assert_eq!(paginator.page, 0);
assert_eq!(paginator.total_pages, 1);
Source

pub fn with_total_items(self, items: usize) -> Self

Sets the total number of items and calculates total pages (builder pattern).

This method automatically calculates the total number of pages based on the total items and the current per_page setting. If the current page becomes out of bounds, it will be adjusted to the last valid page.

§Arguments
  • items - The total number of items to paginate
§Examples
use bubbletea_widgets::paginator::Model;

let paginator = Model::new()
    .with_per_page(10)
    .with_total_items(95); // Will create 10 pages (95/10 = 9.5 -> 10)

assert_eq!(paginator.total_pages, 10);
Source

pub fn with_per_page(self, per_page: usize) -> Self

Sets the number of items per page (builder pattern).

The minimum value is 1; any value less than 1 will be clamped to 1. This setting affects how total pages are calculated when using set_total_items() or with_total_items().

§Arguments
  • per_page - Number of items to display per page (minimum 1)
§Examples
use bubbletea_widgets::paginator::Model;

let paginator = Model::new()
    .with_per_page(25)
    .with_total_items(100); // Will create 4 pages

assert_eq!(paginator.per_page, 25);
assert_eq!(paginator.total_pages, 4);

// Values less than 1 are clamped to 1
let clamped = Model::new().with_per_page(0);
assert_eq!(clamped.per_page, 1);
Source

pub fn set_per_page(&mut self, per_page: usize)

Sets the number of items per page (mutable version).

The minimum value is 1; any value less than 1 will be clamped to 1. This method modifies the paginator in place.

§Arguments
  • per_page - Number of items to display per page (minimum 1)
§Examples
use bubbletea_widgets::paginator::Model;

let mut paginator = Model::new();
paginator.set_per_page(15);
assert_eq!(paginator.per_page, 15);

// Values less than 1 are clamped to 1
paginator.set_per_page(0);
assert_eq!(paginator.per_page, 1);
Source

pub fn with_active_dot(self, dot: &str) -> Self

Sets the active dot character for dots mode (builder pattern).

§Arguments
  • dot - The character or styled string to use for the active page
§Examples
use bubbletea_widgets::paginator::Model;

let paginator = Model::new().with_active_dot("●");
assert_eq!(paginator.active_dot, "●");
Source

pub fn with_inactive_dot(self, dot: &str) -> Self

Sets the inactive dot character for dots mode (builder pattern).

§Arguments
  • dot - The character or styled string to use for inactive pages
§Examples
use bubbletea_widgets::paginator::Model;

let paginator = Model::new().with_inactive_dot("○");
assert_eq!(paginator.inactive_dot, "○");
Source

pub fn set_active_dot(&mut self, dot: &str)

Sets the active dot character for dots mode (mutable version).

§Arguments
  • dot - The character or styled string to use for the active page
§Examples
use bubbletea_widgets::paginator::Model;

let mut paginator = Model::new();
paginator.set_active_dot("●");
assert_eq!(paginator.active_dot, "●");
Source

pub fn set_inactive_dot(&mut self, dot: &str)

Sets the inactive dot character for dots mode (mutable version).

§Arguments
  • dot - The character or styled string to use for inactive pages
§Examples
use bubbletea_widgets::paginator::Model;

let mut paginator = Model::new();
paginator.set_inactive_dot("○");
assert_eq!(paginator.inactive_dot, "○");
Source

pub fn set_total_pages(&mut self, pages: usize)

Sets the total number of pages directly.

The minimum value is 1; any value less than 1 will be clamped to 1. If the current page becomes out of bounds after setting the total pages, it will be adjusted to the last valid page.

Note: This method sets pages directly. If you want to calculate pages based on total items, use set_total_items() instead.

§Arguments
  • pages - The total number of pages (minimum 1)
§Examples
use bubbletea_widgets::paginator::Model;

let mut paginator = Model::new();
paginator.set_total_pages(10);
assert_eq!(paginator.total_pages, 10);

// If current page is out of bounds, it gets adjusted
paginator.page = 15; // Out of bounds
paginator.set_total_pages(5);
assert_eq!(paginator.page, 4); // Adjusted to last page (0-indexed)
Source

pub fn set_total_items(&mut self, items: usize)

Calculates and sets the total number of pages based on the total items.

This method divides the total number of items by the current per_page setting to calculate the total pages. The result is always at least 1, even for 0 items. If the current page becomes out of bounds after recalculation, it will be adjusted to the last valid page.

§Arguments
  • items - The total number of items to paginate
§Examples
use bubbletea_widgets::paginator::Model;

let mut paginator = Model::new().with_per_page(10);

// 95 items with 10 per page = 10 pages (95/10 = 9.5 -> 10)
paginator.set_total_items(95);
assert_eq!(paginator.total_pages, 10);

// 0 items still results in 1 page minimum
paginator.set_total_items(0);
assert_eq!(paginator.total_pages, 1);

// Exact division
paginator.set_total_items(100);
assert_eq!(paginator.total_pages, 10);
Source

pub fn items_on_page(&self, total_items: usize) -> usize

Returns the number of items on the current page.

This method calculates how many items are actually present on the current page, which may be less than per_page on the last page or when there are fewer total items than per_page.

§Arguments
  • total_items - The total number of items being paginated
§Returns

The number of items on the current page, or 0 if there are no items.

§Examples
use bubbletea_widgets::paginator::Model;

let mut paginator = Model::new().with_per_page(10);

// Full page
assert_eq!(paginator.items_on_page(100), 10);

// Partial last page
paginator.page = 9; // Last page (0-indexed)
assert_eq!(paginator.items_on_page(95), 5); // Only 5 items on page 10

// No items
assert_eq!(paginator.items_on_page(0), 0);
Source

pub fn get_slice_bounds(&self, length: usize) -> (usize, usize)

Calculates slice bounds for the current page.

This is a helper function for paginating slices. Given the total length of your data, it returns the start and end indices for the current page. The returned bounds can be used directly with slice notation.

§Arguments
  • length - The total length of the data being paginated
§Returns

A tuple (start, end) where:

  • start is the inclusive start index for the current page
  • end is the exclusive end index for the current page
§Examples
use bubbletea_widgets::paginator::Model;

let items: Vec<i32> = (1..=100).collect();
let mut paginator = Model::new().with_per_page(10);

// First page (0)
let (start, end) = paginator.get_slice_bounds(items.len());
assert_eq!((start, end), (0, 10));
let page_items = &items[start..end]; // Items 1-10

// Third page (2)
paginator.page = 2;
let (start, end) = paginator.get_slice_bounds(items.len());
assert_eq!((start, end), (20, 30));
let page_items = &items[start..end]; // Items 21-30
Source

pub fn start_index_end_index(&self) -> (usize, usize)

Returns slice bounds assuming maximum possible data length.

This is a convenience method that calls get_slice_bounds() with the maximum possible data length (per_page * total_pages). It’s useful when you know your data exactly fills the pagination structure.

§Returns

A tuple (start, end) representing slice bounds for the current page.

§Examples
use bubbletea_widgets::paginator::Model;

let mut paginator = Model::new()
    .with_per_page(10)
    .with_total_items(100); // Exactly 10 pages

paginator.page = 3;
let (start, end) = paginator.start_index_end_index();
assert_eq!((start, end), (30, 40));
Source

pub fn prev_page(&mut self)

Navigates to the previous page.

If the paginator is already on the first page (page 0), this method has no effect. The page number will not go below 0.

§Examples
use bubbletea_widgets::paginator::Model;

let mut paginator = Model::new().with_per_page(10).with_total_items(100);
paginator.page = 5;

paginator.prev_page();
assert_eq!(paginator.page, 4);

// Won't go below 0
paginator.page = 0;
paginator.prev_page();
assert_eq!(paginator.page, 0);
Source

pub fn next_page(&mut self)

Navigates to the next page.

If the paginator is already on the last page, this method has no effect. The page number will not exceed total_pages - 1.

§Examples
use bubbletea_widgets::paginator::Model;

let mut paginator = Model::new().with_per_page(10).with_total_items(100);
// total_pages = 10, so last page is 9 (0-indexed)

paginator.page = 5;
paginator.next_page();
assert_eq!(paginator.page, 6);

// Won't go beyond last page  
paginator.page = 8; // Second to last page
paginator.next_page();
assert_eq!(paginator.page, 9); // Should go to last page (9 is the last valid page)
paginator.next_page();
assert_eq!(paginator.page, 9); // Should stay at last page
Source

pub fn on_first_page(&self) -> bool

Returns true if the paginator is on the first page.

The first page is always page 0 in the 0-indexed pagination system.

§Examples
use bubbletea_widgets::paginator::Model;

let mut paginator = Model::new().with_per_page(10).with_total_items(100);

assert!(paginator.on_first_page());

paginator.next_page();
assert!(!paginator.on_first_page());
Source

pub fn on_last_page(&self) -> bool

Returns true if the paginator is on the last page.

The last page is total_pages - 1 in the 0-indexed pagination system.

§Examples
use bubbletea_widgets::paginator::Model;

let mut paginator = Model::new().with_per_page(10).with_total_items(90);
// Creates 9 pages (0-8), so last page is 8

assert!(!paginator.on_last_page());

paginator.page = 8; // Last page  
assert!(paginator.on_last_page());
Source

pub fn update(&mut self, msg: &Msg)

Updates the paginator based on received messages.

This method should be called from your application’s update() method to handle pagination key presses. It automatically responds to the configured key bindings for next/previous page navigation.

§Arguments
  • msg - The message to process, typically containing key press events
§Examples
use bubbletea_widgets::paginator::Model as Paginator;
use bubbletea_rs::{Model, Msg};

struct App {
    paginator: Paginator,
}

impl Model for App {
    fn update(&mut self, msg: Msg) -> Option<bubbletea_rs::Cmd> {
        // Forward messages to paginator
        self.paginator.update(&msg);
        None
    }
     
    // ... other methods
}
Source

pub fn view(&self) -> String

Renders the paginator as a string.

The output format depends on the paginator_type setting:

  • Arabic: Shows “current/total” (e.g., “3/10”)
  • Dots: Shows dots with active page highlighted (e.g., “○ ○ ● ○ ○”)
§Returns

A string representation of the current pagination state.

§Examples
use bubbletea_widgets::paginator::{Model, Type};

let mut paginator = Model::new().with_per_page(10).with_total_items(50);
// Creates 5 pages, currently on page 0

// Arabic mode (default)
paginator.paginator_type = Type::Arabic;
assert_eq!(paginator.view(), "1/5"); // 1-indexed for display

// Dots mode  
paginator.paginator_type = Type::Dots;
assert_eq!(paginator.view(), "•○○○○"); // Active page shows filled bullet, others are hollow

// Move to page 2
paginator.page = 2;
assert_eq!(paginator.view(), "○○•○○"); // Third bullet filled (active page), others hollow

Trait Implementations§

Source§

impl Clone for Model

Source§

fn clone(&self) -> Model

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Model

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Model

Source§

fn default() -> Self

Creates a paginator with default settings.

Default configuration:

  • Type: Arabic (“1/5” style)
  • Current page: 0 (first page)
  • Items per page: 1
  • Total pages: 1
  • Active dot: “•” (for dots mode)
  • Inactive dot: “○” (for dots mode)
  • Arabic format: “%d/%d” (current/total)
  • Default key bindings
§Examples
use bubbletea_widgets::paginator::{Model, Type};

let paginator = Model::default();
assert_eq!(paginator.paginator_type, Type::Arabic);
assert_eq!(paginator.page, 0);
assert_eq!(paginator.per_page, 1);
assert_eq!(paginator.total_pages, 1);

Auto Trait Implementations§

§

impl Freeze for Model

§

impl RefUnwindSafe for Model

§

impl Send for Model

§

impl Sync for Model

§

impl Unpin for Model

§

impl UnwindSafe for Model

Blanket Implementations§

Source§

impl<S, D, Swp, Dwp, T> AdaptInto<D, Swp, Dwp, T> for S
where T: Real + Zero + Arithmetics + Clone, Swp: WhitePoint<T>, Dwp: WhitePoint<T>, D: AdaptFrom<S, Swp, Dwp, T>,

Source§

fn adapt_into_using<M>(self, method: M) -> D
where M: TransformMatrix<T>,

Convert the source color to the destination color using the specified method.
Source§

fn adapt_into(self) -> D

Convert the source color to the destination color using the bradford method by default.
Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T, C> ArraysFrom<C> for T
where C: IntoArrays<T>,

Source§

fn arrays_from(colors: C) -> T

Cast a collection of colors into a collection of arrays.
Source§

impl<T, C> ArraysInto<C> for T
where C: FromArrays<T>,

Source§

fn arrays_into(self) -> C

Cast this collection of arrays into a collection of colors.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<WpParam, T, U> Cam16IntoUnclamped<WpParam, T> for U
where T: FromCam16Unclamped<WpParam, U>,

Source§

type Scalar = <T as FromCam16Unclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn cam16_into_unclamped( self, parameters: BakedParameters<WpParam, <U as Cam16IntoUnclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T, C> ComponentsFrom<C> for T
where C: IntoComponents<T>,

Source§

fn components_from(colors: C) -> T

Cast a collection of colors into a collection of color components.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromAngle<T> for T

Source§

fn from_angle(angle: T) -> T

Performs a conversion from angle.
Source§

impl<T, U> FromStimulus<U> for T
where U: IntoStimulus<T>,

Source§

fn from_stimulus(other: U) -> T

Converts other into Self, while performing the appropriate scaling, rounding and clamping.
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> IntoAngle<U> for T
where U: FromAngle<T>,

Source§

fn into_angle(self) -> U

Performs a conversion into T.
Source§

impl<WpParam, T, U> IntoCam16Unclamped<WpParam, T> for U
where T: Cam16FromUnclamped<WpParam, U>,

Source§

type Scalar = <T as Cam16FromUnclamped<WpParam, U>>::Scalar

The number type that’s used in parameters when converting.
Source§

fn into_cam16_unclamped( self, parameters: BakedParameters<WpParam, <U as IntoCam16Unclamped<WpParam, T>>::Scalar>, ) -> T

Converts self into C, using the provided parameters.
Source§

impl<T, U> IntoColor<U> for T
where U: FromColor<T>,

Source§

fn into_color(self) -> U

Convert into T with values clamped to the color defined bounds Read more
Source§

impl<T, U> IntoColorUnclamped<U> for T
where U: FromColorUnclamped<T>,

Source§

fn into_color_unclamped(self) -> U

Convert into T. The resulting color might be invalid in its color space Read more
Source§

impl<T> IntoStimulus<T> for T

Source§

fn into_stimulus(self) -> T

Converts self into T, while performing the appropriate scaling, rounding and clamping.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, C> TryComponentsInto<C> for T
where C: TryFromComponents<T>,

Source§

type Error = <C as TryFromComponents<T>>::Error

The error for when try_into_colors fails to cast.
Source§

fn try_components_into(self) -> Result<C, <T as TryComponentsInto<C>>::Error>

Try to cast this collection of color components into a collection of colors. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T, U> TryIntoColor<U> for T
where U: TryFromColor<T>,

Source§

fn try_into_color(self) -> Result<U, OutOfBounds<U>>

Convert into T, returning ok if the color is inside of its defined range, otherwise an OutOfBounds error is returned which contains the unclamped color. Read more
Source§

impl<C, U> UintsFrom<C> for U
where C: IntoUints<U>,

Source§

fn uints_from(colors: C) -> U

Cast a collection of colors into a collection of unsigned integers.
Source§

impl<C, U> UintsInto<C> for U
where C: FromUints<U>,

Source§

fn uints_into(self) -> C

Cast this collection of unsigned integers into a collection of colors.