use fluidattacks_designs_domain::icon::Style as IconStyle;
use fluidattacks_designs_domain::table::{
write_range, Page, ARROW_BG, ARROW_BORDER, ARROW_DISABLED_BG, ARROW_DISABLED_ICON, ARROW_GLYPH,
ARROW_HOVER_BG, ARROW_ICON, ARROW_PADDING, ARROW_RADIUS, BORDER_PX, FOOTER_GAP, FOOTER_PADDING,
NEXT_ICON, PREVIOUS_ICON, RANGE_TEXT_SIZE, RANGE_WEIGHT,
};
use fluidattacks_designs_domain::typography::FONT_PRIMARY;
use gpui::prelude::FluentBuilder as _;
use gpui::{
div, px, rgb, App, Div, Entity, FontWeight, InteractiveElement as _, ParentElement as _,
SharedString, Stateful, StatefulInteractiveElement as _, Styled as _,
};
use crate::icon::Icon;
use crate::table::state::{PageHandler, TableState};
use crate::theme::{ActiveTheme as _, Theme};
pub fn footer(state: &Entity<TableState>, on_page: &PageHandler, cx: &App) -> Div {
let read = state.read(cx);
let page = read.page();
let counts = read.page_counts();
div()
.flex()
.flex_none()
.items_center()
.gap(px(FOOTER_GAP))
.py(px(FOOTER_PADDING.0))
.px(px(FOOTER_PADDING.1))
.child(range_label(page, cx, state))
.child(crate::table::page_size::page_size(state, on_page, cx))
.child(
div()
.flex()
.items_center()
.gap(px(FOOTER_GAP))
.child(arrow(
state,
on_page,
PREVIOUS_ICON,
page.can_previous().then(|| page.previous()),
cx.theme(),
))
.child(arrow(
state,
on_page,
NEXT_ICON,
page.can_next(counts).then(|| page.next()),
cx.theme(),
)),
)
}
fn range_label(page: Page, cx: &App, state: &Entity<TableState>) -> Div {
let mut label = String::new();
if write_range(&mut label, page, state.read(cx).page_counts()).is_err() {
label.clear();
}
div()
.flex_none()
.font_family(FONT_PRIMARY)
.text_size(px(RANGE_TEXT_SIZE.px()))
.line_height(px(RANGE_TEXT_SIZE.line_height_px()))
.font_weight(FontWeight(f32::from(RANGE_WEIGHT.value())))
.child(SharedString::from(label))
}
fn arrow(
state: &Entity<TableState>,
on_page: &PageHandler,
glyph: &'static str,
target: Option<Page>,
theme: &Theme,
) -> Stateful<Div> {
let stepping = state.clone();
let handler = on_page.clone();
let enabled = target.is_some();
let hover_bg = theme.shade(ARROW_HOVER_BG);
div()
.id(crate::table::part(state, format!("page-{glyph}")))
.flex()
.flex_none()
.items_center()
.justify_center()
.py(px(ARROW_PADDING.0))
.px(px(ARROW_PADDING.1))
.rounded(px(ARROW_RADIUS))
.border(px(BORDER_PX))
.border_color(rgb(theme.shade(ARROW_BORDER)))
.map(|button| {
if enabled {
button
.bg(rgb(theme.shade(ARROW_BG)))
.cursor_pointer()
.hover(move |hovered| hovered.bg(rgb(hover_bg)))
} else {
button.bg(rgb(theme.shade(ARROW_DISABLED_BG)))
}
})
.child(
Icon::new(glyph)
.style(IconStyle::Light)
.size(ARROW_GLYPH)
.color(theme.shade(if enabled {
ARROW_ICON
} else {
ARROW_DISABLED_ICON
})),
)
.when_some(target, |button, page| {
button.on_click(move |_, _win, app| {
stepping.update(app, |table, inner| table.set_page(page, inner));
handler(page, app);
})
})
}