use crate::render::RenderContext;
use crate::types::Rect;
use super::style::{
BorderedContainerStyle, CardContainerStyle, ClippingContainerStyle, ContainerStyle,
PanelContainerStyle, PlainContainerStyle, SectionContainerStyle,
};
use super::theme::ContainerTheme;
use super::types::{ContainerType, PanelRole};
pub fn draw_plain_container(
ctx: &mut dyn RenderContext,
rect: Rect,
theme: &dyn ContainerTheme,
_style: &PlainContainerStyle,
) {
ctx.set_fill_color(theme.bg());
ctx.fill_rect(rect.x, rect.y, rect.width, rect.height);
}
pub fn draw_bordered_container(
ctx: &mut dyn RenderContext,
rect: Rect,
theme: &dyn ContainerTheme,
style: &BorderedContainerStyle,
) {
ctx.set_fill_color(theme.bg());
ctx.fill_rounded_rect(rect.x, rect.y, rect.width, rect.height, style.radius());
ctx.set_stroke_color(theme.border());
ctx.set_stroke_width(style.border_width());
ctx.stroke_rounded_rect(rect.x, rect.y, rect.width, rect.height, style.radius());
}
pub fn draw_card_container(
ctx: &mut dyn RenderContext,
rect: Rect,
theme: &dyn ContainerTheme,
style: &CardContainerStyle,
) {
let (sx, sy) = style.shadow_offset();
ctx.set_fill_color_alpha(theme.card_shadow_color(), style.shadow_alpha());
ctx.fill_rounded_rect(
rect.x + sx,
rect.y + sy,
rect.width,
rect.height,
style.radius(),
);
ctx.reset_alpha();
ctx.set_fill_color(theme.bg());
if style.radius() > 0.0 {
ctx.fill_rounded_rect(rect.x, rect.y, rect.width, rect.height, style.radius());
} else {
ctx.fill_rect(rect.x, rect.y, rect.width, rect.height);
}
ctx.set_stroke_color(theme.border());
ctx.set_stroke_width(1.0);
if style.radius() > 0.0 {
ctx.stroke_rounded_rect(rect.x, rect.y, rect.width, rect.height, style.radius());
} else {
ctx.stroke_rect(rect.x, rect.y, rect.width, rect.height);
}
}
pub fn begin_clipping_container(
ctx: &mut dyn RenderContext,
rect: Rect,
style: &ClippingContainerStyle,
) {
if style.clipping {
ctx.save();
ctx.clip_rect(rect.x, rect.y, rect.width, rect.height);
}
}
pub fn end_clipping_container(ctx: &mut dyn RenderContext, style: &ClippingContainerStyle) {
if style.clipping {
ctx.restore();
}
}
pub fn draw_section_container(
ctx: &mut dyn RenderContext,
rect: Rect,
theme: &dyn ContainerTheme,
style: &SectionContainerStyle,
) {
ctx.set_fill_color(theme.bg());
ctx.fill_rect(rect.x, rect.y, rect.width, rect.height);
let header_h = style.header_height.min(rect.height);
ctx.set_fill_color(theme.section_header_bg());
ctx.fill_rect(rect.x, rect.y, rect.width, header_h);
}
pub fn draw_panel_container(
ctx: &mut dyn RenderContext,
rect: Rect,
theme: &dyn ContainerTheme,
style: &PanelContainerStyle,
role: PanelRole,
) {
let _ = style;
ctx.set_fill_color(theme.panel_bg());
ctx.fill_rect(rect.x, rect.y, rect.width, rect.height);
ctx.set_fill_color(theme.panel_border());
match role {
PanelRole::Toolbar => {
ctx.fill_rect(rect.x, rect.y + rect.height - 1.0, rect.width, 1.0);
}
PanelRole::Sidebar => {
ctx.fill_rect(rect.x + rect.width - 1.0, rect.y, 1.0, rect.height);
}
PanelRole::StatusBar => {
ctx.fill_rect(rect.x, rect.y, rect.width, 1.0);
}
}
}
pub struct ContainerView {
pub kind: ContainerType,
pub border: bool,
}
pub fn draw_container(
ctx: &mut dyn RenderContext,
rect: Rect,
view: &ContainerView,
theme: &dyn ContainerTheme,
style: &dyn ContainerStyle,
) {
match view.kind {
ContainerType::Plain => {
ctx.set_fill_color(theme.bg());
ctx.fill_rect(rect.x, rect.y, rect.width, rect.height);
}
ContainerType::Bordered => {
ctx.set_fill_color(theme.bg());
ctx.fill_rounded_rect(rect.x, rect.y, rect.width, rect.height, style.radius());
if view.border {
ctx.set_stroke_color(theme.border());
ctx.set_stroke_width(style.border_width());
ctx.stroke_rounded_rect(rect.x, rect.y, rect.width, rect.height, style.radius());
}
}
ContainerType::Card => {
let (sx, sy) = style.shadow_offset();
ctx.set_fill_color_alpha(theme.card_shadow_color(), style.shadow_alpha());
ctx.fill_rounded_rect(
rect.x + sx,
rect.y + sy,
rect.width,
rect.height,
style.radius(),
);
ctx.reset_alpha();
ctx.set_fill_color(theme.bg());
if style.radius() > 0.0 {
ctx.fill_rounded_rect(rect.x, rect.y, rect.width, rect.height, style.radius());
} else {
ctx.fill_rect(rect.x, rect.y, rect.width, rect.height);
}
if view.border {
ctx.set_stroke_color(theme.border());
ctx.set_stroke_width(style.border_width());
if style.radius() > 0.0 {
ctx.stroke_rounded_rect(
rect.x,
rect.y,
rect.width,
rect.height,
style.radius(),
);
} else {
ctx.stroke_rect(rect.x, rect.y, rect.width, rect.height);
}
}
}
ContainerType::Clip => {
ctx.save();
ctx.clip_rect(rect.x, rect.y, rect.width, rect.height);
}
ContainerType::Section => {
ctx.set_fill_color(theme.bg());
ctx.fill_rect(rect.x, rect.y, rect.width, rect.height);
let header_h: f64 = 24.0;
ctx.set_fill_color(theme.section_header_bg());
ctx.fill_rect(rect.x, rect.y, rect.width, header_h.min(rect.height));
}
ContainerType::Panel(role) => {
ctx.set_fill_color(theme.panel_bg());
ctx.fill_rect(rect.x, rect.y, rect.width, rect.height);
ctx.set_fill_color(theme.panel_border());
match role {
PanelRole::Toolbar => {
ctx.fill_rect(rect.x, rect.y + rect.height - 1.0, rect.width, 1.0);
}
PanelRole::Sidebar => {
ctx.fill_rect(rect.x + rect.width - 1.0, rect.y, 1.0, rect.height);
}
PanelRole::StatusBar => {
ctx.fill_rect(rect.x, rect.y, rect.width, 1.0);
}
}
}
}
}