187 lines
6.9 KiB
Fennel
187 lines
6.9 KiB
Fennel
(local lume (require :lib.lume))
|
|
(local style (require :core.style))
|
|
(local common (require :core.common))
|
|
(local View (require :core.view))
|
|
(local {: attach-imstate : textbutton} (require :editor.imstate))
|
|
|
|
(local SlideshowView (View:extend))
|
|
(fn SlideshowView.parse [slides]
|
|
(var style nil)
|
|
(icollect [_ slide (ipairs slides)]
|
|
(icollect [_ elem (ipairs slide)]
|
|
(match (type elem)
|
|
(where :table elem.style) (do (set style elem) nil)
|
|
:table (if elem.button (lume.merge style elem) elem)
|
|
:string (lume.merge style {:text elem})))))
|
|
|
|
(fn slides-target [slides]
|
|
(var target 0)
|
|
(each [_ slide (ipairs slides)]
|
|
(each [_ elem (ipairs slide)]
|
|
(when elem.target (set target (+ target elem.target)))))
|
|
target)
|
|
|
|
(fn SlideshowView.new [self slides]
|
|
(SlideshowView.super.new self)
|
|
(attach-imstate self)
|
|
(set self.slides slides)
|
|
(set self.total-target (slides-target slides))
|
|
(set self.imagecache {})
|
|
(set self.islide 1)
|
|
(set self.ielem 0)
|
|
(set self.cleanup {})
|
|
(self:cleanup-slide)
|
|
(self:advance))
|
|
|
|
(fn SlideshowView.cleanup-slide [self]
|
|
(each [_ f (pairs self.cleanup)] (f))
|
|
(set self.cleanup {})
|
|
(set self.current-target (slides-target (lume.slice self.slides 1 self.islide)))
|
|
(set self.sections (icollect [_ slide (ipairs self.slides)]
|
|
(let [{: section} (or (lume.match slide #$1.section) {})] section)))
|
|
(var isection-current 0)
|
|
(set self.islide-to-isection (icollect [_ slide (ipairs self.slides)]
|
|
(let [{: section} (or (lume.match slide #$1.section) {})]
|
|
(when section (set isection-current (+ isection-current 1)))
|
|
isection-current))))
|
|
|
|
(fn SlideshowView.next-slide [self]
|
|
(set self.islide (if (>= self.islide (length self.slides)) 1 (+ self.islide 1)))
|
|
(set self.ielem 0)
|
|
(self:cleanup-slide)
|
|
(self:advance))
|
|
|
|
(fn SlideshowView.prev-slide [self]
|
|
(set self.islide (if (<= self.islide 1) (length self.slides) (- self.islide 1)))
|
|
(set self.ielem (+ 1 (length (. self.slides self.islide))))
|
|
(self:cleanup-slide)
|
|
(self:back))
|
|
|
|
(fn SlideshowView.ielemNext [self ielem di]
|
|
(let [slide (. self.slides self.islide)
|
|
elem (. slide ielem)]
|
|
(when elem
|
|
(when elem.action
|
|
(if (= di 1) (tset self.cleanup ielem (elem:action))
|
|
(. self.cleanup ielem) ((. self.cleanup ielem))))
|
|
(if elem.pause-after ielem
|
|
(self:ielemNext (+ ielem di) di)))))
|
|
|
|
(fn SlideshowView.advance [self]
|
|
(let [ielemNext (self:ielemNext (+ self.ielem 1) 1)]
|
|
(if ielemNext (set self.ielem ielemNext)
|
|
(self:next-slide))))
|
|
|
|
(fn SlideshowView.back [self]
|
|
(let [ielemNext (self:ielemNext (- self.ielem 1) -1)]
|
|
(if ielemNext (set self.ielem ielemNext)
|
|
(self:prev-slide))))
|
|
|
|
(fn SlideshowView.load-image [self {:image filename}]
|
|
(when (= (. self.imagecache filename) nil)
|
|
(tset self.imagecache filename (love.graphics.newImage filename)))
|
|
(. self.imagecache filename))
|
|
|
|
(fn SlideshowView.justify [self element width]
|
|
(match element.justify
|
|
:center (/ (- self.size.x width) 2)
|
|
:right (- self.size.x width style.padding.x)
|
|
_ style.padding.x))
|
|
|
|
(fn SlideshowView.this-y [self element y]
|
|
(if element.topPadding (+ y element.topPadding)
|
|
(+ y style.padding.y)))
|
|
|
|
(fn SlideshowView.next-y [self element height y]
|
|
(if element.lowerPadding (+ y height element.lowerPadding)
|
|
element.overlay y
|
|
(+ y height style.padding.y)))
|
|
|
|
(fn SlideshowView.word-wrap [self element]
|
|
(let [letter-width (element.font:get_width "m")
|
|
screen-width (- self.size.x style.padding.x style.padding.x)
|
|
max-letters (math.floor (/ screen-width letter-width))
|
|
wrapped (lume.wordwrap element.text max-letters)
|
|
lines (icollect [line (string.gmatch wrapped "([^\n]+)")] line)]
|
|
lines))
|
|
|
|
(fn SlideshowView.render-element [self element y]
|
|
(if element.button
|
|
(let [(pressed yNext) (textbutton self
|
|
element.text
|
|
(+ self.position.x (self:justify element (element.font:get_width element.text)))
|
|
y
|
|
element.font)]
|
|
(when pressed (element:button))
|
|
(self:next-y element (- yNext y) y))
|
|
|
|
element.text
|
|
(let [lines (self:word-wrap element)
|
|
line-height (element.font:get_height)
|
|
full-height (+ (* line-height (length lines)) (* style.padding.y (- (length lines) 1)))]
|
|
(each [iline line (ipairs lines)]
|
|
(let [width (element.font:get_width line) ;; todo: word-wrapping
|
|
x (+ self.position.x (self:justify element width))
|
|
yline (+ y (* (+ (element.font:get_height) style.padding.y) (- iline 1)))]
|
|
(renderer.draw_text element.font line x yline element.color)))
|
|
(self:next-y element full-height y))
|
|
|
|
element.image
|
|
(let [image (self:load-image element)
|
|
x (+ self.position.x (self:justify element (image:getWidth)))]
|
|
(love.graphics.setColor 1 1 1 element.alpha)
|
|
(love.graphics.draw image x y)
|
|
(self:next-y element (image:getHeight) y))
|
|
y))
|
|
|
|
(fn SlideshowView.draw [self]
|
|
(self:draw_background style.background)
|
|
(var y self.position.y)
|
|
(each [ielem element (ipairs (. self.slides self.islide)) :until (> ielem self.ielem)]
|
|
(set y (self:render-element element (self:this-y element y)))))
|
|
|
|
; timer
|
|
(fn SlideshowView.elapsed [self]
|
|
(if self.elapsed-time self.elapsed-time
|
|
self.start-time (- (system.get_time) self.start-time)
|
|
0))
|
|
|
|
(fn SlideshowView.toggle-timer [self]
|
|
(if (= self.start-time nil)
|
|
(set self.start-time (system.get_time))
|
|
|
|
(= self.elapsed-time nil)
|
|
(set self.elapsed-time (self:elapsed))
|
|
|
|
(do (set self.start-time (- (system.get_time) self.elapsed-time))
|
|
(set self.elapsed-time nil))))
|
|
|
|
(fn SlideshowView.reset-timer [self]
|
|
(set self.elapsed-time nil)
|
|
(set self.start-time nil))
|
|
|
|
(fn time [seconds]
|
|
(let [sign (if (< seconds 0) "-" "")
|
|
seconds (math.abs seconds)
|
|
m (math.floor (/ seconds 60))
|
|
s (% seconds 60)]
|
|
(string.format "%s%d:%02d" sign m s)))
|
|
|
|
; status bar
|
|
(fn SlideshowView.status_items [self {: separator : separator2}]
|
|
(let [full (renderer.font.load "presentation/font/PrintChar21.ttf" (* 14 SCALE))
|
|
thin (renderer.font.load "presentation/font/PRNumber3.ttf" (* 14 SCALE))
|
|
elapsed (self:elapsed)
|
|
left [full "\xE2\x8C\xA5 " thin]
|
|
right [thin (time (- self.total-target elapsed))
|
|
full " \xE2\x8C\x9B "
|
|
thin (time (- self.current-target elapsed))]]
|
|
(each [isection section (ipairs self.sections)]
|
|
(when (> isection 1) (lume.push left style.dim " > "))
|
|
(lume.push left (if (= isection (. self.islide-to-isection self.islide)) style.text style.dim) section))
|
|
(values left right)))
|
|
|
|
(fn SlideshowView.get_name [self] "] KFest 2021")
|
|
|
|
SlideshowView
|