Allow changing doc pages
This commit is contained in:
74
docs/miscellaneous.md
Normal file
74
docs/miscellaneous.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Miscellaneous
|
||||
|
||||
This document covers a variety of topics that don't fit into any other category.
|
||||
|
||||
## Remote Print HTTP Status Proxy
|
||||
|
||||
Part of the process to upload a model to a printer with remote print is to serve the .goo file on a http server, then send the download link to the printer over MQTT. Because remote print already has to run a HTTP server, this option exposes an api at `0.0.0.0:<http_port>/status`. Each time remote print starts all server port are randomized and printed to the log (check the console or the Log panel).
|
||||
|
||||
The status route returns an array of printers, each with the following format.
|
||||
|
||||
```
|
||||
struct Printer {
|
||||
machineId: String,
|
||||
attributes: Attributes,
|
||||
status: Status,
|
||||
lastUpdate: i64,
|
||||
}
|
||||
```
|
||||
|
||||
The `Attributes` structure is passed directly from the printer's innitial handshake message. I'm honestly not sure what all the fields are for.
|
||||
|
||||
```
|
||||
struct Attributes {
|
||||
Name: String,
|
||||
MachineName: String,
|
||||
ProtocolVersion: String,
|
||||
FirmwareVersion: String,
|
||||
Resolution: Resolution,
|
||||
MainboardIP: String,
|
||||
MainboardID: String,
|
||||
SDCPStatus: u8,
|
||||
LocalSDCPAddress: String,
|
||||
SDCPAddress: String,
|
||||
Capabilities: Capability[],
|
||||
}
|
||||
|
||||
enum Capability {
|
||||
FILE_TRANSFER,
|
||||
PRINT_CONTROL
|
||||
}
|
||||
```
|
||||
|
||||
Finally, this data is sent from the printer over MQTT every few seconds.
|
||||
|
||||
```
|
||||
struct Status {
|
||||
CurrentStatus: CurrentStatus,
|
||||
PreviousStatus: u8,
|
||||
PrintInfo: PrintInfo,
|
||||
FileTransferInfo: FileTransferInfo,
|
||||
}
|
||||
|
||||
enum CurrentStatus {
|
||||
Ready,
|
||||
Busy,
|
||||
TransferringFile
|
||||
}
|
||||
|
||||
enum PrintInfoStatus {
|
||||
None,
|
||||
InitialLower,
|
||||
Lowering,
|
||||
Exposure,
|
||||
Retracting,
|
||||
FinalRetract,
|
||||
Complete
|
||||
}
|
||||
|
||||
enum FileTransferStatus {
|
||||
None,
|
||||
Done,
|
||||
Error
|
||||
}
|
||||
```
|
@@ -3,3 +3,4 @@
|
||||
This pages can also be viewed directly in mslcier on the `About` panel.
|
||||
|
||||
- [Getting Started](getting_started.md)
|
||||
- [Miscellaneous](miscellaneous.md)
|
||||
|
@@ -1,16 +1,18 @@
|
||||
use bitflags::bitflags;
|
||||
use egui::{Align, Layout, RichText, Sense, TextStyle, Ui, Vec2};
|
||||
use egui::{Align, Layout, RichText, Sense, Shape, TextStyle, Ui, Vec2, Visuals};
|
||||
use markdown::{Block, Span};
|
||||
|
||||
const BODY_SIZE: f32 = 12.5;
|
||||
const HEADING_SIZES: [f32; 6] = [18.0, 16.0, 14.0, 12.0, 10.0, 8.0];
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct CompiledMarkdown {
|
||||
nodes: Vec<Node>,
|
||||
}
|
||||
|
||||
enum Node {
|
||||
Body(Vec<BodyNode>),
|
||||
Code(String),
|
||||
Break,
|
||||
}
|
||||
|
||||
@@ -37,33 +39,11 @@ bitflags! {
|
||||
}
|
||||
}
|
||||
|
||||
impl TextFlags {
|
||||
pub fn apply(&self, mut text: RichText) -> RichText {
|
||||
if self.contains(TextFlags::HEADER) {
|
||||
text = text.heading();
|
||||
}
|
||||
|
||||
if self.contains(TextFlags::WEAK) {
|
||||
text = text.weak();
|
||||
}
|
||||
|
||||
if self.contains(TextFlags::BOLD) {
|
||||
text = text.strong();
|
||||
}
|
||||
|
||||
if self.contains(TextFlags::ITALIC) {
|
||||
text = text.italics();
|
||||
}
|
||||
|
||||
if self.contains(TextFlags::MONOSPACE) {
|
||||
text = text.monospace();
|
||||
}
|
||||
|
||||
text
|
||||
}
|
||||
}
|
||||
|
||||
impl CompiledMarkdown {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.nodes.is_empty()
|
||||
}
|
||||
|
||||
pub fn compile(source: &str) -> Self {
|
||||
let mut nodes = Vec::new();
|
||||
|
||||
@@ -77,14 +57,18 @@ impl CompiledMarkdown {
|
||||
}
|
||||
|
||||
nodes.push(Node::Body(span_text(span, HEADING_SIZES[level - 1], flags)));
|
||||
nodes.push(Node::Break);
|
||||
}
|
||||
Block::Paragraph(span) => {
|
||||
nodes.push(Node::Body(span_text(span, BODY_SIZE, TextFlags::empty())));
|
||||
nodes.push(Node::Break);
|
||||
nodes.push(Node::Body(span_text(span, BODY_SIZE, TextFlags::empty())))
|
||||
}
|
||||
Block::CodeBlock(_lang, code) => nodes.push(Node::Code(code)),
|
||||
_ => {}
|
||||
}
|
||||
nodes.push(Node::Break);
|
||||
}
|
||||
|
||||
if let Some(Node::Break) = nodes.last() {
|
||||
nodes.pop();
|
||||
}
|
||||
|
||||
Self { nodes }
|
||||
@@ -105,7 +89,12 @@ impl CompiledMarkdown {
|
||||
for node in body_nodes {
|
||||
match node {
|
||||
BodyNode::Text { text, size, flags } => {
|
||||
ui.label(flags.apply(RichText::new(text).size(*size)));
|
||||
ui.label(
|
||||
flags.apply(
|
||||
ui.visuals(),
|
||||
RichText::new(text).size(*size),
|
||||
),
|
||||
);
|
||||
}
|
||||
BodyNode::Link { text, url } => {
|
||||
ui.hyperlink_to(text, url).on_hover_text(url);
|
||||
@@ -113,6 +102,13 @@ impl CompiledMarkdown {
|
||||
}
|
||||
}
|
||||
}
|
||||
Node::Code(code) => {
|
||||
let placeholder = ui.painter().add(Shape::Noop);
|
||||
let mut rect = ui.monospace(code).rect.expand(1.0);
|
||||
rect.max.x = ui.max_rect().max.x;
|
||||
let shape = Shape::rect_filled(rect, 2.0, ui.visuals().code_bg_color);
|
||||
ui.painter().set(placeholder, shape);
|
||||
}
|
||||
Node::Break => {
|
||||
ui.allocate_exact_size(Vec2::new(0.0, row_height), Sense::hover());
|
||||
ui.end_row();
|
||||
@@ -125,6 +121,32 @@ impl CompiledMarkdown {
|
||||
}
|
||||
}
|
||||
|
||||
impl TextFlags {
|
||||
pub fn apply(&self, visuals: &Visuals, mut text: RichText) -> RichText {
|
||||
if self.contains(TextFlags::HEADER) {
|
||||
text = text.heading();
|
||||
}
|
||||
|
||||
if self.contains(TextFlags::WEAK) {
|
||||
text = text.weak();
|
||||
}
|
||||
|
||||
if self.contains(TextFlags::BOLD) {
|
||||
text = text.strong();
|
||||
}
|
||||
|
||||
if self.contains(TextFlags::ITALIC) {
|
||||
text = text.italics();
|
||||
}
|
||||
|
||||
if self.contains(TextFlags::MONOSPACE) {
|
||||
text = text.monospace().background_color(visuals.code_bg_color);
|
||||
}
|
||||
|
||||
text
|
||||
}
|
||||
}
|
||||
|
||||
fn span_text(span: Vec<Span>, size: f32, flags: TextFlags) -> Vec<BodyNode> {
|
||||
fn span_text_inner(out: &mut Vec<BodyNode>, span: &[Span], size: f32, flags: TextFlags) {
|
||||
for node in span {
|
||||
|
@@ -2,6 +2,8 @@ use egui_tracing::EventCollector;
|
||||
use nalgebra::Vector3;
|
||||
use slicer::supports::line::LineSupportConfig;
|
||||
|
||||
use super::markdown::CompiledMarkdown;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct UiState {
|
||||
pub event_collector: EventCollector,
|
||||
@@ -16,6 +18,7 @@ pub struct UiState {
|
||||
|
||||
// documentation
|
||||
pub docs_page: DocsPage,
|
||||
pub compiled_markdown: CompiledMarkdown,
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq, Eq)]
|
||||
@@ -26,9 +29,27 @@ pub enum RemotePrintConnectStatus {
|
||||
Scanning,
|
||||
}
|
||||
|
||||
#[derive(Default, PartialEq)]
|
||||
#[derive(Default, Clone, Copy, PartialEq)]
|
||||
pub enum DocsPage {
|
||||
#[default]
|
||||
GettingStarted,
|
||||
AnotherPage,
|
||||
Miscellaneous,
|
||||
}
|
||||
|
||||
impl DocsPage {
|
||||
pub const ALL: [DocsPage; 2] = [DocsPage::GettingStarted, DocsPage::Miscellaneous];
|
||||
|
||||
pub fn name(&self) -> &'static str {
|
||||
match self {
|
||||
DocsPage::GettingStarted => "Getting Started",
|
||||
DocsPage::Miscellaneous => "Miscellaneous",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn source(&self) -> &'static str {
|
||||
match self {
|
||||
DocsPage::GettingStarted => include_str!("../../../docs/getting_started.md"),
|
||||
DocsPage::Miscellaneous => include_str!("../../../docs/miscellaneous.md"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -30,20 +30,19 @@ pub fn ui(app: &mut App, ui: &mut Ui, _ctx: &Context) {
|
||||
});
|
||||
|
||||
ui.add_space(8.0);
|
||||
|
||||
let last_page = app.state.docs_page;
|
||||
ui.horizontal(|ui| {
|
||||
ui.selectable_value(
|
||||
&mut app.state.docs_page,
|
||||
DocsPage::GettingStarted,
|
||||
"Getting Started",
|
||||
);
|
||||
ui.selectable_value(
|
||||
&mut app.state.docs_page,
|
||||
DocsPage::AnotherPage,
|
||||
"Another Page",
|
||||
);
|
||||
for page in DocsPage::ALL {
|
||||
ui.selectable_value(&mut app.state.docs_page, page, page.name());
|
||||
}
|
||||
});
|
||||
|
||||
if last_page != app.state.docs_page || app.state.compiled_markdown.is_empty() {
|
||||
app.state.compiled_markdown = CompiledMarkdown::compile(app.state.docs_page.source());
|
||||
}
|
||||
|
||||
ui.separator();
|
||||
|
||||
CompiledMarkdown::compile(include_str!("../../../docs/getting_started.md")).render(ui);
|
||||
app.state.compiled_markdown.render(ui);
|
||||
}
|
||||
|
@@ -1,8 +1,8 @@
|
||||
use const_format::concatcp;
|
||||
use egui::{Context, Grid, Id, Ui};
|
||||
use egui_phosphor::regular::{
|
||||
ARROWS_CLOCKWISE, ARROW_LINE_DOWN, COPY, DICE_THREE, EYE, EYE_SLASH, FLIP_HORIZONTAL, TRASH,
|
||||
VECTOR_THREE,
|
||||
ARROWS_CLOCKWISE, ARROW_LINE_DOWN, COPY, DICE_THREE, EYE, EYE_SLASH, FLIP_HORIZONTAL,
|
||||
LINK_BREAK, LINK_SIMPLE, TRASH, VECTOR_THREE,
|
||||
};
|
||||
use slicer::Pos;
|
||||
|
||||
@@ -119,7 +119,11 @@ pub fn ui(app: &mut App, ui: &mut Ui, _ctx: &Context) {
|
||||
(mesh.mesh.scale() != scale).then(|| mesh.mesh.set_scale(scale));
|
||||
|
||||
mesh.locked_scale ^= ui
|
||||
.button(if mesh.locked_scale { "🔒" } else { "🔓" })
|
||||
.button(if mesh.locked_scale {
|
||||
LINK_SIMPLE
|
||||
} else {
|
||||
LINK_BREAK
|
||||
})
|
||||
.clicked();
|
||||
});
|
||||
ui.end_row();
|
||||
|
Reference in New Issue
Block a user