Switch over to WebAssembly, Rust and Yew #35

Merged
BlakeRain merged 87 commits from yew-static into main 2023-08-30 18:01:40 +00:00
3 changed files with 135 additions and 18 deletions
Showing only changes of commit 44cfab16aa - Show all commits

View File

@ -30,7 +30,7 @@ It's interesting to me that we don't often see this kind of UI in many GTK appli
In this article I thought it would be fun to walk through creating a simple GTK application that uses an [overlay](https://developer.gnome.org/gtk3/stable/GtkOverlay.html) widget to render a set of controls over the top of a custom drawn widget. In this article I thought it would be fun to walk through creating a simple GTK application that uses an [overlay](https://developer.gnome.org/gtk3/stable/GtkOverlay.html) widget to render a set of controls over the top of a custom drawn widget.
![Simple application using an overlay widget](/content/overlays-with-custom-widgets-in-gtk/Collapsible-Controls-Overlay-Demo_2102-1.png) ![Simple application using an overlay widget](/content/overlays-with-custom-widgets-in-gtk/Collapsible-Controls-Overlay-Demo_2102.png)
As we're only focusing on the GTK side of things, I decided to use Python instead of C++. As we're only focusing on the GTK side of things, I decided to use Python instead of C++.
@ -646,11 +646,12 @@ After this final change to the `ControlPanel` widget we should have a demo that
If you want to download the source code for this demo you can find it at the following GitHub Gist: If you want to download the source code for this demo you can find it at the following GitHub Gist:
<Bookmark ```bookmark
url="https://gist.github.com/BlakeRain/f62732c37dcb3a4950134a9b37d4913b" title: collapsible-controls.py
title="collapse-controls.py" url: "https://gist.github.com/BlakeRain/f62732c37dcb3a4950134a9b37d4913b"
description="GitHub Gist: instantly share code, notes, and snippets." description: "GitHub Gist: instantly share code, notes, and snippets."
author="262588213843476" author: Blake Rain
publisher="Gist" publisher: GitHub Gist
thumbnail="https://github.githubassets.com/images/modules/gists/gist-og-image.png" thumbnail: "https://github.githubassets.com/images/modules/gists/gist-og-image.png"
icon="https://github.githubassets.com/favicons/favicon.svg" /> icon: "https://github.githubassets.com/favicons/favicon.svg"
```

View File

@ -1,7 +1,7 @@
use std::{collections::HashMap, fmt::Write, str::FromStr}; use std::{collections::HashMap, fmt::Write, str::FromStr};
use gray_matter::engine::Engine; use gray_matter::engine::Engine;
use pulldown_cmark::{CodeBlockKind, CowStr, Event, HeadingLevel, Options, Parser, Tag}; use pulldown_cmark::{Alignment, CodeBlockKind, CowStr, Event, HeadingLevel, Options, Parser, Tag};
use serde::Deserialize; use serde::Deserialize;
use yew::{ use yew::{
html, html,
@ -147,6 +147,9 @@ struct Writer<'a, I> {
output: Vec<VNode>, output: Vec<VNode>,
stack: Vec<VNode>, stack: Vec<VNode>,
footnotes: HashMap<CowStr<'a>, usize>, footnotes: HashMap<CowStr<'a>, usize>,
table_align: Vec<Alignment>,
table_head: bool,
table_colidx: usize,
} }
impl<'a, I> Writer<'a, I> impl<'a, I> Writer<'a, I>
@ -159,9 +162,18 @@ where
output: Vec::new(), output: Vec::new(),
stack: Vec::new(), stack: Vec::new(),
footnotes: HashMap::new(), footnotes: HashMap::new(),
table_align: Vec::new(),
table_head: false,
table_colidx: 0,
} }
} }
fn pop(&mut self) -> VNode {
self.stack.pop().unwrap_or_else(|| {
panic!("Stack underflow");
})
}
fn output(&mut self, node: VNode) { fn output(&mut self, node: VNode) {
if let Some(VNode::VTag(top)) = self.stack.last_mut() { if let Some(VNode::VTag(top)) = self.stack.last_mut() {
top.add_child(node); top.add_child(node);
@ -242,10 +254,41 @@ where
Tag::FootnoteDefinition(_) => todo!(), Tag::FootnoteDefinition(_) => todo!(),
Tag::Table(_) => todo!(), Tag::Table(align) => {
Tag::TableHead => todo!(), self.table_align = align;
Tag::TableRow => todo!(), self.stack.push(VTag::new("table").into());
Tag::TableCell => todo!(), }
Tag::TableHead => {
self.table_head = true;
self.stack.push(VTag::new("thead").into());
self.stack.push(VTag::new("tr").into());
}
Tag::TableRow => {
self.table_colidx = 0;
self.stack.push(VTag::new("tr").into());
}
Tag::TableCell => {
let mut cell = if self.table_head {
VTag::new("th")
} else {
VTag::new("td")
};
match self.table_align.get(self.table_colidx) {
Some(&Alignment::Left) => {
cell.add_attribute("class", "left");
}
Some(&Alignment::Right) => {
cell.add_attribute("class", "right");
}
Some(&Alignment::Center) => cell.add_attribute("class", "center"),
_ => {}
}
self.stack.push(cell.into());
}
Tag::Emphasis => self.stack.push(VTag::new("em").into()), Tag::Emphasis => self.stack.push(VTag::new("em").into()),
Tag::Strong => self.stack.push(VTag::new("strong").into()), Tag::Strong => self.stack.push(VTag::new("strong").into()),
@ -304,11 +347,34 @@ where
} }
fn end_tag(&mut self, tag: Tag) { fn end_tag(&mut self, tag: Tag) {
let element = self.stack.pop().unwrap_or_else(|| { match tag {
panic!("Expected stack to have an element at end of tag: {tag:?}"); Tag::Table(_) => {
}); // Pop the <tbody> and then the <table>
let tbody = self.pop();
self.output(tbody);
let table = self.pop();
self.output(table);
}
Tag::TableHead => {
// Pop the <tr>, the <thead>, and then enter the <tbody>.
let row = self.pop();
self.output(row);
let thead = self.pop();
self.output(thead);
self.output(element); self.table_head = false;
self.stack.push(VTag::new("tbody").into());
}
Tag::TableCell => {
let cell = self.pop();
self.output(cell);
self.table_colidx += 1;
}
_ => {
let element = self.pop();
self.output(element);
}
}
} }
fn raw_text(&mut self) -> Result<String, std::fmt::Error> { fn raw_text(&mut self) -> Result<String, std::fmt::Error> {

View File

@ -120,5 +120,55 @@
@apply mt-4 font-sans text-sm text-center; @apply mt-4 font-sans text-sm text-center;
@apply text-neutral-600 dark:text-neutral-500; @apply text-neutral-600 dark:text-neutral-500;
} }
table {
@apply mb-6 border-collapse table-auto min-w-full;
thead {
@apply bg-transparent dark:bg-neutral-800;
@apply dark:text-white;
@apply border-b border-neutral-500;
tr {
th {
@apply px-6 py-4;
&.left {
@apply text-left;
}
&.right {
@apply text-right;
}
&.center {
@apply text-center;
}
}
}
}
tbody {
tr {
@apply border-b border-neutral-400 dark:border-neutral-600;
td {
@apply whitespace-nowrap px-6 py-4;
&.left {
@apply text-left;
}
&.right {
@apply text-right;
}
&.center {
@apply text-center;
}
}
}
}
}
} }
} }