#![no_std]
#![forbid(unsafe_code)]
extern crate alloc;
pub mod consts;
pub mod keys;
mod a11y;
mod auto;
mod auto_perm;
mod agent;
mod assoc;
mod basic;
mod chart;
mod chrome;
mod clipimg;
mod cmd;
mod color;
mod ctx;
mod cursor;
mod data;
mod datepick;
mod diagram; pub use diagram::{
dg_edge_points, dg_hairline, dg_length, dg_paint_grid, dg_point_at, dg_stroke_edge, DEdge, DEv, DHit, DModel, DNode, DPort, DgFrame, DgGeo,
DgPaint, DgRoute, DiagramState, Viewport, DG_CONNECT, DG_PAN, DG_PLACE, DG_SELECT, DN_LOCKED, DN_NOSELECT, DPT_HIDDEN,
DPT_USED, DR_BEZIER, DR_ORTHO, DR_STRAIGHT,
};
pub use diagram::{dg_toggle_rect, DN_FRAME, DN_OUTLINE, DN_RESIZE, DN_STEP, DN_TOGGLE}; pub use diagram::DN_HITMIN; mod dirty;
mod dnd;
mod ed_core;
pub use ed_core::{TextPos, TextSel};
mod rich_doc;
pub use rich_doc::{
list_marks, Fmt, Para, RichDoc, RA_CENTER, RA_JUSTIFY, RA_LEFT, RA_RIGHT, LEVEL_MAX, LS_BULLET, LS_NONE, LS_NUMBER, PS_H1, PS_H2,
PS_H3, PS_NORMAL, PS_QUOTE, RF_ALL, RF_BOLD, RF_ITALIC, RF_STRIKE, RF_UNDER,
};
mod rich_edit;
pub use rich_edit::{
RTB_ALIGN, RTB_ALL, RTB_CHARS, RTB_CLEAR, RTB_COLOR, RTB_HISTORY, RTB_LINK, RTB_LISTS, RTB_STYLE, RT_NO_FRAME, RT_OPEN_LINKS, RT_PLAIN_PASTE,
RT_READONLY, RT_TAB,
};
mod rich_html;
mod md_doc;
pub use md_doc::{
MdBlock, MdBox, MdDoc, MdField, MdFieldSpot, MdForm, MdImage, MdLinkSpot, MdOption, MdSpan, MdTable, MA_CENTER, MA_LEFT, MA_NONE, MA_RIGHT,
MB_CODE, MB_HEADING, MB_PARA, MB_ROW, MB_RULE, MF_BUTTON, MF_CHECKBOX, MF_HIDDEN, MF_PASSWORD, MF_RADIO, MF_RESET, MF_SELECT, MF_SUBMIT,
MF_TEXT, MF_TEXTAREA, MK_BULLET, MK_NONE, MK_NUMBER, MS_BOLD, MS_CODE, MS_ITALIC, MS_STRIKE, MS_UNDER,
};
mod md_dom;
pub use md_dom::MdNode;
mod md_view;
pub use md_view::{md_field_id, MdEv, MdSubmit, MdViewState, MI_APP, MI_ASK, MI_LOCAL, MV_LTR, MV_NO_FRAME, MV_OPEN_LINKS, MV_RTL};
mod vlist;
pub use vlist::VListState;
mod code_doc;
pub use code_doc::{CodeDoc, LineChange, FIND_CASE, FIND_MAX, FIND_WORD};
pub use code_doc::{Diag, DIAG_ERROR, DIAG_INFO, DIAG_WARNING}; mod highlight;
pub use highlight::{
CodeTheme, Grammar, Highlighter, Rule, Token, INI, JSON, MARKDOWN, PLAIN, RUST, SY_CODE, SY_COMMENT, SY_CONST, SY_COUNT, SY_EMPH, SY_ESCAPE,
SY_FUNC, SY_HEADING, SY_KEY, SY_KEYWORD, SY_LINK, SY_META, SY_NUMBER, SY_PUNCT, SY_STRING, SY_STRONG, SY_TEXT, SY_TYPE, TOML,
};
pub use highlight::JFS; mod code_edit;
mod code_long;
pub use code_edit::{CodeStatus, CE_NO_FIND, CE_NO_FRAME, CE_NO_GUTTER, CE_NO_LINE, CE_READONLY};
pub use code_edit::CE_MARKS; pub use code_long::code_long_check; mod dock;
mod drop;
mod edit;
mod filedlg;
mod fontpick;
pub use fontpick::{font_language, FontSel};
mod grid;
mod hexview;
pub use hexview::{HexEv, HexMark, HexState};
mod imgview;
pub use imgview::{ImageViewState, SvgFonts, SvgText, ViewImage, IV_NO_BARS, IV_NO_CHECKER, IV_NO_GRID, IV_SMOOTH, IV_TEXT_COLOR, IV_WHEEL_SCROLL};
pub use img_svg::Svg;
mod history;
pub use history::{Edit, History, Snapshot};
mod hotreload;
mod hyph;
pub mod i18n;
mod ids;
#[cfg(any(windows, jfgui_glibc, target_os = "android", target_arch = "wasm32"))]
mod gpu_out;
#[cfg(not(any(windows, jfgui_glibc, target_os = "android", target_arch = "wasm32")))]
#[path = "gpu_out_off.rs"]
mod gpu_out;
#[cfg(any(windows, jfgui_glibc, target_os = "android"))]
pub use gpu_out::{GPU_OUT_FS, GPU_OUT_FS_IMAGE, GPU_OUT_FS_TILE, GPU_OUT_VS, GPU_OUT_WGSL};
mod canvas;
pub use canvas::{CanvasContent, CanvasDesc, CanvasGpu, CanvasView};
mod inspect;
#[cfg(jfgui_dev)]
mod inspect_edit;
#[cfg(not(jfgui_dev))]
#[path = "inspect_edit_off.rs"]
mod inspect_edit;
#[cfg(jfgui_dev)]
mod inspect_src;
#[cfg(not(jfgui_dev))]
#[path = "inspect_src_off.rs"]
mod inspect_src;
mod kbnav;
pub use ids::{ID_HASH_BASE, wid, wid_path};
mod layout;
mod list;
mod notify;
mod office_gallery;
mod perm;
mod popup;
mod recent;
mod render_par;
mod ribbon;
mod settings_page;
mod shell;
mod slider;
mod sound;
mod rtl;
mod runtime;
mod screen;
mod sensors;
mod scrollcopy;
mod stock;
mod style;
mod symbol;
mod taskbar;
mod tasks;
mod term;
mod touch;
pub use touch::{Finger, TwoFingers};
pub use term::{TermEv, TermState, TF_CTRL_SHIFT6, TF_NO_FRAME, TF_NO_INPUT, TF_QHELP, TK_KEY, TM_BUSY, TM_LINE, TM_RAW, TM_SECRET};
pub mod theme;
mod timeline;
pub use timeline::{TimelineState, TlTrack};
mod tray;
mod value;
mod vicon;
mod win;
mod winstate;
mod desk;
pub use desk::{
DeskEv, DeskState, DeskWin, DTB_ICONS, DWF_FIXED, DWF_MAXIMIZED, DWF_NOCLOSE, DWF_NOMAX, DWF_NOMIN, DWF_NOTASK, DW_LEFT, DW_MAX, DW_MIN,
DW_RIGHT,
};
use alloc::collections::{BTreeMap, VecDeque};
use alloc::string::String;
use alloc::vec::Vec;
use gfx::Dc;
use text::Text;
pub use clipimg::{clip_bmp_from_sf, clipimg_parse, clipimg_record};
pub use cmd::{Cmd, Draw, DrawRef, Gfx, IconHook};
pub use consts::*;
pub use ctx::{Sem, Slot, ease};
pub use cursor::CursorDraw;
pub use edit::TextboxPresentation;
pub use edit::TextSurfaceLine;
pub use keys::*;
pub use layout::{dp_at, px2dip_at};
pub use perm::boot;
pub use assoc::{assoc_switch, desk_boot};
pub use recent::{RECENT_KEEP, RecentOpen};
pub use rt::{app_version, VERSION, VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH};
pub use plat::{DE_ALL, DE_COPY, DE_LINK, DE_MOVE, DT_FILES, DT_HTML, DT_IMAGE, DT_STD, DT_TEXT, DT_URL, DT_USER0, DragData};
pub use popup::{Command, Mi}; pub use ribbon::{RibbonGroup, RibbonGroupMode, RibbonLayout, RibbonMetrics, RibbonSample};
pub use runtime::{Runtime, launch, run, run_window};
pub use style::{Sp, Style, StyleBasic, StyleChrome, StyleData, StyleEdit, StyleList, StyleMisc, StylePopup, StyleShell, StyleValue};
pub use data::{GridCol, GridEv, GridState, TreeEv, TreeRow, TreeState};
pub use chart::{BarSeries, DonutSlice};
pub use chart::{
lc_nice, lc_time_step, lc_time_text, LcMarker, LcSeries, LcThreshold, LcUnit, LineChart, SeriesBuf, SeriesCol, LC_NO_GRID, LC_NO_HOVER,
LC_NO_LEGEND, LX_NANOS, LX_NUM, LX_SECS,
};
pub use shell::{CmdItem, NavState};
pub use dock::{
DockPanel, DockState, DOCK_BOTTOM, DOCK_CENTER, DOCK_FLOAT, DOCK_FLOAT_MAX, DOCK_LEFT, DOCK_MK_BOTTOM, DOCK_MK_CENTER, DOCK_MK_LEFT,
DOCK_MK_RIGHT, DOCK_MK_TOP, DOCK_RIGHT, DP_HIDDEN, DP_NOCLOSE, DP_NOFLOAT, DOCK_HOLD_MS, DOCK_TAB_HOLD,
};
pub use plat::taskbar::{JumpTask, TaskbarProgress};
pub use plat::hotkey::{Chord, HotkeyError};
pub use plat::screen::{Monitor, ScreenError};
pub use stock::{card_opaque, kind_colors, Stock};
pub use vicon::{paint_svg_icon, paint_svg_icon2};
pub use symbol::{SymPalette, Symbol, SymbolCache, SYM_BODY, SYM_CACHE_MAX_W, SYM_CRIT, SYM_HI, SYM_INK, SYM_OK, SYM_PORT, SYM_ROLES,
SYM_SCREEN, SYM_SHADE, SYM_TINT, SYM_WARN}; pub use theme::color_mix;
pub use theme::{contrast_ratio, luminance};
pub use theme::{Theme, ThemeError}; pub use win::Shared; pub use color::{hsv_to_rgb, rgb_to_hsv};
pub use value::{cvtd, deg_atan2, deg_sincos, grad_at, part_id, px_mix, RangeF, Track, NO_DEFAULT};
#[cfg(not(feature = "std"))]
#[macro_export]
macro_rules! main {
($body:expr) => {
$crate::__jfgui_main!($body);
};
}
#[cfg(feature = "std")]
#[macro_export]
macro_rules! main {
($body:expr) => {
$crate::__jfgui_main!($body);
#[allow(unsafe_code, dead_code)]
fn main() {
unsafe extern "Rust" {
fn jfgui_std_start() -> !;
}
unsafe { jfgui_std_start() }
}
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! __jfgui_main {
($body:expr) => {
#[cfg(panic = "unwind")]
compile_error!("JFLib needs panic = \"abort\": add [profile.dev] and [profile.release] with panic = \"abort\" to this project's Cargo.toml");
#[allow(unsafe_code, unexpected_cfgs)]
#[unsafe(no_mangle)]
fn jfgui_main() -> i32 {
#[cfg(jfgui_manifest)]
const JF_MANIFEST: Option<&str> = Some(include_str!(env!("JFGUI_PERMISSIONS_FILE")));
#[cfg(not(jfgui_manifest))]
const JF_MANIFEST: Option<&str> = option_env!("JFGUI_PERMISSIONS");
#[cfg(jfgui_package)]
const JF_PACKAGE: Option<&str> = Some(include_str!(env!("JFGUI_PACKAGE_FILE")));
#[cfg(not(jfgui_package))]
const JF_PACKAGE: Option<&str> = option_env!("JFGUI_PACKAGE");
#[cfg(jfgui_assets)]
static ASSETS: &[u8] = include_bytes!(env!("JFGUI_ASSETS"));
#[cfg(not(jfgui_assets))]
static ASSETS: &[u8] = &[];
if let Err(code) = $crate::boot(option_env!("JFGUI_APP"), JF_MANIFEST, ASSETS) {
return code;
}
if let Some(code) = $crate::desk_boot(JF_PACKAGE) {
return code;
}
$body
}
};
}
#[derive(Clone, Copy)]
pub struct AppDesc {
pub title: &'static str,
pub flags: u32,
pub w: u16,
pub h: u16,
pub min_w: u16,
pub min_h: u16,
pub accent: u32,
pub cmds: &'static [Command],
pub menubar: &'static [Mi],
}
impl AppDesc {
pub const NONE: AppDesc =
AppDesc { title: "", flags: 0, w: 0, h: 0, min_w: 0, min_h: 0, accent: 0, cmds: &[], menubar: &[] };
pub fn translated(&self) -> AppDesc {
AppDesc { title: i18n::t(self.title), cmds: i18n::commands(self.cmds), menubar: i18n::menu(self.menubar), ..*self }
}
}
pub trait App {
fn actions(&self) -> &'static [agent_core::ActionSpec] { &[] }
fn action_revision(&self) -> Option<u64> { None }
fn action_available(&self, _spec: &agent_core::ActionSpec) -> Result<(), agent_core::ActionError> { Ok(()) }
fn action(&mut self, _ui: &mut Ui, _spec: &agent_core::ActionSpec, _input: &agent_core::Value,
_context: &agent_core::ActionContext) -> Result<agent_core::ActionResult, agent_core::ActionError> {
Err(agent_core::ActionError::new(agent_core::ErrorCode::NotFound, "No domain action with this name"))
}
fn action_inspect(&self, _query: &agent_core::Value) -> Result<agent_core::Value, agent_core::ActionError> {
Ok(agent_core::Value::object([]))
}
fn action_resource_info(&self, _uri: &str) -> Result<agent_core::Resource, agent_core::ActionError> {
Err(agent_core::ActionError::new(agent_core::ErrorCode::NotFound, "Resource not found"))
}
fn action_resource_read(&self, _uri: &str, _offset: u64, _limit: usize) -> Result<Vec<u8>, agent_core::ActionError> {
Err(agent_core::ActionError::new(agent_core::ErrorCode::NotFound, "Resource not found"))
}
fn init(&mut self, _ui: &mut Ui) -> bool {
true
}
fn frame(&mut self, ui: &mut Ui);
fn command(&mut self, _ui: &mut Ui, _id: u32, _arg: u32) -> bool {
false
}
}
pub struct WinParts {
pub(crate) ctx: ctx::W,
pub(crate) lay: layout::W,
pub(crate) cmd: cmd::W,
pub(crate) dirty: dirty::W,
pub(crate) rt: runtime::W,
#[allow(dead_code)] pub(crate) popup: popup::W,
#[allow(dead_code)]
pub(crate) list: list::W,
#[allow(dead_code)]
pub(crate) chrome: chrome::W,
pub(crate) rtl: rtl::W,
pub(crate) scopy: scrollcopy::W,
pub(crate) canv: canvas::W,
}
impl WinParts {
pub(crate) fn new() -> WinParts {
WinParts {
ctx: ctx::W::new(),
lay: layout::W::default(),
cmd: cmd::W::new(&cmd::CAPS_MAIN),
dirty: dirty::W::default(),
rt: runtime::W::new(),
popup: Default::default(),
list: Default::default(),
chrome: Default::default(),
rtl: Default::default(),
scopy: Default::default(),
canv: Default::default(),
}
}
}
#[derive(Default)]
#[allow(dead_code)] pub(crate) struct Mods {
pub(crate) popup: popup::S,
pub(crate) edit: edit::S,
pub(crate) list: list::S,
pub(crate) value: value::S,
pub(crate) color: color::S,
pub(crate) win: win::S,
pub(crate) chrome: chrome::S,
pub(crate) filedlg: filedlg::S,
pub(crate) chart: chart::S,
pub(crate) shell: shell::S,
pub(crate) notify: notify::S,
pub(crate) a11y: a11y::S,
pub(crate) dock: dock::S,
pub(crate) kbnav: kbnav::S,
pub(crate) fonts: fontpick::S,
pub(crate) term: term::S,
pub(crate) perm: perm::S,
pub(crate) rich: rich_edit::S,
pub(crate) code: code_edit::S,
pub(crate) ins: inspect::S,
pub(crate) hr: hotreload::S,
pub(crate) ied: inspect_edit::S,
pub(crate) isrc: inspect_src::S,
pub(crate) svg: imgview::S,
pub(crate) hyph: hyph::S,
pub(crate) vlist: vlist::S,
pub(crate) sound: sound::S,
pub(crate) screen: screen::S,
pub(crate) recent: recent::S,
pub(crate) scopy: scrollcopy::S,
pub(crate) rpar: render_par::S,
pub(crate) desk: desk::S,
pub(crate) touch: touch::S,
pub(crate) gout: gpu_out::S,
}
#[derive(Clone, Debug, Default)]
pub struct GpuOutput {
pub wanted: bool,
pub on: bool,
pub building: bool,
pub pending: bool,
pub never: bool,
pub adapter: alloc::string::String,
pub present_mode: &'static str,
pub error: Option<alloc::string::String>,
pub reserved: u64,
pub frames: u64,
pub cpu_frames: u64,
pub upload_bytes: u64,
pub upload_base: u64,
pub base_px: u64,
pub split_frames: u64,
pub layer_textures: u32,
pub layer_bytes: u64,
pub layer_store: u64,
pub image_quads: u32,
pub image_textures: u32,
pub image_bytes: u64,
pub image_uploads: u64,
pub image_hits: u64,
pub image_evicted: u64,
pub canvas_apart: u32,
pub canvas_quads: u32,
pub canvas_frames: u64,
pub canvas_tiles: u32,
pub canvas_bytes: u64,
pub canvas_fills: u64,
pub canvas_fill_us: u64,
pub canvas_evicted: u64,
pub canvas_settles: u64,
pub canvas_diff_frames: u64,
pub canvas_diff_px: u64,
pub canvas_diff_sum: u64,
pub canvas_diff_max: u32,
pub render_us: u64,
pub present_us: u64,
pub switches: u32,
pub leaves: u32,
pub verified: u64,
pub verify_bad: u64,
}
pub struct Ui {
pub(crate) agent: agent::State,
pub desc: AppDesc,
pub style: &'static dyn Style,
pub text: Text,
pub dc: Dc,
pub(crate) wp: WinParts,
pub(crate) m: Mods,
pub(crate) sems: Vec<Sem>,
pub(crate) semtext_len: usize,
pub(crate) sem_dummy: Sem,
pub(crate) slots: BTreeMap<u32, Slot>,
pub(crate) keydown: [u8; 256],
pub(crate) mpts: Vec<[i32; 2]>,
pub(crate) mprs: Vec<u32>,
pub(crate) mtilt: [i32; 2],
pub(crate) mpress: u32,
pub(crate) mptype: u32,
pub(crate) mpts_win: u32,
pub(crate) cmdq: VecDeque<(u32, u32)>,
pub(crate) text_more: Vec<(u32, Vec<u32>)>,
pub(crate) timers: Vec<(u32, u32)>,
pub(crate) limits: [u32; ctx::LIM_N],
pub(crate) mods: u32,
pub(crate) frame: u32,
pub(crate) now_ms: u32,
pub(crate) repass: bool,
pub(crate) animating: bool,
pub(crate) anim_off: bool,
pub(crate) rtl: bool,
pub(crate) rtl_mode: u8,
pub(crate) app_focus: u32,
pub(crate) app_active: bool,
pub(crate) theme_sys: bool,
pub(crate) theme_base_dark: bool,
pub(crate) contrast_mode: u8,
pub(crate) high_contrast: bool,
pub(crate) hc_sys: Option<plat::HcColors>,
pub(crate) accent_sys: bool,
pub(crate) anim_forced: bool,
pub(crate) anim_sys: bool,
pub(crate) text_scale_forced: bool,
pub(crate) text_scale: u32,
pub(crate) dbl_ms: u32,
pub(crate) font_prefs: (Option<bool>, Option<u8>, Option<u8>),
pub(crate) tb_sys: plat::Titlebar,
pub(crate) blink_ms: u32,
pub(crate) warns: u32,
pub(crate) ui_debug: bool,
pub(crate) dup_check: bool,
pub(crate) dup_warned: alloc::collections::BTreeSet<u32>,
pub(crate) ids: ids::Ids,
pub(crate) focus_req: u32,
pub(crate) focus_req_win: u32,
pub(crate) focus_req_old: u32,
pub(crate) focus_req_frame: u32,
pub(crate) uiw_cur: u32,
pub(crate) theme: [u32; theme::THEME_N],
pub(crate) theme_dark: bool,
pub(crate) accent: u32,
pub(crate) look: theme::Look,
pub(crate) title: String,
pub(crate) t0_us: u64,
pub(crate) headless: bool,
pub(crate) need: bool,
pub(crate) need_render: bool,
pub(crate) quit: bool,
pub(crate) log_events: bool,
pub(crate) open_reqs: Vec<plat::instance::Request>,
pub(crate) autoclose_ms: u32,
pub(crate) accent_raw: u32,
pub(crate) settle_warned: bool,
pub(crate) verify_dirty: bool,
pub(crate) frames_rendered: u32,
pub(crate) close_at: u32,
pub(crate) drects: Vec<[i32; 4]>,
pub(crate) dmg: Vec<dirty::Dmg>,
pub(crate) cvs: Vec<dirty::Cvs>,
pub(crate) icon_hook: Option<IconHook>,
pub(crate) uiinput: UiInput,
pub(crate) sc: auto::S,
pub(crate) ucur: cursor::S,
pub(crate) dr: drop::S,
pub(crate) dnd: dnd::S,
pub(crate) tasks: plat::task::Executor,
}
mod code_assist;
pub use code_assist::{
CodeAssist, CodeEv, CompItem, CompList, SigHelp, CI_CONSTANT, CI_FIELD, CI_FUNCTION, CI_KEYWORD, CI_METHOD, CI_MODULE, CI_PARAM, CI_TEXT,
CI_VALUE, CI_VARIABLE, POP_ROWS,
};
pub use code_doc::{TextEdit, BP_COND, BP_DISABLED, BP_ON};
pub use code_edit::{CE_BREAKPOINTS, CE_FOLDS};
mod action_card;
pub use action_card::CardDesc;