Switch over to WebAssembly, Rust and Yew #35
@ -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.
|
||||
|
||||
![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++.
|
||||
|
||||
@ -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:
|
||||
|
||||
<Bookmark
|
||||
url="https://gist.github.com/BlakeRain/f62732c37dcb3a4950134a9b37d4913b"
|
||||
title="collapse-controls.py"
|
||||
description="GitHub Gist: instantly share code, notes, and snippets."
|
||||
author="262588213843476"
|
||||
publisher="Gist"
|
||||
thumbnail="https://github.githubassets.com/images/modules/gists/gist-og-image.png"
|
||||
icon="https://github.githubassets.com/favicons/favicon.svg" />
|
||||
```bookmark
|
||||
title: collapsible-controls.py
|
||||
url: "https://gist.github.com/BlakeRain/f62732c37dcb3a4950134a9b37d4913b"
|
||||
description: "GitHub Gist: instantly share code, notes, and snippets."
|
||||
author: Blake Rain
|
||||
publisher: GitHub Gist
|
||||
thumbnail: "https://github.githubassets.com/images/modules/gists/gist-og-image.png"
|
||||
icon: "https://github.githubassets.com/favicons/favicon.svg"
|
||||
```
|
||||
|
@ -1,7 +1,7 @@
|
||||
use std::{collections::HashMap, fmt::Write, str::FromStr};
|
||||
|
||||
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 yew::{
|
||||
html,
|
||||
@ -147,6 +147,9 @@ struct Writer<'a, I> {
|
||||
output: Vec<VNode>,
|
||||
stack: Vec<VNode>,
|
||||
footnotes: HashMap<CowStr<'a>, usize>,
|
||||
table_align: Vec<Alignment>,
|
||||
table_head: bool,
|
||||
table_colidx: usize,
|
||||
}
|
||||
|
||||
impl<'a, I> Writer<'a, I>
|
||||
@ -159,9 +162,18 @@ where
|
||||
output: Vec::new(),
|
||||
stack: Vec::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) {
|
||||
if let Some(VNode::VTag(top)) = self.stack.last_mut() {
|
||||
top.add_child(node);
|
||||
@ -242,10 +254,41 @@ where
|
||||
|
||||
Tag::FootnoteDefinition(_) => todo!(),
|
||||
|
||||
Tag::Table(_) => todo!(),
|
||||
Tag::TableHead => todo!(),
|
||||
Tag::TableRow => todo!(),
|
||||
Tag::TableCell => todo!(),
|
||||
Tag::Table(align) => {
|
||||
self.table_align = align;
|
||||
self.stack.push(VTag::new("table").into());
|
||||
}
|
||||
|
||||
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::Strong => self.stack.push(VTag::new("strong").into()),
|
||||
@ -304,11 +347,34 @@ where
|
||||
}
|
||||
|
||||
fn end_tag(&mut self, tag: Tag) {
|
||||
let element = self.stack.pop().unwrap_or_else(|| {
|
||||
panic!("Expected stack to have an element at end of tag: {tag:?}");
|
||||
});
|
||||
match 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> {
|
||||
|
@ -120,5 +120,55 @@
|
||||
@apply mt-4 font-sans text-sm text-center;
|
||||
@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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user