use egui::{emath::Float, pos2, Align2, Color32, Mesh, Rect, Shape, Vec2};
use crate::{DesignTokens, TopBarStyle};
pub trait ContextExt {
fn ctx(&self) -> &egui::Context;
fn text_format_body(&self) -> egui::TextFormat {
egui::TextFormat::simple(
egui::TextStyle::Body.resolve(&self.ctx().style()),
self.ctx().style().visuals.text_color(),
)
}
fn text_format_key(&self) -> egui::TextFormat {
let mut style = egui::TextFormat::simple(
egui::TextStyle::Monospace.resolve(&self.ctx().style()),
self.ctx().style().visuals.text_color(),
);
style.background = self.ctx().style().visuals.widgets.noninteractive.bg_fill;
style
}
fn rerun_logo_uri(&self) -> &'static str {
if self.ctx().style().visuals.dark_mode {
"bytes://logo_dark_mode"
} else {
"bytes://logo_light_mode"
}
}
fn hover_stroke(&self) -> egui::Stroke {
self.ctx().style().visuals.widgets.active.fg_stroke
}
fn selection_stroke(&self) -> egui::Stroke {
self.ctx().style().visuals.selection.stroke
}
#[must_use]
fn warning_text(&self, text: impl Into<String>) -> egui::RichText {
let style = self.ctx().style();
egui::RichText::new(text)
.italics()
.color(style.visuals.warn_fg_color)
}
#[must_use]
fn error_text(&self, text: impl Into<String>) -> egui::RichText {
let style = self.ctx().style();
egui::RichText::new(text)
.italics()
.color(style.visuals.error_fg_color)
}
fn top_bar_style(&self, style_like_web: bool) -> TopBarStyle {
let egui_zoom_factor = self.ctx().zoom_factor();
let fullscreen = self
.ctx()
.input(|i| i.viewport().fullscreen)
.unwrap_or(false);
let make_room_for_window_buttons = !style_like_web && {
#[cfg(target_os = "macos")]
{
crate::FULLSIZE_CONTENT && !fullscreen
}
#[cfg(not(target_os = "macos"))]
{
_ = fullscreen;
false
}
};
let native_buttons_size_in_native_scale = egui::vec2(64.0, 24.0);
let height = if make_room_for_window_buttons {
let height = native_buttons_size_in_native_scale.y;
height.max(native_buttons_size_in_native_scale.y / egui_zoom_factor)
} else {
DesignTokens::top_bar_height() - DesignTokens::top_bar_margin().sum().y
};
let indent = if make_room_for_window_buttons {
native_buttons_size_in_native_scale.x / egui_zoom_factor
} else {
0.0
};
TopBarStyle { height, indent }
}
fn paint_watermark(&self) {
if let Ok(egui::load::TexturePoll::Ready { texture }) = self.ctx().try_load_texture(
self.rerun_logo_uri(),
egui::TextureOptions::default(),
egui::SizeHint::Scale(1.0.ord()),
) {
let rect = Align2::RIGHT_BOTTOM
.align_size_within_rect(texture.size, self.ctx().screen_rect())
.translate(-Vec2::splat(16.0));
let mut mesh = Mesh::with_texture(texture.id);
let uv = Rect::from_min_max(pos2(0.0, 0.0), pos2(1.0, 1.0));
mesh.add_rect_with_uv(rect, uv, Color32::WHITE);
self.ctx().debug_painter().add(Shape::mesh(mesh));
}
}
}
impl ContextExt for egui::Context {
fn ctx(&self) -> &egui::Context {
self
}
}