thesis/slides/sns_polylux_template.typ
Jean-Marie 'Histausse' Mineau 10c1d5ec24
Some checks failed
/ test_checkout (push) Failing after 15s
update template
2025-10-22 17:02:25 +02:00

677 lines
18 KiB
Typst

/***************************************************************
* A polylux theme by martino barbieri (https://mbarbieri.it) *
* https://gitlab.com/martino.barbieri/polylux-sns-template/ *
* Patched for the PhD defence of Jean-Marie Mineau *
* LICENSE: MIT-0 *
***************************************************************/
#import "@preview/polylux:0.4.0" as pl: *
/* PER TEMPLATE SNS */
// Background and decorations
#let sns-polylux-template_sns-colormap = (
rgb("#00728D"),
rgb("#183F56"),
rgb("#4D4E4F"),
rgb("#AB3502"),
rgb("#E69426"),
rgb("#9CD7F3"),
)
/* PER TEMPLATE UNIPI */
#let sns-polylux-template_unipi-colormap = (
cmyk(100%,57%,0%,9%),
cmyk(100%,57%,0%,38%),
rgb("#444444"),
rgb("#AB3502"),
rgb("#E69426"),
cmyk(25%,7%,0%,0%),
)
#let sns-polylux-template_colormap = state("colormap", none)
// Text and Fonts
#let sns-polylux-template_text-font = state("txt-font", none)
#let sns-polylux-template_title-font = state("title-font", none)
#let sns-polylux-template_background-color = state("bkg_color1", none)
#let sns-polylux-template_main-text-color = state("txt_color1", none)
#let sns-polylux-template_second-text-color = state("txt_color2", none)
#let sns-polylux-template_title-text-color = state("title_color", none)
#let sns-polylux-template_size = state("size", none)
#let sns-polylux-template_section-size = state("section-size",none)
#let sns-polylux-template_title-size = state("title-size", none)
// Data
#let sns-polylux-template_title = state("title", none)
#let sns-polylux-template_subtitle = state("subtitle", none)
#let sns-polylux-template_footer-text = state("footer-text", none)
#let sns-polylux-template_short-event = state("short-event", none)
#let sns-polylux-template_authors = state("authors", none)
#let sns-polylux-template_logo-1 = state("logo-1", none)
#let sns-polylux-template_logo-2 = state("logo-2", none)
#let sns-polylux-template_date = state("date", none)
#let sns-polylux-template_section-pages = state("section-pages", ("plop": 0))
#let sns-polylux-template_slide-pages = state("slide-pages", 0)
// Init
#let sns-polylux-template(
// General parameters
aspect-ratio : "16-9",
txt-font : ("Roboto", "Fira Sans", "DejaVu Sans"),
title-font : ("Raleway", "PT Sans", "DejaVu Sans"),
txt-color1 : black,
txt-color2 : white,
title-color : rgb("#444444"),
size : 20pt,
section-size : 20pt,
title-size : 64pt,
bkgnd-color : white,
colormap : sns-polylux-template_sns-colormap,
// Data
title : none,
subtitle : none,
footer-text : none,
short-event : none,
logo-2 : none,
logo-1 : none,
authors : none,
date : none,
// Stuff
body
) = {
sns-polylux-template_text-font.update(txt-font)
sns-polylux-template_title-font.update(title-font)
sns-polylux-template_background-color.update(bkgnd-color)
sns-polylux-template_main-text-color.update(txt-color1)
sns-polylux-template_second-text-color.update(txt-color2)
sns-polylux-template_title-text-color.update(title-color)
sns-polylux-template_size.update(size)
sns-polylux-template_title-size.update(title-size)
sns-polylux-template_section-size.update(section-size)
sns-polylux-template_colormap.update(colormap)
set page(
paper : "presentation-" + aspect-ratio,
fill : bkgnd-color,
margin : 0pt,
header : none,
footer : none,
header-ascent : 0pt,
footer-descent : 0pt,
)
set text(
fill : txt-color1,
size : size,
font : txt-font,
)
sns-polylux-template_title.update(title)
sns-polylux-template_subtitle.update(subtitle)
if footer-text != none { sns-polylux-template_footer-text.update(footer-text) }
sns-polylux-template_logo-2.update(logo-2)
sns-polylux-template_logo-1.update(logo-1)
sns-polylux-template_authors.update(authors)
sns-polylux-template_date.update(date)
body
context {
//let section-pages = sns-polylux-template_section-pages.final()
if not "END" in sns-polylux-template_section-pages.at(here()).keys() {
let page_num = counter("logical-slide").get()
sns-polylux-template_section-pages.update(secpages => {
secpages.insert("END", page_num)
secpages
})
}
}
}
#let register-section(title, no_dedicated_slide: false) = context {
// YUCKKKKK, but polylux don't allows access to integers soooooo
let page_num = counter("logical-slide").get() //sns-polylux-template_slide-pages.at(here())
if no_dedicated_slide {
page_num.at(0) += 1
}
sns-polylux-template_section-pages.update(secpages => {
secpages.insert(repr(title), page_num)
secpages
})
pl.toolbox.register-section(title)
}
#let progress-bar() = pl.toolbox.progress-ratio( ratio => {
let colormap = sns-polylux-template_colormap.at(here())
let height = 3pt
stack(dir: ltr,
rect(width: ratio * 100%, height: height, fill: colormap.at(5)),
rect(width: (1-ratio) * 100%, height: height, fill: colormap.at(0)),
)
})
// Slides
#let title-slide(
body : none,
logo : none,
background : [],
foreground : [],
) = context( {
let content = align(top + center, context( {
let title = sns-polylux-template_title.at(here())
let subtitle = sns-polylux-template_subtitle.at(here())
let authors = sns-polylux-template_authors.at(here())
let title-size = sns-polylux-template_title-size.at(here())
let logo = {
if logo == none { sns-polylux-template_logo-1.at(here()) }
else { logo }
}
let date = sns-polylux-template_date.at(here())
// Background
place(
bottom + right,
polygon(
fill : sns-polylux-template_colormap.at(here()).at(2),
stroke : none,
(0%, 42%),(100%, 42%),(100%, 0%),
),
)
place(
bottom + right,
polygon(
fill : sns-polylux-template_colormap.at(here()).at(1),
stroke : none,
(0%, 29%),(0%, 37%),(100%, 37%),(100%, 0%),
),
)
place(
bottom + right,
polygon(
fill : sns-polylux-template_colormap.at(here()).at(0),
stroke : none,
(0%, 20%),(0%, 30%),(100%, 30%),(100%, 0%),
),
)
place(
top + left,
polygon(
fill : sns-polylux-template_colormap.at(here()).at(2),
stroke : none,
(0%, 0%),(0%, 16%),(75%, 0%),
),
)
place(
top + left,
polygon(
fill : sns-polylux-template_colormap.at(here()).at(0),
stroke : none,
(0%, 0%),(0%, 15%),(75%, 0%),
),
)
if logo != none {
place(
bottom + right,
dx: -0.5cm,
dy: -0.3cm,
scale(page.height/measure(logo).height*22%, reflow: true, logo)
)
}
// Contents
set align(center+top)
v(17%)
text(
font : sns-polylux-template_title-font.at(here()),
size : title-size,
fill: sns-polylux-template_title-text-color.at(here()),
weight: "bold",
title
)
linebreak()
v(0em)
text(
font : sns-polylux-template_title-font.at(here()),
size : 22pt,
fill: sns-polylux-template_title-text-color.at(here()),
subtitle
)
//v(-0.9em)
line(length: 90%, stroke: (paint: sns-polylux-template_colormap.at(here()).at(5), thickness: 4pt, cap: "round"))
v(1em)
set text(
size: 24pt,
top-edge: 0pt,
bottom-edge: 0pt,
fill: sns-polylux-template_main-text-color.at(here())
)
{
set align(left)
for i in range(authors.len()) {
h(1em)
authors.at(i)
v(0.5em)
//move(dx: 2% * ( i - ( authors.len() - 1 ) / 2 ), authors.at(i))
}
if date != none {
v(1em)
h(1em)
date.display()
}
}
body
} ))
set page(background: background, foreground: foreground)
pl.slide({ content })
counter("logical-slide").update( n => n - 1 )
} )
#let sections(pos_before_slide) = context {
let section-pages = sns-polylux-template_section-pages.final()
let section-size = sns-polylux-template_section-size.at(pos_before_slide)
set text(size: section-size)
let pnum = counter("logical-slide").at(pos_before_slide).first() + 1
pl.toolbox.all-sections((sections, current) => {
let beg-end-section = (:)
let prev-sec = none
for section in sections {
let s = repr(section.at("body"))
if prev-sec != none {
beg-end-section.insert(prev-sec, (section-pages.at(prev-sec).first(), section-pages.at(s).first()))
}
prev-sec = s
}
if prev-sec != none {
beg-end-section.insert(prev-sec, (section-pages.at(prev-sec).first(), section-pages.at("END").first() + 1))
}
let section_names = ()
let section_pages = ()
for s in sections {
let pages = ()
let (pmin, pmax) = beg-end-section.at(repr(s.at("body")))
let p_i = pmin
while p_i < pmax and p_i < pnum {
// In section, before current page
pages.push(sym.circle.filled)
p_i += 1
}
if p_i == pnum and p_i != pmax {
// In section, current page
pages.push(sym.ast.circle)
p_i += 1
}
while p_i < pmax {
// In section, after current page
pages.push(sym.circle.dotted)
p_i += 1
}
//section_names.push(scale(50%, reflow: true, [#pnum #s (#pmin, #pmax)]))
if s == current {
section_names.push(strong(s))
section_pages.push(strong(pages.join([])))
} else {
section_names.push(s)
section_pages.push(pages.join([]))
}
}
grid(
columns: (auto,)*section_names.len(),
column-gutter: 1fr,
row-gutter: 12pt,
..section_names, ..section_pages,
)
})
}
/*
#let small-sections(show-sec-name: true) = context( {
set text(bottom-edge: "descender")
if show-sec-name {pl.toolbox.current-section;" "}
pl.toolbox.all-sections(
(sections, current) => {
let over_current = false
for i in sections {
if current == i {$ast.circle$; over_current = true}
else if (over_current or current not in sections) {
$circle.dotted$
} else {$circle.filled$}
}
}
)
} )
#let big-sections = context( {
set align(horizon + right)
grid(
box(height: 40%, inset: 0.8cm)[#small-sections(show-sec-name: false)],
box(height: 60%, inset: 0.8cm)[
#pl.toolbox.current-section
])
} )
*/
#let slide(
title : none,
subtitle : none,
new-sec : false,
page-number : true,
hide-section : false,
hide-title : false,
background : [],
foreground : [],
body
) = context( {
let sections_height = 1.5cm
let progress_bar_height = 3pt
let title_bar_height = 2cm
let pos_before_slide = here()
// HEADER
let header = align(top, context( {
let logo = sns-polylux-template_logo-2.at(here())
// If new-sec is false, do nothing
// If new-sec is true, new section's name is the slide title
// Else the new-sec name is new-sec
if type(new-sec)==bool {
if new-sec {
register-section(title, no_dedicated_slide: true)
}
} else {
register-section(new-sec)
}
place(top + left, {
let columns = if logo != none { (auto, 1fr,) } else { (1fr,) };
grid(
columns: columns,
gutter: 0pt,
if logo != none { pad(logo, x: 0.3cm, top: 0.2cm) } else { [] },
rect(
width: 100%, height: sections_height,
inset: 0.8cm, outset: 0pt,
fill: sns-polylux-template_colormap.at(here()).at(1),
align(horizon + center,text(fill: sns-polylux-template_second-text-color.at(here()), {
v(-1em)
if hide-section { hide(sections(pos_before_slide)) } else { sections(pos_before_slide) }
}))
),
grid.cell(colspan: columns.len(), progress-bar()),
if title != none and not hide-title {
rect(
width: 100%, height: title_bar_height,
inset: 0.8cm, outset: 0pt,
fill: sns-polylux-template_colormap.at(here()).at(0),
align(horizon + center, {
text(
fill: sns-polylux-template_second-text-color.at(here()),
font: sns-polylux-template_title-font.at(here()),
size: 32pt,
weight: "bold",
title
)
if subtitle != none {
smallcaps(text(
fill: sns-polylux-template_second-text-color.at(here()),
font: sns-polylux-template_title-font.at(here()),
size: 24pt,
" — " + subtitle
))
}
})
)
} else { [] }
)
}) // closes `place(top+left, {`
} )) // closes `let header = ...`
// FOOTER
let footer = align(top + center, context( {
let footer-text = sns-polylux-template_footer-text.at(here())
place(top + center, line(length: 100%-2cm, stroke: (paint: sns-polylux-template_colormap.at(here()).at(1), thickness: 2pt, cap: "round")))
set text(bottom-edge: "descender")
block(
height: 100%,
width: 100%,
inset: (x: 0.8cm),
align(horizon,text(fill: sns-polylux-template_colormap.at(here()).at(2), size: 16pt,
grid(
gutter: 0.8cm,
columns: (1fr, 5em),
align(center, smallcaps(footer-text)),
align(right, if page-number [#toolbox.slide-number/#toolbox.last-slide-number]),
))
))
} ))
let top-margin = if title != none {
sections_height + progress_bar_height + title_bar_height
} else {
sections_height + progress_bar_height
};
set page(
margin: (top: top-margin, bottom: 1cm),
header: header,
footer: footer,
background: background,
foreground: foreground
)
pl.slide({
set align(horizon)
set text(size: sns-polylux-template_size.at(here()), top-edge: 20pt, bottom-edge: 0pt)
show: block.with(inset: (x: 1.2cm, y:.2cm), width: 100%)
body
})
if not page-number { counter("logical-slide").update( n => n - 1 ) }
} )
#let focus-slide(
new-sec : none,
page-number : true,
hide-section : false,
background : [],
foreground : [],
body
) = context( {
set page(
margin: (top: 2.5cm, bottom: 0cm),
footer: none,
fill: sns-polylux-template_colormap.at(here()).at(1),
background: background,
foreground: foreground
)
pl.slide({
set align(horizon + center)
set text(
size: sns-polylux-template_size.at(here())*1.5,
fill: sns-polylux-template_second-text-color.at(here()),
style: "italic"
)
show: block.with(inset: (x: 1.2cm, y:.2cm), width: 100%)
body
})
if not page-number { counter("logical-slide").update( n => n - 1 ) }
} )
#let empty-slide(
background : [],
foreground : [],
body
) = context( {
// HEADER
let header = align(top, context( {
let logo = sns-polylux-template_logo-1.at(here())
place(
top + left,
box(
height: 2.5cm,
if logo != none { pad(logo, x: 0.3cm, top: 0.2cm) }
)
)
} ))
set page(
margin: (top: 2.7cm, bottom: 0cm),
header: header,
footer: none,
fill: sns-polylux-template_colormap.at(here()).at(1),
background: background,
foreground: foreground
)
pl.slide({
set align(horizon + center)
set text(
size: sns-polylux-template_size.at(here())*1.5,
fill: sns-polylux-template_second-text-color.at(here()),
)
show: block.with(inset: (x: 1.2cm, y:.2cm), width: 100%)
body
})
counter("logical-slide").update( n => n - 1 )
} )
#let new-section-slide(
name,
background : [],
foreground : [],
) = context( {
// HEADER
let header = align(top, context( {
let logo = sns-polylux-template_logo-1.at(here())
place(
top + left,
box(
height: 2.5cm,
if logo != none { pad(logo, x: 0.3cm, top: 0.2cm) }
)
)
} ))
set page(
margin: (top: 2.7cm, bottom: 0cm),
header: header,
footer: none,
fill: sns-polylux-template_colormap.at(here()).at(1),
background: background,
foreground: foreground
)
// TOC
/*
let content = context( {
pl.toolbox.all-sections( (sections, current) => {
set text(weight: "regular")
let over_current = false
for i in sections {
if (current == i) {[
+ #text(weight: "black", i)
]; over_current = true}
else if (over_current) [
+ #text(weight: "thin", i)
]
else [
+ #text(i)
]
}
} )
} )
*/
pl.slide({
set align(horizon + center)
set text(
size: sns-polylux-template_size.at(here())*1.5,
fill: sns-polylux-template_second-text-color.at(here()),
)
register-section(name)
show: pad.with(20%)
name
progress-bar()
})
counter("logical-slide").update( n => n - 1 )
} )
#let toc-slide(
title : none,
background : [],
foreground : [],
) = context( {
// HEADER
let header = align(top, {
let logo = sns-polylux-template_logo-1.at(here())
place(
top + left,
box(
height: 2.5cm,
if logo != none { pad(logo, x: 0.3cm, top: 0.2cm) }
)
)
} )
set page(
margin: (top: 2.7cm, bottom: 0cm),
header: header,
footer: none,
fill: sns-polylux-template_colormap.at(here()).at(1),
background: background,
foreground: foreground
)
// TOC
let content = {
if title != none { align(center,text(weight: "bold", title)); v(-0.2em) }
pl.toolbox.all-sections( (sections, current) => {
for i in sections [
+ #text(i)
]
} )
}
pl.slide({
set align(horizon + center)
set text(
size: sns-polylux-template_size.at(here())*1.5,
fill: sns-polylux-template_second-text-color.at(here()),
)
show: box.with()
set align(left)
content
})
counter("logical-slide").update( n => n - 1 )
} )