use gtk4::cairo::Context;
use gtk4::pango;
use crate::types::Color;
mod activity_bar;
mod app_font;
pub mod backend;
mod board;
mod chart;
mod combo_box;
mod command_center;
mod command_line;
mod completions;
mod context_menu;
mod data_table;
mod date_picker;
mod dialog;
mod diff_view;
mod drop_overlay;
mod editor;
pub mod events;
mod form;
mod image;
mod list;
mod menu_bar;
pub mod menu_overlay;
mod message_list;
mod minimap;
mod multi_section_view;
mod number_input;
mod painted_text;
mod palette;
mod panel;
mod pipeline_view;
mod progress;
mod rich_text_popup;
mod run;
pub mod scroll_view;
mod scrollbar;
pub mod services;
pub mod shell_runner;
mod sidebar_panel;
mod spinner;
mod split;
mod split_tree;
mod status_bar;
mod surface;
mod tab_bar;
mod terminal;
pub mod testing;
mod text_display;
mod text_input;
mod toast;
mod toolbar;
mod tooltip;
mod tree;
#[allow(deprecated)]
pub use crate::primitives::tab_bar::TabBarHits;
pub use activity_bar::{draw_activity_bar, draw_activity_bar_with_style, ACTIVITY_ROW_PX};
pub use backend::GtkBackend;
pub use board::gtk_board_layout;
pub use chart::gtk_chart_layout;
pub use command_center::{draw_command_center, gtk_command_center_layout};
pub use completions::draw_completions;
pub use context_menu::draw_context_menu;
pub use data_table::{draw_data_table, draw_data_table_with_glyphs, gtk_data_table_layout};
pub use dialog::draw_dialog;
pub use editor::{draw_editor, editor_col_at_x};
pub use events::{wire_da_events, wire_da_events_with_scroll_direction};
pub use form::draw_settings_chrome;
pub use image::draw_image;
pub use list::{draw_list, gtk_list_layout};
pub use menu_bar::{draw_menu_bar, gtk_menu_bar_layout};
pub use menu_overlay::MenuOverlay;
pub use message_list::draw_message_list;
pub use minimap::{draw_minimap, gtk_minimap_layout};
pub use multi_section_view::{
draw_multi_section_view, gtk_msv_layout, metrics_for as multi_section_view_metrics,
};
pub use palette::{draw_palette, gtk_palette_layout};
pub use panel::gtk_panel_layout;
pub use pipeline_view::gtk_pipeline_view_layout;
pub use progress::gtk_progress_layout;
pub use rich_text_popup::{
draw_rich_text_popup, RICH_TEXT_POPUP_SB_INSET, RICH_TEXT_POPUP_SB_WIDTH,
};
pub use run::{
app_id_is_valid, display_available, run, run_with, GtkRunner, RunConfig, StepOutcome,
};
pub use sidebar_panel::gtk_sidebar_panel_layout;
pub use spinner::{draw_spinner, gtk_spinner_layout};
pub use split::gtk_split_layout;
pub use split_tree::gtk_split_tree_layout;
pub use status_bar::{draw_status_bar, MIN_GAP_PX};
pub use tab_bar::{
draw_tab_bar, draw_tab_bar_icons, draw_tab_bar_icons_with_chrome,
draw_tab_bar_icons_with_chrome_and_glyphs, draw_tab_bar_with_chrome,
draw_tab_bar_with_chrome_and_glyphs,
};
pub use text_display::{draw_text_display, gtk_text_display_layout};
pub use text_input::{draw_text_input, gtk_text_input_layout};
pub use toast::gtk_toast_stack_layout;
pub use toolbar::{draw_toolbar, draw_toolbar_with_options, gtk_toolbar_layout};
pub use tooltip::{draw_tooltip, draw_tooltip_with_chrome};
pub use tree::{draw_tree, gtk_tree_layout, gtk_tree_layout_measured};
pub fn cairo_rgb(c: Color) -> (f64, f64, f64) {
(c.r as f64 / 255.0, c.g as f64 / 255.0, c.b as f64 / 255.0)
}
pub fn set_source(cr: &Context, c: Color) {
let (r, g, b) = cairo_rgb(c);
cr.set_source_rgb(r, g, b);
}
pub fn set_source_rgba(cr: &Context, c: Color) {
cr.set_source_rgba(
c.r as f64 / 255.0,
c.g as f64 / 255.0,
c.b as f64 / 255.0,
c.a as f64 / 255.0,
);
}
pub(crate) fn rounded_rect_path(cr: &Context, x: f64, y: f64, w: f64, h: f64, r: f64) {
use std::f64::consts::{FRAC_PI_2, PI};
cr.new_path();
cr.arc(x + w - r, y + r, r, -FRAC_PI_2, 0.0);
cr.arc(x + w - r, y + h - r, r, 0.0, FRAC_PI_2);
cr.arc(x + r, y + h - r, r, FRAC_PI_2, PI);
cr.arc(x + r, y + r, r, PI, 3.0 * FRAC_PI_2);
cr.close_path();
}
pub use pango::Layout as PangoLayout;
pub const NERD_FONT_FALLBACK_FAMILY: &str = "Symbols Nerd Font";
thread_local! {
static NERD_FONT_FALLBACK: std::cell::RefCell<String> =
std::cell::RefCell::new(NERD_FONT_FALLBACK_FAMILY.to_string());
}
pub(crate) fn current_nerd_font_fallback_family() -> String {
NERD_FONT_FALLBACK.with(|f| f.borrow().clone())
}
pub(crate) fn set_current_nerd_font_fallback_family(family: &str) {
NERD_FONT_FALLBACK.with(|f| *f.borrow_mut() = family.to_string());
}
pub(crate) fn chrome_font_description(ui_font: &str) -> pango::FontDescription {
with_nerd_font_fallback(&pango::FontDescription::from_string(ui_font))
}
pub(crate) fn with_nerd_font_fallback(base: &pango::FontDescription) -> pango::FontDescription {
let mut desc = base.clone();
let fallback = current_nerd_font_fallback_family();
let family = desc.family().map(|f| f.to_string()).unwrap_or_default();
let codicon = crate::codicon::FONT_FAMILY;
let with_fallback = if family.is_empty() {
format!("{fallback},{codicon}")
} else {
format!("{family},{fallback},{codicon}")
};
desc.set_family(&with_fallback);
desc
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn chrome_font_description_appends_nerd_font_fallback() {
let desc = chrome_font_description("Sans 11");
let family = desc.family().expect("family set").to_string();
assert_eq!(family, "Sans,Symbols Nerd Font,codicon");
}
#[test]
fn chrome_font_description_preserves_size() {
let plain = pango::FontDescription::from_string("Sans 11");
let desc = chrome_font_description("Sans 11");
assert_eq!(desc.size(), plain.size());
}
#[test]
fn chrome_font_description_appends_after_existing_family_list() {
let desc = chrome_font_description("Cantarell,DejaVu Sans 12");
let family = desc.family().expect("family set").to_string();
assert_eq!(family, "Cantarell,DejaVu Sans,Symbols Nerd Font,codicon");
}
#[test]
fn with_nerd_font_fallback_appends_to_an_existing_description() {
let base = pango::FontDescription::from_string("Monospace 13");
let desc = with_nerd_font_fallback(&base);
let family = desc.family().expect("family set").to_string();
assert_eq!(family, "Monospace,Symbols Nerd Font,codicon");
assert_eq!(desc.size(), base.size());
}
struct FallbackFamilyGuard;
impl Drop for FallbackFamilyGuard {
fn drop(&mut self) {
set_current_nerd_font_fallback_family(NERD_FONT_FALLBACK_FAMILY);
}
}
#[test]
fn set_current_nerd_font_fallback_family_is_read_back_by_with_nerd_font_fallback() {
let _guard = FallbackFamilyGuard;
assert_eq!(
current_nerd_font_fallback_family(),
NERD_FONT_FALLBACK_FAMILY
);
set_current_nerd_font_fallback_family("Consumer Icons");
assert_eq!(current_nerd_font_fallback_family(), "Consumer Icons");
let desc = chrome_font_description("Sans 11");
let family = desc.family().expect("family set").to_string();
assert_eq!(family, "Sans,Consumer Icons,codicon");
}
#[test]
fn tab_icon_font_tracks_the_overridden_fallback_family() {
let _guard = FallbackFamilyGuard;
set_current_nerd_font_fallback_family("Consumer Icons");
let base = pango::FontDescription::from_string("Sans 11");
let desc = tab_bar::tab_icon_font(&base);
let family = desc.family().expect("family set").to_string();
assert_eq!(family, "Consumer Icons, codicon, monospace");
}
}