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.
|
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"
|
||||||
|
```
|
||||||
|
@ -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,12 +347,35 @@ 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.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);
|
self.output(element);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn raw_text(&mut self) -> Result<String, std::fmt::Error> {
|
fn raw_text(&mut self) -> Result<String, std::fmt::Error> {
|
||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user