Replace TODO:
with TODO(emilk):
and update code guidelines
This commit is contained in:
parent
3d5e203d86
commit
f3e305a646
60 changed files with 140 additions and 112 deletions
|
@ -59,15 +59,44 @@ Conventions unless otherwise specified:
|
||||||
|
|
||||||
While using an immediate mode gui is simple, implementing one is a lot more tricky. There are many subtle corner-case you need to think through. The `egui` source code is a bit messy, partially because it is still evolving.
|
While using an immediate mode gui is simple, implementing one is a lot more tricky. There are many subtle corner-case you need to think through. The `egui` source code is a bit messy, partially because it is still evolving.
|
||||||
|
|
||||||
* read some code before writing your own
|
* Read some code before writing your own.
|
||||||
* follow the `egui` code style
|
* Follow the `egui` code style.
|
||||||
* add blank lines around all `fn`, `struct`, `enum`, etc.
|
* Add blank lines around all `fn`, `struct`, `enum`, etc.
|
||||||
* `// Comment like this`, not `//like this`
|
* `// Comment like this.` and not `//like this`.
|
||||||
* write idiomatic rust
|
* Use `TODO` instead of `FIXME`.
|
||||||
* avoid `unsafe`
|
* Add your github handle to the `TODO`:s you write, e.g: `TODO(emilk): clean this up`.
|
||||||
* avoid code that can cause panics
|
* Write idiomatic rust.
|
||||||
* use good names for everything
|
* Avoid `unsafe`.
|
||||||
* add docstrings to types, `struct` fields and all `pub fn`.
|
* Avoid code that can cause panics.
|
||||||
* add some example code (doc-tests)
|
* Use good names for everything.
|
||||||
* before making a function longer, consider adding a helper function
|
* Add docstrings to types, `struct` fields and all `pub fn`.
|
||||||
* break the above rules when it makes sense
|
* Add some example code (doc-tests).
|
||||||
|
* Before making a function longer, consider adding a helper function.
|
||||||
|
* If you are only using it in one function, put the `use` statement in that function. This improves locality, making it easier to read and move the code.
|
||||||
|
* When importing a `trait` to use it's trait methods, do this: `use Trait as _;`. That lets the reader know why you imported it, even though it seems unused.
|
||||||
|
* Follow the [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/).
|
||||||
|
* Break the above rules when it makes sense.
|
||||||
|
|
||||||
|
|
||||||
|
### Good:
|
||||||
|
``` rust
|
||||||
|
/// The name of the thing.
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo(&self) {
|
||||||
|
// TODO(emilk): implement
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bad:
|
||||||
|
``` rust
|
||||||
|
//some function
|
||||||
|
fn get_name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
fn foo(&self) {
|
||||||
|
//FIXME: implement
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
@ -180,7 +180,7 @@ pub fn run_glow(
|
||||||
if integration.should_quit() {
|
if integration.should_quit() {
|
||||||
*control_flow = winit::event_loop::ControlFlow::Exit;
|
*control_flow = winit::event_loop::ControlFlow::Exit;
|
||||||
}
|
}
|
||||||
window.request_redraw(); // TODO: ask egui if the events warrants a repaint instead
|
window.request_redraw(); // TODO(emilk): ask egui if the events warrants a repaint instead
|
||||||
}
|
}
|
||||||
winit::event::Event::LoopDestroyed => {
|
winit::event::Event::LoopDestroyed => {
|
||||||
integration.save(&mut *app, window);
|
integration.save(&mut *app, window);
|
||||||
|
@ -193,7 +193,7 @@ pub fn run_glow(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: merge with with the clone above
|
// TODO(emilk): merge with with the clone above
|
||||||
/// Run an egui app
|
/// Run an egui app
|
||||||
#[cfg(feature = "wgpu")]
|
#[cfg(feature = "wgpu")]
|
||||||
pub fn run_wgpu(
|
pub fn run_wgpu(
|
||||||
|
@ -329,7 +329,7 @@ pub fn run_wgpu(
|
||||||
if integration.should_quit() {
|
if integration.should_quit() {
|
||||||
*control_flow = winit::event_loop::ControlFlow::Exit;
|
*control_flow = winit::event_loop::ControlFlow::Exit;
|
||||||
}
|
}
|
||||||
window.request_redraw(); // TODO: ask egui if the events warrants a repaint instead
|
window.request_redraw(); // TODO(emilk): ask egui if the events warrants a repaint instead
|
||||||
}
|
}
|
||||||
winit::event::Event::LoopDestroyed => {
|
winit::event::Event::LoopDestroyed => {
|
||||||
integration.save(&mut *app, window);
|
integration.save(&mut *app, window);
|
||||||
|
|
|
@ -270,7 +270,7 @@ impl AppRunner {
|
||||||
let epi::backend::AppOutput {
|
let epi::backend::AppOutput {
|
||||||
quit: _, // Can't quit a web page
|
quit: _, // Can't quit a web page
|
||||||
window_size: _, // Can't resize a web page
|
window_size: _, // Can't resize a web page
|
||||||
window_title: _, // TODO: change title of window
|
window_title: _, // TODO(emilk): change title of window
|
||||||
decorated: _, // Can't toggle decorations
|
decorated: _, // Can't toggle decorations
|
||||||
drag_window: _, // Can't be dragged
|
drag_window: _, // Can't be dragged
|
||||||
window_pos: _, // Can't set position of a web page
|
window_pos: _, // Can't set position of a web page
|
||||||
|
@ -406,7 +406,7 @@ fn start_runner(app_runner: AppRunner) -> Result<AppRunnerRef, JsValue> {
|
||||||
super::events::install_canvas_events(&runner_container)?;
|
super::events::install_canvas_events(&runner_container)?;
|
||||||
super::events::install_document_events(&runner_container)?;
|
super::events::install_document_events(&runner_container)?;
|
||||||
text_agent::install_text_agent(&runner_container)?;
|
text_agent::install_text_agent(&runner_container)?;
|
||||||
super::events::repaint_every_ms(&runner_container, 1000)?; // just in case. TODO: make it a parameter
|
super::events::repaint_every_ms(&runner_container, 1000)?; // just in case. TODO(emilk): make it a parameter
|
||||||
|
|
||||||
super::events::paint_and_schedule(&runner_container.runner, runner_container.panicked.clone())?;
|
super::events::paint_and_schedule(&runner_container.runner, runner_container.panicked.clone())?;
|
||||||
|
|
||||||
|
|
|
@ -252,7 +252,7 @@ pub(crate) fn webgl1_requires_brightening(gl: &web_sys::WebGlRenderingContext) -
|
||||||
fn is_safari_and_webkit_gtk(gl: &web_sys::WebGlRenderingContext) -> bool {
|
fn is_safari_and_webkit_gtk(gl: &web_sys::WebGlRenderingContext) -> bool {
|
||||||
// This call produces a warning in Firefox ("WEBGL_debug_renderer_info is deprecated in Firefox and will be removed.")
|
// This call produces a warning in Firefox ("WEBGL_debug_renderer_info is deprecated in Firefox and will be removed.")
|
||||||
// but unless we call it we get errors in Chrome when we call `get_parameter` below.
|
// but unless we call it we get errors in Chrome when we call `get_parameter` below.
|
||||||
// TODO: do something smart based on user agent?
|
// TODO(emilk): do something smart based on user agent?
|
||||||
if gl
|
if gl
|
||||||
.get_extension("WEBGL_debug_renderer_info")
|
.get_extension("WEBGL_debug_renderer_info")
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
|
|
@ -44,7 +44,7 @@ impl Painter {
|
||||||
format: surface_format,
|
format: surface_format,
|
||||||
width: size.width as u32,
|
width: size.width as u32,
|
||||||
height: size.height as u32,
|
height: size.height as u32,
|
||||||
present_mode: wgpu::PresentMode::Fifo, // TODO: make vsync configurable
|
present_mode: wgpu::PresentMode::Fifo, // TODO(emilk): make vsync configurable
|
||||||
};
|
};
|
||||||
surface.configure(&device, &surface_config);
|
surface.configure(&device, &surface_config);
|
||||||
|
|
||||||
|
@ -143,6 +143,6 @@ impl Painter {
|
||||||
|
|
||||||
#[allow(clippy::unused_self)]
|
#[allow(clippy::unused_self)]
|
||||||
pub fn destroy(&mut self) {
|
pub fn destroy(&mut self) {
|
||||||
// TODO: something here?
|
// TODO(emilk): something here?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::{fmt::Debug, hash::Hash};
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
/// State that is persisted between frames.
|
/// State that is persisted between frames.
|
||||||
// TODO: this is not currently stored in `memory().data`, but maybe it should be?
|
// TODO(emilk): this is not currently stored in `memory().data`, but maybe it should be?
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub(crate) struct State {
|
pub(crate) struct State {
|
||||||
|
|
|
@ -485,7 +485,7 @@ impl CollapsingHeader {
|
||||||
show_background,
|
show_background,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
// TODO: horizontal layout, with icon and text as labels. Insert background behind using Frame.
|
// TODO(emilk): horizontal layout, with icon and text as labels. Insert background behind using Frame.
|
||||||
|
|
||||||
let id = ui.make_persistent_id(id_source);
|
let id = ui.make_persistent_id(id_source);
|
||||||
let button_padding = ui.spacing().button_padding;
|
let button_padding = ui.spacing().button_padding;
|
||||||
|
|
|
@ -52,7 +52,7 @@ impl Default for Resize {
|
||||||
resizable: true,
|
resizable: true,
|
||||||
min_size: Vec2::splat(16.0),
|
min_size: Vec2::splat(16.0),
|
||||||
max_size: Vec2::splat(f32::INFINITY),
|
max_size: Vec2::splat(f32::INFINITY),
|
||||||
default_size: vec2(320.0, 128.0), // TODO: preferred size of [`Resize`] area.
|
default_size: vec2(320.0, 128.0), // TODO(emilk): preferred size of [`Resize`] area.
|
||||||
with_stroke: true,
|
with_stroke: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -592,7 +592,7 @@ impl Prepared {
|
||||||
- current_bar_use[d]
|
- current_bar_use[d]
|
||||||
- ui.spacing().item_spacing[d];
|
- ui.spacing().item_spacing[d];
|
||||||
inner_rect.max[d] = inner_rect.max[d].at_most(max);
|
inner_rect.max[d] = inner_rect.max[d].at_most(max);
|
||||||
// TODO: maybe auto-enable horizontal/vertical scrolling if this limit is reached
|
// TODO(emilk): maybe auto-enable horizontal/vertical scrolling if this limit is reached
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -507,7 +507,7 @@ fn interact(
|
||||||
|
|
||||||
let new_rect = ctx.constrain_window_rect_to_area(new_rect, area.drag_bounds());
|
let new_rect = ctx.constrain_window_rect_to_area(new_rect, area.drag_bounds());
|
||||||
|
|
||||||
// TODO: add this to a Window state instead as a command "move here next frame"
|
// TODO(emilk): add this to a Window state instead as a command "move here next frame"
|
||||||
area.state_mut().pos = new_rect.min;
|
area.state_mut().pos = new_rect.min;
|
||||||
|
|
||||||
if window_interaction.is_resize() {
|
if window_interaction.is_resize() {
|
||||||
|
|
|
@ -1227,7 +1227,7 @@ impl Context {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let text = format!("{} - {:?}", layer_id.short_debug_format(), area.rect(),);
|
let text = format!("{} - {:?}", layer_id.short_debug_format(), area.rect(),);
|
||||||
// TODO: `Sense::hover_highlight()`
|
// TODO(emilk): `Sense::hover_highlight()`
|
||||||
if ui
|
if ui
|
||||||
.add(Label::new(RichText::new(text).monospace()).sense(Sense::click()))
|
.add(Label::new(RichText::new(text).monospace()).sense(Sense::click()))
|
||||||
.hovered
|
.hovered
|
||||||
|
|
|
@ -506,7 +506,7 @@ impl WidgetInfo {
|
||||||
text_selection: _,
|
text_selection: _,
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
// TODO: localization
|
// TODO(emilk): localization
|
||||||
let widget_type = match typ {
|
let widget_type = match typ {
|
||||||
WidgetType::Link => "link",
|
WidgetType::Link => "link",
|
||||||
WidgetType::TextEdit => "text edit",
|
WidgetType::TextEdit => "text edit",
|
||||||
|
|
|
@ -37,7 +37,7 @@ pub(crate) struct FrameState {
|
||||||
/// Set to [`InputState::scroll_delta`] on the start of each frame.
|
/// Set to [`InputState::scroll_delta`] on the start of each frame.
|
||||||
///
|
///
|
||||||
/// Cleared by the first [`ScrollArea`] that makes use of it.
|
/// Cleared by the first [`ScrollArea`] that makes use of it.
|
||||||
pub(crate) scroll_delta: Vec2, // TODO: move to a Mutex inside of `InputState` ?
|
pub(crate) scroll_delta: Vec2, // TODO(emilk): move to `InputState` ?
|
||||||
|
|
||||||
/// horizontal, vertical
|
/// horizontal, vertical
|
||||||
pub(crate) scroll_target: [Option<(RangeInclusive<f32>, Option<Align>)>; 2],
|
pub(crate) scroll_target: [Option<(RangeInclusive<f32>, Option<Align>)>; 2],
|
||||||
|
|
|
@ -74,7 +74,7 @@ impl GridLayout {
|
||||||
pub(crate) fn new(ui: &Ui, id: Id) -> Self {
|
pub(crate) fn new(ui: &Ui, id: Id) -> Self {
|
||||||
let prev_state = State::load(ui.ctx(), id).unwrap_or_default();
|
let prev_state = State::load(ui.ctx(), id).unwrap_or_default();
|
||||||
|
|
||||||
// TODO: respect current layout
|
// TODO(emilk): respect current layout
|
||||||
|
|
||||||
let initial_available = ui.placer().max_rect().intersect(ui.cursor());
|
let initial_available = ui.placer().max_rect().intersect(ui.cursor());
|
||||||
crate::egui_assert!(
|
crate::egui_assert!(
|
||||||
|
@ -126,7 +126,7 @@ impl GridLayout {
|
||||||
let width = if is_last_column {
|
let width = if is_last_column {
|
||||||
(self.initial_available.right() - region.cursor.left()).at_most(self.max_cell_size.x)
|
(self.initial_available.right() - region.cursor.left()).at_most(self.max_cell_size.x)
|
||||||
} else if self.max_cell_size.x.is_finite() {
|
} else if self.max_cell_size.x.is_finite() {
|
||||||
// TODO: should probably heed `prev_state` here too
|
// TODO(emilk): should probably heed `prev_state` here too
|
||||||
self.max_cell_size.x
|
self.max_cell_size.x
|
||||||
} else {
|
} else {
|
||||||
// If we want to allow width-filling widgets like [`Separator`] in one of the first cells
|
// If we want to allow width-filling widgets like [`Separator`] in one of the first cells
|
||||||
|
@ -159,7 +159,7 @@ impl GridLayout {
|
||||||
|
|
||||||
#[allow(clippy::unused_self)]
|
#[allow(clippy::unused_self)]
|
||||||
pub(crate) fn align_size_within_rect(&self, size: Vec2, frame: Rect) -> Rect {
|
pub(crate) fn align_size_within_rect(&self, size: Vec2, frame: Rect) -> Rect {
|
||||||
// TODO: allow this alignment to be customized
|
// TODO(emilk): allow this alignment to be customized
|
||||||
Align2::LEFT_CENTER.align_size_within_rect(size, frame)
|
Align2::LEFT_CENTER.align_size_within_rect(size, frame)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// TODO: have separate types `PositionId` and `UniqueId`. ?
|
// TODO(emilk): have separate types `PositionId` and `UniqueId`. ?
|
||||||
|
|
||||||
/// egui tracks widgets frame-to-frame using [`Id`]s.
|
/// egui tracks widgets frame-to-frame using [`Id`]s.
|
||||||
///
|
///
|
||||||
|
|
|
@ -9,13 +9,13 @@ pub use touch_state::MultiTouchInfo;
|
||||||
use touch_state::TouchState;
|
use touch_state::TouchState;
|
||||||
|
|
||||||
/// If the pointer moves more than this, it won't become a click (but it is still a drag)
|
/// If the pointer moves more than this, it won't become a click (but it is still a drag)
|
||||||
const MAX_CLICK_DIST: f32 = 6.0; // TODO: move to settings
|
const MAX_CLICK_DIST: f32 = 6.0; // TODO(emilk): move to settings
|
||||||
|
|
||||||
/// If the pointer is down for longer than this, it won't become a click (but it is still a drag)
|
/// If the pointer is down for longer than this, it won't become a click (but it is still a drag)
|
||||||
const MAX_CLICK_DURATION: f64 = 0.6; // TODO: move to settings
|
const MAX_CLICK_DURATION: f64 = 0.6; // TODO(emilk): move to settings
|
||||||
|
|
||||||
/// The new pointer press must come within this many seconds from previous pointer release
|
/// The new pointer press must come within this many seconds from previous pointer release
|
||||||
const MAX_DOUBLE_CLICK_DELAY: f64 = 0.3; // TODO: move to settings
|
const MAX_DOUBLE_CLICK_DELAY: f64 = 0.3; // TODO(emilk): move to settings
|
||||||
|
|
||||||
/// Input state that egui updates each frame.
|
/// Input state that egui updates each frame.
|
||||||
///
|
///
|
||||||
|
@ -192,7 +192,7 @@ impl InputState {
|
||||||
stable_dt,
|
stable_dt,
|
||||||
modifiers: new.modifiers,
|
modifiers: new.modifiers,
|
||||||
keys_down,
|
keys_down,
|
||||||
events: new.events.clone(), // TODO: remove clone() and use raw.events
|
events: new.events.clone(), // TODO(emilk): remove clone() and use raw.events
|
||||||
raw: new,
|
raw: new,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,7 +324,7 @@ impl InputState {
|
||||||
/// Returns imprecision in points.
|
/// Returns imprecision in points.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn aim_radius(&self) -> f32 {
|
pub fn aim_radius(&self) -> f32 {
|
||||||
// TODO: multiply by ~3 for touch inputs because fingers are fat
|
// TODO(emilk): multiply by ~3 for touch inputs because fingers are fat
|
||||||
self.physical_pixel_size()
|
self.physical_pixel_size()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,7 +144,7 @@ pub struct Layout {
|
||||||
|
|
||||||
impl Default for Layout {
|
impl Default for Layout {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
// TODO: Get from `Style` instead.
|
// TODO(emilk): Get from `Style` instead.
|
||||||
Self::top_down(Align::LEFT) // This is a very euro-centric default.
|
Self::top_down(Align::LEFT) // This is a very euro-centric default.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -497,7 +497,7 @@ pub mod special_emojis {
|
||||||
#[derive(Clone, Copy, Debug, PartialEq)]
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
pub enum WidgetType {
|
pub enum WidgetType {
|
||||||
Label, // TODO: emit Label events
|
Label, // TODO(emilk): emit Label events
|
||||||
/// e.g. a hyperlink
|
/// e.g. a hyperlink
|
||||||
Link,
|
Link,
|
||||||
TextEdit,
|
TextEdit,
|
||||||
|
|
|
@ -142,7 +142,7 @@ pub(crate) fn menu_ui<'c, R>(
|
||||||
|
|
||||||
Frame::menu(style)
|
Frame::menu(style)
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
const DEFAULT_MENU_WIDTH: f32 = 150.0; // TODO: add to ui.spacing
|
const DEFAULT_MENU_WIDTH: f32 = 150.0; // TODO(emilk): add to ui.spacing
|
||||||
ui.set_max_width(DEFAULT_MENU_WIDTH);
|
ui.set_max_width(DEFAULT_MENU_WIDTH);
|
||||||
ui.set_menu_state(Some(menu_state_arc.clone()));
|
ui.set_menu_state(Some(menu_state_arc.clone()));
|
||||||
ui.with_layout(Layout::top_down_justified(Align::LEFT), add_contents)
|
ui.with_layout(Layout::top_down_justified(Align::LEFT), add_contents)
|
||||||
|
|
|
@ -46,7 +46,7 @@ pub struct Response {
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub clicked: [bool; NUM_POINTER_BUTTONS],
|
pub clicked: [bool; NUM_POINTER_BUTTONS],
|
||||||
|
|
||||||
// TODO: `released` for sliders
|
// TODO(emilk): `released` for sliders
|
||||||
/// The thing was double-clicked.
|
/// The thing was double-clicked.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub double_clicked: [bool; NUM_POINTER_BUTTONS],
|
pub double_clicked: [bool; NUM_POINTER_BUTTONS],
|
||||||
|
|
|
@ -204,7 +204,7 @@ pub struct Style {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Style {
|
impl Style {
|
||||||
// TODO: rename style.interact() to maybe... `style.interactive` ?
|
// TODO(emilk): rename style.interact() to maybe... `style.interactive` ?
|
||||||
/// Use this style for interactive things.
|
/// Use this style for interactive things.
|
||||||
/// Note that you must already have a response,
|
/// Note that you must already have a response,
|
||||||
/// i.e. you must allocate space and interact BEFORE painting the widget!
|
/// i.e. you must allocate space and interact BEFORE painting the widget!
|
||||||
|
@ -258,10 +258,10 @@ pub struct Spacing {
|
||||||
/// Minimum size of a [`DragValue`], color picker button, and other small widgets.
|
/// Minimum size of a [`DragValue`], color picker button, and other small widgets.
|
||||||
/// `interact_size.y` is the default height of button, slider, etc.
|
/// `interact_size.y` is the default height of button, slider, etc.
|
||||||
/// Anything clickable should be (at least) this size.
|
/// Anything clickable should be (at least) this size.
|
||||||
pub interact_size: Vec2, // TODO: rename min_interact_size ?
|
pub interact_size: Vec2, // TODO(emilk): rename min_interact_size ?
|
||||||
|
|
||||||
/// Default width of a [`Slider`] and [`ComboBox`](crate::ComboBox).
|
/// Default width of a [`Slider`] and [`ComboBox`](crate::ComboBox).
|
||||||
pub slider_width: f32, // TODO: rename big_interact_size ?
|
pub slider_width: f32, // TODO(emilk): rename big_interact_size ?
|
||||||
|
|
||||||
/// Default width of a [`TextEdit`].
|
/// Default width of a [`TextEdit`].
|
||||||
pub text_edit_width: f32,
|
pub text_edit_width: f32,
|
||||||
|
@ -1226,7 +1226,7 @@ impl DebugOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: improve and standardize `slider_vec2`
|
// TODO(emilk): improve and standardize `slider_vec2`
|
||||||
fn slider_vec2<'a>(
|
fn slider_vec2<'a>(
|
||||||
value: &'a mut Vec2,
|
value: &'a mut Vec2,
|
||||||
range: std::ops::RangeInclusive<f32>,
|
range: std::ops::RangeInclusive<f32>,
|
||||||
|
|
|
@ -1037,7 +1037,7 @@ impl Ui {
|
||||||
/// # });
|
/// # });
|
||||||
/// ```
|
/// ```
|
||||||
pub fn add_sized(&mut self, max_size: impl Into<Vec2>, widget: impl Widget) -> Response {
|
pub fn add_sized(&mut self, max_size: impl Into<Vec2>, widget: impl Widget) -> Response {
|
||||||
// TODO: configure to overflow to main_dir instead of centered overflow
|
// TODO(emilk): configure to overflow to main_dir instead of centered overflow
|
||||||
// to handle the bug mentioned at https://github.com/emilk/egui/discussions/318#discussioncomment-627578
|
// to handle the bug mentioned at https://github.com/emilk/egui/discussions/318#discussioncomment-627578
|
||||||
// and fixed in https://github.com/emilk/egui/commit/035166276322b3f2324bd8b97ffcedc63fa8419f
|
// and fixed in https://github.com/emilk/egui/commit/035166276322b3f2324bd8b97ffcedc63fa8419f
|
||||||
//
|
//
|
||||||
|
@ -1721,7 +1721,7 @@ impl Ui {
|
||||||
/// Create a child ui which is indented to the right.
|
/// Create a child ui which is indented to the right.
|
||||||
///
|
///
|
||||||
/// The `id_source` here be anything at all.
|
/// The `id_source` here be anything at all.
|
||||||
// TODO: remove `id_source` argument?
|
// TODO(emilk): remove `id_source` argument?
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn indent<R>(
|
pub fn indent<R>(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -2037,7 +2037,7 @@ impl Ui {
|
||||||
num_columns: usize,
|
num_columns: usize,
|
||||||
add_contents: Box<dyn FnOnce(&mut [Self]) -> R + 'c>,
|
add_contents: Box<dyn FnOnce(&mut [Self]) -> R + 'c>,
|
||||||
) -> R {
|
) -> R {
|
||||||
// TODO: ensure there is space
|
// TODO(emilk): ensure there is space
|
||||||
let spacing = self.spacing().item_spacing.x;
|
let spacing = self.spacing().item_spacing.x;
|
||||||
let total_spacing = spacing * (num_columns as f32 - 1.0);
|
let total_spacing = spacing * (num_columns as f32 - 1.0);
|
||||||
let column_width = (self.available_width() - total_spacing) / (num_columns as f32);
|
let column_width = (self.available_width() - total_spacing) / (num_columns as f32);
|
||||||
|
|
|
@ -2,7 +2,7 @@ use epaint::util::hash;
|
||||||
|
|
||||||
const FIXED_CACHE_SIZE: usize = 1024; // must be small for web/WASM build (for unknown reason)
|
const FIXED_CACHE_SIZE: usize = 1024; // must be small for web/WASM build (for unknown reason)
|
||||||
|
|
||||||
/// Very stupid/simple key-value cache. TODO: improve
|
/// Very stupid/simple key-value cache. TODO(emilk): improve
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct FixedCache<K, V>([Option<(K, V)>; FIXED_CACHE_SIZE]);
|
pub(crate) struct FixedCache<K, V>([Option<(K, V)>; FIXED_CACHE_SIZE]);
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ where
|
||||||
|
|
||||||
/// `(time, value)` pairs
|
/// `(time, value)` pairs
|
||||||
/// Time difference between values can be zero, but never negative.
|
/// Time difference between values can be zero, but never negative.
|
||||||
// TODO: impl IntoIter
|
// TODO(emilk): impl IntoIter
|
||||||
pub fn iter(&'_ self) -> impl ExactSizeIterator<Item = (f64, T)> + '_ {
|
pub fn iter(&'_ self) -> impl ExactSizeIterator<Item = (f64, T)> + '_ {
|
||||||
self.values.iter().map(|(time, value)| (*time, *value))
|
self.values.iter().map(|(time, value)| (*time, *value))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// TODO: it is possible we can simplify `Element` further by
|
// TODO(emilk): it is possible we can simplify `Element` further by
|
||||||
// assuming everything is possibly serializable, and by supplying serialize/deserialize functions for them.
|
// assuming everything is possibly serializable, and by supplying serialize/deserialize functions for them.
|
||||||
// For non-serializable types, these simply return `None`.
|
// For non-serializable types, these simply return `None`.
|
||||||
// This will also allow users to pick their own serialization format per type.
|
// This will also allow users to pick their own serialization format per type.
|
||||||
|
@ -292,7 +292,7 @@ fn from_ron_str<T: serde::de::DeserializeOwned>(ron: &str) -> Option<T> {
|
||||||
|
|
||||||
use crate::Id;
|
use crate::Id;
|
||||||
|
|
||||||
// TODO: make IdTypeMap generic over the key (`Id`), and make a library of IdTypeMap.
|
// TODO(emilk): make IdTypeMap generic over the key (`Id`), and make a library of IdTypeMap.
|
||||||
/// Stores values identified by an [`Id`] AND a the [`std::any::TypeId`] of the value.
|
/// Stores values identified by an [`Id`] AND a the [`std::any::TypeId`] of the value.
|
||||||
///
|
///
|
||||||
/// In other words, it maps `(Id, TypeId)` to any value you want.
|
/// In other words, it maps `(Id, TypeId)` to any value you want.
|
||||||
|
|
|
@ -203,7 +203,7 @@ impl Widget for Button {
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
// TODO: allow checkbox without a text label
|
// TODO(emilk): allow checkbox without a text label
|
||||||
/// Boolean on/off control with text label.
|
/// Boolean on/off control with text label.
|
||||||
///
|
///
|
||||||
/// Usually you'd use [`Ui::checkbox`] instead.
|
/// Usually you'd use [`Ui::checkbox`] instead.
|
||||||
|
|
|
@ -350,7 +350,7 @@ pub fn color_edit_button_hsva(ui: &mut Ui, hsva: &mut Hsva, alpha: Alpha) -> Res
|
||||||
if button_response.clicked() {
|
if button_response.clicked() {
|
||||||
ui.memory().toggle_popup(popup_id);
|
ui.memory().toggle_popup(popup_id);
|
||||||
}
|
}
|
||||||
// TODO: make it easier to show a temporary popup that closes when you click outside it
|
// TODO(emilk): make it easier to show a temporary popup that closes when you click outside it
|
||||||
if ui.memory().is_popup_open(popup_id) {
|
if ui.memory().is_popup_open(popup_id) {
|
||||||
let area_response = Area::new(popup_id)
|
let area_response = Area::new(popup_id)
|
||||||
.order(Order::Foreground)
|
.order(Order::Foreground)
|
||||||
|
|
|
@ -112,7 +112,7 @@ impl<'a> DragValue<'a> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: we should also have a "min precision".
|
// TODO(emilk): we should also have a "min precision".
|
||||||
/// Set a minimum number of decimals to display.
|
/// Set a minimum number of decimals to display.
|
||||||
/// Normally you don't need to pick a precision, as the slider will intelligently pick a precision for you.
|
/// Normally you don't need to pick a precision, as the slider will intelligently pick a precision for you.
|
||||||
/// Regardless of precision the slider will use "smart aim" to help the user select nice, round values.
|
/// Regardless of precision the slider will use "smart aim" to help the user select nice, round values.
|
||||||
|
@ -121,7 +121,7 @@ impl<'a> DragValue<'a> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: we should also have a "max precision".
|
// TODO(emilk): we should also have a "max precision".
|
||||||
/// Set a maximum number of decimals to display.
|
/// Set a maximum number of decimals to display.
|
||||||
/// Values will also be rounded to this number of decimals.
|
/// Values will also be rounded to this number of decimals.
|
||||||
/// Normally you don't need to pick a precision, as the slider will intelligently pick a precision for you.
|
/// Normally you don't need to pick a precision, as the slider will intelligently pick a precision for you.
|
||||||
|
@ -214,7 +214,7 @@ impl<'a> Widget for DragValue<'a> {
|
||||||
)
|
)
|
||||||
.wrap(false)
|
.wrap(false)
|
||||||
.sense(Sense::click_and_drag())
|
.sense(Sense::click_and_drag())
|
||||||
.min_size(ui.spacing().interact_size); // TODO: find some more generic solution to `min_size`
|
.min_size(ui.spacing().interact_size); // TODO(emilk): find some more generic solution to `min_size`
|
||||||
|
|
||||||
let response = ui.add(button);
|
let response = ui.add(button);
|
||||||
let mut response = response.on_hover_cursor(CursorIcon::ResizeHorizontal);
|
let mut response = response.on_hover_cursor(CursorIcon::ResizeHorizontal);
|
||||||
|
@ -223,7 +223,7 @@ impl<'a> Widget for DragValue<'a> {
|
||||||
response = response .on_hover_text(format!(
|
response = response .on_hover_text(format!(
|
||||||
"{}{}{}\nDrag to edit or click to enter a value.\nPress 'Shift' while dragging for better control.",
|
"{}{}{}\nDrag to edit or click to enter a value.\nPress 'Shift' while dragging for better control.",
|
||||||
prefix,
|
prefix,
|
||||||
value as f32, // Show full precision value on-hover. TODO: figure out f64 vs f32
|
value as f32, // Show full precision value on-hover. TODO(emilk): figure out f64 vs f32
|
||||||
suffix
|
suffix
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,7 +116,7 @@ impl Image {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// TODO: builder pattern for Mesh
|
// TODO(emilk): builder pattern for Mesh
|
||||||
let mut mesh = Mesh::with_texture(*texture_id);
|
let mut mesh = Mesh::with_texture(*texture_id);
|
||||||
mesh.add_rect_with_uv(rect, *uv, *tint);
|
mesh.add_rect_with_uv(rect, *uv, *tint);
|
||||||
if let Some((rot, origin)) = rotation {
|
if let Some((rot, origin)) = rotation {
|
||||||
|
|
|
@ -135,7 +135,7 @@ impl Label {
|
||||||
};
|
};
|
||||||
|
|
||||||
if ui.is_grid() {
|
if ui.is_grid() {
|
||||||
// TODO: remove special Grid hacks like these
|
// TODO(emilk): remove special Grid hacks like these
|
||||||
text_job.job.halign = Align::LEFT;
|
text_job.job.halign = Align::LEFT;
|
||||||
text_job.job.justify = false;
|
text_job.job.justify = false;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -347,7 +347,7 @@ impl ExplicitGenerator {
|
||||||
let max_x = *self.x_range.end();
|
let max_x = *self.x_range.end();
|
||||||
let min_y = (self.function)(min_x);
|
let min_y = (self.function)(min_x);
|
||||||
let max_y = (self.function)(max_x);
|
let max_y = (self.function)(max_x);
|
||||||
// TODO: sample some more points
|
// TODO(emilk): sample some more points
|
||||||
PlotBounds {
|
PlotBounds {
|
||||||
min: [min_x, min_y],
|
min: [min_x, min_y],
|
||||||
max: [max_x, max_y],
|
max: [max_x, max_y],
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl Default for CoordinatesFormatter {
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
const MIN_LINE_SPACING_IN_POINTS: f64 = 6.0; // TODO: large enough for a wide label
|
const MIN_LINE_SPACING_IN_POINTS: f64 = 6.0; // TODO(emilk): large enough for a wide label
|
||||||
|
|
||||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -867,7 +867,7 @@ impl PlotUi {
|
||||||
self.next_auto_color_idx += 1;
|
self.next_auto_color_idx += 1;
|
||||||
let golden_ratio = (5.0_f32.sqrt() - 1.0) / 2.0; // 0.61803398875
|
let golden_ratio = (5.0_f32.sqrt() - 1.0) / 2.0; // 0.61803398875
|
||||||
let h = i as f32 * golden_ratio;
|
let h = i as f32 * golden_ratio;
|
||||||
Hsva::new(h, 0.85, 0.5, 1.0).into() // TODO: OkLab or some other perspective color space
|
Hsva::new(h, 0.85, 0.5, 1.0).into() // TODO(emilk): OkLab or some other perspective color space
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ctx(&self) -> &Context {
|
pub fn ctx(&self) -> &Context {
|
||||||
|
|
|
@ -212,7 +212,7 @@ impl<'a> Slider<'a> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: we should also have a "min precision".
|
// TODO(emilk): we should also have a "min precision".
|
||||||
/// Set a minimum number of decimals to display.
|
/// Set a minimum number of decimals to display.
|
||||||
/// Normally you don't need to pick a precision, as the slider will intelligently pick a precision for you.
|
/// Normally you don't need to pick a precision, as the slider will intelligently pick a precision for you.
|
||||||
/// Regardless of precision the slider will use "smart aim" to help the user select nice, round values.
|
/// Regardless of precision the slider will use "smart aim" to help the user select nice, round values.
|
||||||
|
@ -221,7 +221,7 @@ impl<'a> Slider<'a> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: we should also have a "max precision".
|
// TODO(emilk): we should also have a "max precision".
|
||||||
/// Set a maximum number of decimals to display.
|
/// Set a maximum number of decimals to display.
|
||||||
/// Values will also be rounded to this number of decimals.
|
/// Values will also be rounded to this number of decimals.
|
||||||
/// Normally you don't need to pick a precision, as the slider will intelligently pick a precision for you.
|
/// Normally you don't need to pick a precision, as the slider will intelligently pick a precision for you.
|
||||||
|
@ -485,7 +485,7 @@ impl<'a> Slider<'a> {
|
||||||
|
|
||||||
/// delta(value) / delta(points)
|
/// delta(value) / delta(points)
|
||||||
fn current_gradient(&mut self, position_range: &RangeInclusive<f32>) -> f64 {
|
fn current_gradient(&mut self, position_range: &RangeInclusive<f32>) -> f64 {
|
||||||
// TODO: handle clamping
|
// TODO(emilk): handle clamping
|
||||||
let value = self.get_value();
|
let value = self.get_value();
|
||||||
let value_from_pos =
|
let value_from_pos =
|
||||||
|position: f32| self.value_from_position(position, position_range.clone());
|
|position: f32| self.value_from_position(position, position_range.clone());
|
||||||
|
|
|
@ -312,7 +312,7 @@ impl<'t> TextEdit<'t> {
|
||||||
rect: frame_rect,
|
rect: frame_rect,
|
||||||
rounding: visuals.rounding,
|
rounding: visuals.rounding,
|
||||||
fill: ui.visuals().extreme_bg_color,
|
fill: ui.visuals().extreme_bg_color,
|
||||||
stroke: visuals.bg_stroke, // TODO: we want to show something here, or a text-edit field doesn't "pop".
|
stroke: visuals.bg_stroke, // TODO(emilk): we want to show something here, or a text-edit field doesn't "pop".
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -323,7 +323,7 @@ impl<'t> TextEdit<'t> {
|
||||||
// fill: ui.visuals().extreme_bg_color,
|
// fill: ui.visuals().extreme_bg_color,
|
||||||
// fill: visuals.bg_fill,
|
// fill: visuals.bg_fill,
|
||||||
fill: Color32::TRANSPARENT,
|
fill: Color32::TRANSPARENT,
|
||||||
stroke: visuals.bg_stroke, // TODO: we want to show something here, or a text-edit field doesn't "pop".
|
stroke: visuals.bg_stroke, // TODO(emilk): we want to show something here, or a text-edit field doesn't "pop".
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -388,7 +388,7 @@ impl<'t> TextEdit<'t> {
|
||||||
let desired_width = if multiline {
|
let desired_width = if multiline {
|
||||||
galley.size().x.max(wrap_width) // always show everything in multiline
|
galley.size().x.max(wrap_width) // always show everything in multiline
|
||||||
} else {
|
} else {
|
||||||
wrap_width // visual clipping with scroll in singleline input. TODO: opt-in/out?
|
wrap_width // visual clipping with scroll in singleline input. TODO(emilk): opt-in/out?
|
||||||
};
|
};
|
||||||
let desired_height = (desired_height_rows.at_least(1) as f32) * row_height;
|
let desired_height = (desired_height_rows.at_least(1) as f32) * row_height;
|
||||||
let desired_size = vec2(desired_width, galley.size().y.max(desired_height));
|
let desired_size = vec2(desired_width, galley.size().y.max(desired_height));
|
||||||
|
@ -430,7 +430,7 @@ impl<'t> TextEdit<'t> {
|
||||||
ui.output().mutable_text_under_cursor = true;
|
ui.output().mutable_text_under_cursor = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: drag selected text to either move or clone (ctrl on windows, alt on mac)
|
// TODO(emilk): drag selected text to either move or clone (ctrl on windows, alt on mac)
|
||||||
let singleline_offset = vec2(state.singleline_offset, 0.0);
|
let singleline_offset = vec2(state.singleline_offset, 0.0);
|
||||||
let cursor_at_pointer =
|
let cursor_at_pointer =
|
||||||
galley.cursor_from_pos(pointer_pos - response.rect.min + singleline_offset);
|
galley.cursor_from_pos(pointer_pos - response.rect.min + singleline_offset);
|
||||||
|
@ -693,7 +693,7 @@ fn events(
|
||||||
|
|
||||||
let mut any_change = false;
|
let mut any_change = false;
|
||||||
|
|
||||||
let events = ui.input().events.clone(); // avoid dead-lock by cloning. TODO: optimize
|
let events = ui.input().events.clone(); // avoid dead-lock by cloning. TODO(emilk): optimize
|
||||||
for event in &events {
|
for event in &events {
|
||||||
let did_mutate_text = match event {
|
let did_mutate_text = match event {
|
||||||
Event::Copy => {
|
Event::Copy => {
|
||||||
|
@ -740,7 +740,7 @@ fn events(
|
||||||
if multiline && ui.memory().has_lock_focus(id) {
|
if multiline && ui.memory().has_lock_focus(id) {
|
||||||
let mut ccursor = delete_selected(text, &cursor_range);
|
let mut ccursor = delete_selected(text, &cursor_range);
|
||||||
if modifiers.shift {
|
if modifiers.shift {
|
||||||
// TODO: support removing indentation over a selection?
|
// TODO(emilk): support removing indentation over a selection?
|
||||||
decrease_identation(&mut ccursor, text);
|
decrease_identation(&mut ccursor, text);
|
||||||
} else {
|
} else {
|
||||||
insert_text(&mut ccursor, text, "\t");
|
insert_text(&mut ccursor, text, "\t");
|
||||||
|
@ -758,7 +758,7 @@ fn events(
|
||||||
if multiline {
|
if multiline {
|
||||||
let mut ccursor = delete_selected(text, &cursor_range);
|
let mut ccursor = delete_selected(text, &cursor_range);
|
||||||
insert_text(&mut ccursor, text, "\n");
|
insert_text(&mut ccursor, text, "\n");
|
||||||
// TODO: if code editor, auto-indent by same leading tabs, + one if the lines end on an opening bracket
|
// TODO(emilk): if code editor, auto-indent by same leading tabs, + one if the lines end on an opening bracket
|
||||||
Some(CCursorRange::one(ccursor))
|
Some(CCursorRange::one(ccursor))
|
||||||
} else {
|
} else {
|
||||||
ui.memory().surrender_focus(id); // End input with enter
|
ui.memory().surrender_focus(id); // End input with enter
|
||||||
|
@ -770,7 +770,7 @@ fn events(
|
||||||
pressed: true,
|
pressed: true,
|
||||||
modifiers,
|
modifiers,
|
||||||
} if modifiers.command && !modifiers.shift => {
|
} if modifiers.command && !modifiers.shift => {
|
||||||
// TODO: redo
|
// TODO(emilk): redo
|
||||||
if let Some((undo_ccursor_range, undo_txt)) = state
|
if let Some((undo_ccursor_range, undo_txt)) = state
|
||||||
.undoer
|
.undoer
|
||||||
.lock()
|
.lock()
|
||||||
|
|
|
@ -21,4 +21,4 @@ pub struct TextEditOutput {
|
||||||
pub cursor_range: Option<super::CursorRange>,
|
pub cursor_range: Option<super::CursorRange>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add `output.paint` and `output.store` and split out that code from `TextEdit::show`.
|
// TODO(emilk): add `output.paint` and `output.store` and split out that code from `TextEdit::show`.
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl FrameHistory {
|
||||||
|
|
||||||
let history = &self.frame_times;
|
let history = &self.frame_times;
|
||||||
|
|
||||||
// TODO: we should not use `slider_width` as default graph width.
|
// TODO(emilk): we should not use `slider_width` as default graph width.
|
||||||
let height = ui.spacing().slider_width;
|
let height = ui.spacing().slider_width;
|
||||||
let size = vec2(ui.available_size_before_wrap().x, height);
|
let size = vec2(ui.available_size_before_wrap().x, height);
|
||||||
let (rect, response) = ui.allocate_at_least(size, Sense::hover());
|
let (rect, response) = ui.allocate_at_least(size, Sense::hover());
|
||||||
|
|
|
@ -300,7 +300,7 @@ impl WrapApp {
|
||||||
|
|
||||||
ui.with_layout(egui::Layout::right_to_left(), |ui| {
|
ui.with_layout(egui::Layout::right_to_left(), |ui| {
|
||||||
if false {
|
if false {
|
||||||
// TODO: fix the overlap on small screens
|
// TODO(emilk): fix the overlap on small screens
|
||||||
if let Some(seconds_since_midnight) = crate::seconds_since_midnight() {
|
if let Some(seconds_since_midnight) = crate::seconds_since_midnight() {
|
||||||
if clock_button(ui, seconds_since_midnight).clicked() {
|
if clock_button(ui, seconds_since_midnight).clicked() {
|
||||||
self.state.selected_anchor = "clock".to_owned();
|
self.state.selected_anchor = "clock".to_owned();
|
||||||
|
|
|
@ -90,7 +90,7 @@ impl ColorTest {
|
||||||
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
// TODO: test color multiplication (image tint),
|
// TODO(emilk): test color multiplication (image tint),
|
||||||
// to make sure vertex and texture color multiplication is done in linear space.
|
// to make sure vertex and texture color multiplication is done in linear space.
|
||||||
|
|
||||||
self.show_gradients(ui, WHITE, (RED, GREEN));
|
self.show_gradients(ui, WHITE, (RED, GREEN));
|
||||||
|
|
|
@ -64,7 +64,7 @@ impl EasyMarkEditor {
|
||||||
ScrollArea::vertical()
|
ScrollArea::vertical()
|
||||||
.id_source("rendered")
|
.id_source("rendered")
|
||||||
.show(&mut columns[1], |ui| {
|
.show(&mut columns[1], |ui| {
|
||||||
// TODO: we can save some more CPU by caching the rendered output.
|
// TODO(emilk): we can save some more CPU by caching the rendered output.
|
||||||
crate::easy_mark::easy_mark(ui, &self.code);
|
crate::easy_mark::easy_mark(ui, &self.code);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum Item<'a> {
|
pub enum Item<'a> {
|
||||||
/// `\n`
|
/// `\n`
|
||||||
// TODO: add Style here so empty heading still uses up the right amount of space.
|
// TODO(emilk): add Style here so empty heading still uses up the right amount of space.
|
||||||
Newline,
|
Newline,
|
||||||
///
|
///
|
||||||
Text(Style, &'a str),
|
Text(Style, &'a str),
|
||||||
|
|
|
@ -95,7 +95,7 @@ impl<'a> Widget for DatePickerButton<'a> {
|
||||||
if pos.x + width_with_padding > ui.clip_rect().right() {
|
if pos.x + width_with_padding > ui.clip_rect().right() {
|
||||||
pos.x = button_response.rect.right() - width_with_padding;
|
pos.x = button_response.rect.right() - width_with_padding;
|
||||||
}
|
}
|
||||||
//TODO: Better positioning
|
//TODO(elwerene): Better positioning
|
||||||
|
|
||||||
let area_response = Area::new(ui.make_persistent_id(&self.id_source))
|
let area_response = Area::new(ui.make_persistent_id(&self.id_source))
|
||||||
.order(Order::Foreground)
|
.order(Order::Foreground)
|
||||||
|
|
|
@ -257,7 +257,7 @@ impl<'a> DatePickerPopup<'a> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: Locale
|
//TODO(elwerene): Locale
|
||||||
for name in ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"] {
|
for name in ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"] {
|
||||||
header.col(|ui| {
|
header.col(|ui| {
|
||||||
ui.with_layout(
|
ui.with_layout(
|
||||||
|
|
|
@ -296,7 +296,7 @@ impl<'a> Table<'a> {
|
||||||
|
|
||||||
let bottom = ui.min_rect().bottom();
|
let bottom = ui.min_rect().bottom();
|
||||||
|
|
||||||
// TODO: fix frame-delay by interacting before laying out (but painting later).
|
// TODO(emilk): fix frame-delay by interacting before laying out (but painting later).
|
||||||
if let Some(resize_id) = resize_id {
|
if let Some(resize_id) = resize_id {
|
||||||
let spacing_x = ui.spacing().item_spacing.x;
|
let spacing_x = ui.spacing().item_spacing.x;
|
||||||
let mut x = avail_rect.left() - spacing_x * 0.5;
|
let mut x = avail_rect.left() - spacing_x * 0.5;
|
||||||
|
|
|
@ -83,7 +83,7 @@ fn main() {
|
||||||
|
|
||||||
egui_glium.on_event(&event);
|
egui_glium.on_event(&event);
|
||||||
|
|
||||||
display.gl_window().window().request_redraw(); // TODO: ask egui if the events warrants a repaint instead
|
display.gl_window().window().request_redraw(); // TODO(emilk): ask egui if the events warrants a repaint instead
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => (),
|
_ => (),
|
||||||
|
|
|
@ -64,7 +64,7 @@ fn main() {
|
||||||
|
|
||||||
egui_glium.on_event(&event);
|
egui_glium.on_event(&event);
|
||||||
|
|
||||||
display.gl_window().window().request_redraw(); // TODO: ask egui if the events warrants a repaint instead
|
display.gl_window().window().request_redraw(); // TODO(emilk): ask egui if the events warrants a repaint instead
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => (),
|
_ => (),
|
||||||
|
|
|
@ -133,11 +133,11 @@ impl Painter {
|
||||||
|
|
||||||
let vertices: &[Vertex] = bytemuck::cast_slice(&mesh.vertices);
|
let vertices: &[Vertex] = bytemuck::cast_slice(&mesh.vertices);
|
||||||
|
|
||||||
// TODO: we should probably reuse the [`VertexBuffer`] instead of allocating a new one each frame.
|
// TODO(emilk): we should probably reuse the [`VertexBuffer`] instead of allocating a new one each frame.
|
||||||
glium::VertexBuffer::new(display, vertices).unwrap()
|
glium::VertexBuffer::new(display, vertices).unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: we should probably reuse the [`IndexBuffer`] instead of allocating a new one each frame.
|
// TODO(emilk): we should probably reuse the [`IndexBuffer`] instead of allocating a new one each frame.
|
||||||
let index_buffer =
|
let index_buffer =
|
||||||
glium::IndexBuffer::new(display, PrimitiveType::TrianglesList, &mesh.indices).unwrap();
|
glium::IndexBuffer::new(display, PrimitiveType::TrianglesList, &mesh.indices).unwrap();
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ fn main() {
|
||||||
|
|
||||||
egui_glow.on_event(&event);
|
egui_glow.on_event(&event);
|
||||||
|
|
||||||
gl_window.window().request_redraw(); // TODO: ask egui if the events warrants a repaint instead
|
gl_window.window().request_redraw(); // TODO(emilk): ask egui if the events warrants a repaint instead
|
||||||
}
|
}
|
||||||
glutin::event::Event::LoopDestroyed => {
|
glutin::event::Event::LoopDestroyed => {
|
||||||
egui_glow.destroy();
|
egui_glow.destroy();
|
||||||
|
|
|
@ -68,7 +68,7 @@ pub struct Painter {
|
||||||
|
|
||||||
textures: HashMap<egui::TextureId, glow::Texture>,
|
textures: HashMap<egui::TextureId, glow::Texture>,
|
||||||
|
|
||||||
next_native_tex_id: u64, // TODO: 128-bit texture space?
|
next_native_tex_id: u64,
|
||||||
|
|
||||||
/// Stores outdated OpenGL textures that are yet to be deleted
|
/// Stores outdated OpenGL textures that are yet to be deleted
|
||||||
textures_to_destroy: Vec<glow::Texture>,
|
textures_to_destroy: Vec<glow::Texture>,
|
||||||
|
|
|
@ -88,7 +88,7 @@ impl PostProcess {
|
||||||
|
|
||||||
// ---------------------------------------------------------
|
// ---------------------------------------------------------
|
||||||
// Depth buffer - we only need this when embedding 3D within egui using `egui::PaintCallback`.
|
// Depth buffer - we only need this when embedding 3D within egui using `egui::PaintCallback`.
|
||||||
// TODO: add a setting to enable/disable the depth buffer.
|
// TODO(emilk): add a setting to enable/disable the depth buffer.
|
||||||
|
|
||||||
let with_depth_buffer = true;
|
let with_depth_buffer = true;
|
||||||
let depth_renderbuffer = if with_depth_buffer {
|
let depth_renderbuffer = if with_depth_buffer {
|
||||||
|
|
|
@ -145,7 +145,7 @@ pub fn format_with_decimals_in_range(value: f64, decimal_range: RangeInclusive<u
|
||||||
let min_decimals = min_decimals.min(max_decimals);
|
let min_decimals = min_decimals.min(max_decimals);
|
||||||
|
|
||||||
if min_decimals != max_decimals {
|
if min_decimals != max_decimals {
|
||||||
// Ugly/slow way of doing this. TODO: clean up precision.
|
// Ugly/slow way of doing this. TODO(emilk): clean up precision.
|
||||||
for decimals in min_decimals..max_decimals {
|
for decimals in min_decimals..max_decimals {
|
||||||
let text = format!("{:.*}", decimals, value);
|
let text = format!("{:.*}", decimals, value);
|
||||||
let epsilon = 16.0 * f32::EPSILON; // margin large enough to handle most peoples round-tripping needs
|
let epsilon = 16.0 * f32::EPSILON; // margin large enough to handle most peoples round-tripping needs
|
||||||
|
|
|
@ -127,7 +127,7 @@ fn test_aim() {
|
||||||
assert_eq!(best_in_range_f64(12.3, 65.9), 50.0, "Prefer leading 5");
|
assert_eq!(best_in_range_f64(12.3, 65.9), 50.0, "Prefer leading 5");
|
||||||
assert_eq!(best_in_range_f64(493.0, 879.0), 500.0, "Prefer leading 5");
|
assert_eq!(best_in_range_f64(493.0, 879.0), 500.0, "Prefer leading 5");
|
||||||
assert_eq!(best_in_range_f64(0.37, 0.48), 0.40);
|
assert_eq!(best_in_range_f64(0.37, 0.48), 0.40);
|
||||||
// assert_eq!(best_in_range_f64(123.71, 123.76), 123.75); // TODO: we get 123.74999999999999 here
|
// assert_eq!(best_in_range_f64(123.71, 123.76), 123.75); // TODO(emilk): we get 123.74999999999999 here
|
||||||
// assert_eq!(best_in_range_f32(123.71, 123.76), 123.75);
|
// assert_eq!(best_in_range_f32(123.71, 123.76), 123.75);
|
||||||
assert_eq!(best_in_range_f64(7.5, 16.3), 10.0);
|
assert_eq!(best_in_range_f64(7.5, 16.3), 10.0);
|
||||||
assert_eq!(best_in_range_f64(7.5, 76.3), 10.0);
|
assert_eq!(best_in_range_f64(7.5, 76.3), 10.0);
|
||||||
|
|
|
@ -38,7 +38,7 @@ pub struct Mesh {
|
||||||
|
|
||||||
/// The texture to use when drawing these triangles.
|
/// The texture to use when drawing these triangles.
|
||||||
pub texture_id: TextureId,
|
pub texture_id: TextureId,
|
||||||
// TODO: bounding rectangle
|
// TODO(emilk): bounding rectangle
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Mesh {
|
impl Mesh {
|
||||||
|
|
|
@ -47,7 +47,7 @@ impl Shadow {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tessellate(&self, rect: emath::Rect, rounding: impl Into<Rounding>) -> Mesh {
|
pub fn tessellate(&self, rect: emath::Rect, rounding: impl Into<Rounding>) -> Mesh {
|
||||||
// tessellator.clip_rect = clip_rect; // TODO: culling
|
// tessellator.clip_rect = clip_rect; // TODO(emilk): culling
|
||||||
|
|
||||||
let Self { extrusion, color } = *self;
|
let Self { extrusion, color } = *self;
|
||||||
|
|
||||||
|
|
|
@ -339,7 +339,7 @@ impl Path {
|
||||||
pub fn add_circle(&mut self, center: Pos2, radius: f32) {
|
pub fn add_circle(&mut self, center: Pos2, radius: f32) {
|
||||||
use precomputed_vertices::*;
|
use precomputed_vertices::*;
|
||||||
|
|
||||||
// These cutoffs are based on a high-dpi display. TODO: use pixels_per_point here?
|
// These cutoffs are based on a high-dpi display. TODO(emilk): use pixels_per_point here?
|
||||||
// same cutoffs as in add_circle_quadrant
|
// same cutoffs as in add_circle_quadrant
|
||||||
|
|
||||||
if radius <= 2.0 {
|
if radius <= 2.0 {
|
||||||
|
@ -547,7 +547,7 @@ pub mod path {
|
||||||
pub fn add_circle_quadrant(path: &mut Vec<Pos2>, center: Pos2, radius: f32, quadrant: f32) {
|
pub fn add_circle_quadrant(path: &mut Vec<Pos2>, center: Pos2, radius: f32, quadrant: f32) {
|
||||||
use super::precomputed_vertices::*;
|
use super::precomputed_vertices::*;
|
||||||
|
|
||||||
// These cutoffs are based on a high-dpi display. TODO: use pixels_per_point here?
|
// These cutoffs are based on a high-dpi display. TODO(emilk): use pixels_per_point here?
|
||||||
// same cutoffs as in add_circle
|
// same cutoffs as in add_circle
|
||||||
|
|
||||||
if radius <= 0.0 {
|
if radius <= 0.0 {
|
||||||
|
@ -1171,7 +1171,7 @@ impl Tessellator {
|
||||||
let cutoff_radius = radius_px * 2.0_f32.powf(0.25);
|
let cutoff_radius = radius_px * 2.0_f32.powf(0.25);
|
||||||
|
|
||||||
// Find the right disc radius for a crisp edge:
|
// Find the right disc radius for a crisp edge:
|
||||||
// TODO: perhaps we can do something faster than this linear search.
|
// TODO(emilk): perhaps we can do something faster than this linear search.
|
||||||
for disc in &self.prepared_discs {
|
for disc in &self.prepared_discs {
|
||||||
if cutoff_radius <= disc.r {
|
if cutoff_radius <= disc.r {
|
||||||
let side = radius_px * disc.w / (self.pixels_per_point * disc.r);
|
let side = radius_px * disc.w / (self.pixels_per_point * disc.r);
|
||||||
|
|
|
@ -66,7 +66,7 @@ pub struct FontImpl {
|
||||||
// move each character by this much (hack)
|
// move each character by this much (hack)
|
||||||
y_offset: f32,
|
y_offset: f32,
|
||||||
pixels_per_point: f32,
|
pixels_per_point: f32,
|
||||||
glyph_info_cache: RwLock<AHashMap<char, GlyphInfo>>, // TODO: standard Mutex
|
glyph_info_cache: RwLock<AHashMap<char, GlyphInfo>>, // TODO(emilk): standard Mutex
|
||||||
atlas: Arc<Mutex<TextureAtlas>>,
|
atlas: Arc<Mutex<TextureAtlas>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ impl FontImpl {
|
||||||
|
|
||||||
let height_in_points = scale_in_pixels as f32 / pixels_per_point;
|
let height_in_points = scale_in_pixels as f32 / pixels_per_point;
|
||||||
|
|
||||||
// TODO: use these font metrics?
|
// TODO(emilk): use these font metrics?
|
||||||
// use ab_glyph::ScaleFont as _;
|
// use ab_glyph::ScaleFont as _;
|
||||||
// let scaled = ab_glyph_font.as_scaled(scale_in_pixels as f32);
|
// let scaled = ab_glyph_font.as_scaled(scale_in_pixels as f32);
|
||||||
// dbg!(scaled.ascent());
|
// dbg!(scaled.ascent());
|
||||||
|
@ -212,7 +212,7 @@ impl FontImpl {
|
||||||
|
|
||||||
type FontIndex = usize;
|
type FontIndex = usize;
|
||||||
|
|
||||||
// TODO: rename?
|
// TODO(emilk): rename?
|
||||||
/// Wrapper over multiple [`FontImpl`] (e.g. a primary + fallbacks for emojis)
|
/// Wrapper over multiple [`FontImpl`] (e.g. a primary + fallbacks for emojis)
|
||||||
pub struct Font {
|
pub struct Font {
|
||||||
fonts: Vec<Arc<FontImpl>>,
|
fonts: Vec<Arc<FontImpl>>,
|
||||||
|
@ -349,7 +349,7 @@ fn invisible_char(c: char) -> bool {
|
||||||
// See https://github.com/emilk/egui/issues/336
|
// See https://github.com/emilk/egui/issues/336
|
||||||
|
|
||||||
// From https://www.fileformat.info/info/unicode/category/Cf/list.htm
|
// From https://www.fileformat.info/info/unicode/category/Cf/list.htm
|
||||||
('\u{200B}'..='\u{206F}').contains(&c) // TODO: heed bidi characters
|
('\u{200B}'..='\u{206F}').contains(&c) // TODO(emilk): heed bidi characters
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allocate_glyph(
|
fn allocate_glyph(
|
||||||
|
|
|
@ -22,7 +22,7 @@ pub struct FontId {
|
||||||
|
|
||||||
/// What font family to use.
|
/// What font family to use.
|
||||||
pub family: FontFamily,
|
pub family: FontFamily,
|
||||||
// TODO: weight (bold), italics, …
|
// TODO(emilk): weight (bold), italics, …
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for FontId {
|
impl Default for FontId {
|
||||||
|
@ -240,7 +240,6 @@ pub struct FontDefinitions {
|
||||||
/// When looking for a character glyph `epaint` will start with
|
/// When looking for a character glyph `epaint` will start with
|
||||||
/// the first font and then move to the second, and so on.
|
/// the first font and then move to the second, and so on.
|
||||||
/// So the first font is the primary, and then comes a list of fallbacks in order of priority.
|
/// So the first font is the primary, and then comes a list of fallbacks in order of priority.
|
||||||
// TODO: per font size-modifier.
|
|
||||||
pub families: BTreeMap<FontFamily, Vec<String>>,
|
pub families: BTreeMap<FontFamily, Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,7 +617,7 @@ struct GalleyCache {
|
||||||
|
|
||||||
impl GalleyCache {
|
impl GalleyCache {
|
||||||
fn layout(&mut self, fonts: &mut FontsImpl, job: LayoutJob) -> Arc<Galley> {
|
fn layout(&mut self, fonts: &mut FontsImpl, job: LayoutJob) -> Arc<Galley> {
|
||||||
let hash = crate::util::hash(&job); // TODO: even faster hasher?
|
let hash = crate::util::hash(&job); // TODO(emilk): even faster hasher?
|
||||||
|
|
||||||
match self.cache.entry(hash) {
|
match self.cache.entry(hash) {
|
||||||
std::collections::hash_map::Entry::Occupied(entry) => {
|
std::collections::hash_map::Entry::Occupied(entry) => {
|
||||||
|
|
|
@ -98,7 +98,7 @@ fn layout_section(
|
||||||
|
|
||||||
let mut paragraph = out_paragraphs.last_mut().unwrap();
|
let mut paragraph = out_paragraphs.last_mut().unwrap();
|
||||||
if paragraph.glyphs.is_empty() {
|
if paragraph.glyphs.is_empty() {
|
||||||
paragraph.empty_paragraph_height = font_height; // TODO: replace this hack with actually including `\n` in the glyphs?
|
paragraph.empty_paragraph_height = font_height; // TODO(emilk): replace this hack with actually including `\n` in the glyphs?
|
||||||
}
|
}
|
||||||
|
|
||||||
paragraph.cursor_x += leading_space;
|
paragraph.cursor_x += leading_space;
|
||||||
|
@ -109,7 +109,7 @@ fn layout_section(
|
||||||
if job.break_on_newline && chr == '\n' {
|
if job.break_on_newline && chr == '\n' {
|
||||||
out_paragraphs.push(Paragraph::default());
|
out_paragraphs.push(Paragraph::default());
|
||||||
paragraph = out_paragraphs.last_mut().unwrap();
|
paragraph = out_paragraphs.last_mut().unwrap();
|
||||||
paragraph.empty_paragraph_height = font_height; // TODO: replace this hack with actually including `\n` in the glyphs?
|
paragraph.empty_paragraph_height = font_height; // TODO(emilk): replace this hack with actually including `\n` in the glyphs?
|
||||||
} else {
|
} else {
|
||||||
let (font_impl, glyph_info) = font.glyph_info_and_font_impl(chr);
|
let (font_impl, glyph_info) = font.glyph_info_and_font_impl(chr);
|
||||||
if let Some(font_impl) = font_impl {
|
if let Some(font_impl) = font_impl {
|
||||||
|
@ -207,7 +207,7 @@ fn line_break(
|
||||||
&& !row_break_candidates.has_good_candidate(job.wrap.break_anywhere)
|
&& !row_break_candidates.has_good_candidate(job.wrap.break_anywhere)
|
||||||
{
|
{
|
||||||
// Allow the first row to be completely empty, because we know there will be more space on the next row:
|
// Allow the first row to be completely empty, because we know there will be more space on the next row:
|
||||||
// TODO: this records the height of this first row as zero, though that is probably fine since first_row_indentation usually comes with a first_row_min_height.
|
// TODO(emilk): this records the height of this first row as zero, though that is probably fine since first_row_indentation usually comes with a first_row_min_height.
|
||||||
out_rows.push(Row {
|
out_rows.push(Row {
|
||||||
glyphs: vec![],
|
glyphs: vec![],
|
||||||
visuals: Default::default(),
|
visuals: Default::default(),
|
||||||
|
@ -685,7 +685,7 @@ fn add_hline(point_scale: PointScale, [start, stop]: [Pos2; 2], stroke: Stroke,
|
||||||
let antialiased = true;
|
let antialiased = true;
|
||||||
|
|
||||||
if antialiased {
|
if antialiased {
|
||||||
let mut path = crate::tessellator::Path::default(); // TODO: reuse this to avoid re-allocations.
|
let mut path = crate::tessellator::Path::default(); // TODO(emilk): reuse this to avoid re-allocations.
|
||||||
path.add_line_segment([start, stop]);
|
path.add_line_segment([start, stop]);
|
||||||
let feathering = 1.0 / point_scale.pixels_per_point();
|
let feathering = 1.0 / point_scale.pixels_per_point();
|
||||||
path.stroke_open(feathering, stroke, mesh);
|
path.stroke_open(feathering, stroke, mesh);
|
||||||
|
|
|
@ -227,7 +227,7 @@ pub struct TextFormat {
|
||||||
/// If you use a small font and [`Align::TOP`] you
|
/// If you use a small font and [`Align::TOP`] you
|
||||||
/// can get the effect of raised text.
|
/// can get the effect of raised text.
|
||||||
pub valign: Align,
|
pub valign: Align,
|
||||||
// TODO: lowered
|
// TODO(emilk): lowered
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TextFormat {
|
impl Default for TextFormat {
|
||||||
|
@ -735,7 +735,7 @@ impl Galley {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: return identical cursor, or clamp?
|
// TODO(emilk): return identical cursor, or clamp?
|
||||||
pub fn from_pcursor(&self, pcursor: PCursor) -> Cursor {
|
pub fn from_pcursor(&self, pcursor: PCursor) -> Cursor {
|
||||||
let prefer_next_row = pcursor.prefer_next_row;
|
let prefer_next_row = pcursor.prefer_next_row;
|
||||||
let mut ccursor_it = CCursor {
|
let mut ccursor_it = CCursor {
|
||||||
|
|
|
@ -87,7 +87,7 @@ impl TextureAtlas {
|
||||||
image[pos] = 1.0;
|
image[pos] = 1.0;
|
||||||
|
|
||||||
// Allocate a series of anti-aliased discs used to render small filled circles:
|
// Allocate a series of anti-aliased discs used to render small filled circles:
|
||||||
// TODO: these circles can be packed A LOT better.
|
// TODO(emilk): these circles can be packed A LOT better.
|
||||||
// In fact, the whole texture atlas could be packed a lot better.
|
// In fact, the whole texture atlas could be packed a lot better.
|
||||||
// for r in [1, 2, 4, 8, 16, 32, 64] {
|
// for r in [1, 2, 4, 8, 16, 32, 64] {
|
||||||
// let w = 2 * r + 3;
|
// let w = 2 * r + 3;
|
||||||
|
|
|
@ -49,7 +49,7 @@ cargo doc --document-private-items --no-deps --all-features
|
||||||
# cargo install cargo-deny
|
# cargo install cargo-deny
|
||||||
cargo deny check
|
cargo deny check
|
||||||
|
|
||||||
# TODO: consider using https://github.com/taiki-e/cargo-hack or https://github.com/frewsxcv/cargo-all-features
|
# TODO(emilk): consider using https://github.com/taiki-e/cargo-hack or https://github.com/frewsxcv/cargo-all-features
|
||||||
|
|
||||||
# ------------------------------------------------------------
|
# ------------------------------------------------------------
|
||||||
#
|
#
|
||||||
|
|
Loading…
Reference in a new issue