(import scheme) (import (chicken base)) (import (chicken bitwise)) (import (chicken format)) (import (chicken time posix)) (import (srfi 1)) (import (rename format (format cl-format))) (import (prefix glfw3 glfw:)) (import (prefix epoxy gl:)) (import (prefix nuklear-glfw3-opengl2 nk:)) (import (prefix nuklear nk:)) (define width 1200) (define height 800) (glfw:init) (glfw:make-window width height "Overview") (glfw:make-context-current (glfw:window)) (set!-values (width height) (glfw:get-window-size (glfw:window))) (define ctx (nk:init (glfw:window))) (nk:init-default-font ctx) (define ->flag bitwise-ior) (define (flag? flag flags) (not (zero? (bitwise-and flag flags)))) (define bg (nk:make-color 0.1 0.18 0.24 1.0)) (define show-menu? #t) (define titlebar? #t) (define border? #t) (define resize? #t) (define movable? #t) (define no-scrollbar? #f) (define scale-left? #f) (define minimizable? #t) (define menu-progress 60) (define menu-slider 10) (define menu-check #t) (define menu/none 0) (define menu/file 1) (define menu/edit 2) (define menu/view 3) (define menu/chart 4) (define menu-state menu/none) (define progress 40) (define slider 10) (define check #t) (define A 0) (define B 1) (define C 2) (define checkbox #f) (define option 0) (define int-slider 5) (define float-slider 2.5) (define prog-value 40) (define property-float 2) (define property-int 10) (define property-neg 10) (define range-float-min 0) (define range-float-max 100) (define range-float-value 50) (define range-int-min 0) (define range-int-value 2048) (define range-int-max 4096) (define ratio '(120 150)) (define selected-list (make-vector 4 #f)) (define selected-grid (make-vector 16 #f)) (define (vector-for-each proc vec) (let loop ((i 0)) (when (< i (vector-length vec)) (proc i (vector-ref vec i)) (loop (add1 i))))) (define (vector-toggle! vec n) (let ((value (vector-ref vec n))) (vector-set! vec n (not value)))) (define chart-selection 8) (define check-values (make-list 4 #f)) (define position '(0 0 0)) (define combo-color (nk:make-color 130 50 50 255)) (define combo-color2 (nk:rgba-f->colorf 0.509 0.705 0.2 1.0)) (define use-hsva? #f) (define prog-a 20) (define prog-b 40) (define prog-c 10) (define prog-d 90) (define weapons '("Fist" "Pistol" "Shotgun" "Plasma" "BFG")) (define weapon-idx 0) (define time-selected? #f) (define date-selected? #f) (define selected-time #f) (define selected-date #f) (define text (make-vector 8 "")) (define field-buffer "") (define box-buffer "") (define (mask-text text) (make-string (string-length text) #\*)) (define pi (* 2 (asin 1))) (define col-index -1) (define line-index -1) (define selected (make-list 4 #f)) (define color (nk:make-color 255 0 0 255)) (define popup-active? #f) (define group-titlebar? #f) (define group-border? #t) (define group-no-scrollbar? #f) (define (group-flags) (->flag (if group-titlebar? nk:window/title 0) (if group-border? nk:window/border 0) (if group-no-scrollbar? nk:window/no-scrollbar 0))) (define group-width 320) (define group-height 200) (define selected-group (make-list 16 #f)) (define root-selected #f) (define selected-leaves (make-list 8 #f)) (define selected-nodes (make-list 4 #f)) (define left-selected-group (make-list 32 #f)) (define top-right-selected-group (make-list 4 #f)) (define center-right-selected-group (make-list 4 #f)) (define bottom-right-selected-group (make-list 4 #f)) (define vertical-a 100) (define vertical-b 100) (define vertical-c 100) (define horizontal-a 100) (define horizontal-b 100) (define horizontal-c 100) (define (window-flags) (->flag (if border? nk:window/border 0) (if resize? nk:window/scalable 0) (if movable? nk:window/movable 0) (if no-scrollbar? nk:window/no-scrollbar 0) (if scale-left? nk:window/scale-left 0) (if minimizable? nk:window/minimizable 0))) (nk:style-window-header-align-set! (nk:context-style ctx) nk:header/right) (define show-app-about? #f) (let loop () (when (and (not (glfw:window-should-close (glfw:window)))) (glfw:poll-events) (nk:new-frame) (when (nk:window-begin ctx "Overview" (nk:make-rect 10 10 400 600) (window-flags)) (when show-menu? ;; menubar (nk:menubar-begin ctx) ;; menu #1 (nk:layout-row-begin ctx nk:layout/static 25 5) (nk:layout-row-push ctx 45) (when (nk:menu-begin-label ctx "MENU" nk:text/left (nk:make-vec2 120 200)) (nk:layout-row-dynamic ctx 25 1) (when (nk:menu-item-label ctx "Hide" nk:text/left) (set! show-menu? #f)) (when (nk:menu-item-label ctx "About" nk:text/left) (set! show-app-about? #t)) (receive (val changed?) (nk:progress ctx progress 100 nk:modify/modifiable) (when changed? (set! progress val))) (set! slider (nk:slider-int ctx 0 slider 16 1)) (set! check (nk:check-label ctx "check" check)) (nk:menu-end ctx)) ;; menu #2 (nk:layout-row-push ctx 60) (when (nk:menu-begin-label ctx "ADVANCED" nk:text/left (nk:make-vec2 200 600)) (let ((state 0)) (set! state (if (= menu-state menu/file) nk:collapse/maximized nk:collapse/minimized)) (receive (open? state) (nk:tree-state-push ctx nk:tree/tab "FILE" state) (if open? (begin (set! menu-state menu/file) (for-each (lambda (label) (nk:menu-item-label ctx label nk:text/left)) '("New" "Open" "Save" "Close" "Exit")) (nk:tree-pop ctx)) (when (= menu-state menu/file) (set! menu-state menu/none)))) (set! state (if (= menu-state menu/edit) nk:collapse/maximized nk:collapse/minimized)) (receive (open? state) (nk:tree-state-push ctx nk:tree/tab "EDIT" state) (if open? (begin (set! menu-state menu/edit) (for-each (lambda (label) (nk:menu-item-label ctx label nk:text/left)) '("Copy" "Delete" "Cut" "Paste")) (nk:tree-pop ctx)) (when (= menu-state menu/edit) (set! menu-state menu/none)))) (set! state (if (= menu-state menu/view) nk:collapse/maximized nk:collapse/minimized)) (receive (open? state) (nk:tree-state-push ctx nk:tree/tab "VIEW" state) (if open? (begin (set! menu-state menu/view) (for-each (lambda (label) (nk:menu-item-label ctx label nk:text/left)) '("About" "Options" "Customize")) (nk:tree-pop ctx)) (when (= menu-state menu/view) (set! menu-state menu/none)))) (set! state (if (= menu-state menu/chart) nk:collapse/maximized nk:collapse/minimized)) (receive (open? state) (nk:tree-state-push ctx nk:tree/tab "CHART" state) (if open? (let ((values '(26 13 30 15 25 10 20 40 12 8 22 28))) (set! menu-state menu/chart) (nk:layout-row-dynamic ctx 150 1) (nk:chart-begin ctx nk:chart/column (length values) 0 50) (for-each (lambda (value) (nk:chart-push ctx value)) values) (nk:chart-end ctx) (nk:tree-pop ctx)) (when (= menu-state menu/chart) (set! menu-state menu/none))))) (nk:menu-end ctx)) ;; menu widgets (nk:layout-row-push ctx 70) (set! menu-progress (nk:progress ctx menu-progress 100 nk:modify/modifiable)) (set! menu-slider (nk:slider-int ctx 0 menu-slider 16 1)) (set! menu-check (nk:check-label ctx "check" menu-check)) (nk:menubar-end ctx)) (when show-app-about? ;; about popup (if (nk:popup-begin ctx nk:popup/static "About" nk:window/closable (nk:make-rect 20 100 300 190)) (begin (nk:layout-row-dynamic ctx 20 1) (nk:label ctx "Nuklear" nk:text/left) (nk:label ctx "By Micha Mettke" nk:text/left) (nk:label ctx "nuklear is licensed under the public domain License" nk:text/left) (nk:popup-end ctx)) (set! show-app-about? #f))) (when (nk:tree-push ctx nk:tree/tab "Window" nk:collapse/minimized) (nk:layout-row-dynamic ctx 30 2) (set! titlebar? (nk:check-label ctx "Titlebar" titlebar?)) (set! show-menu? (nk:check-label ctx "Menu" show-menu?)) (set! border? (nk:check-label ctx "Border" border?)) (set! resize? (nk:check-label ctx "Resizable" resize?)) (set! movable? (nk:check-label ctx "Movable" movable?)) (set! no-scrollbar? (nk:check-label ctx "No Scrollbar" no-scrollbar?)) (set! minimizable? (nk:check-label ctx "Minimizable" minimizable?)) (set! scale-left? (nk:check-label ctx "Scale Left" scale-left?)) (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/tab "Widgets" nk:collapse/minimized) (when (nk:tree-push ctx nk:tree/node "Text" nk:collapse/minimized) (nk:layout-row-dynamic ctx 20 1) (nk:label ctx "Label aligned left" nk:text/left) (nk:label ctx "Label aligned centered" nk:text/centered) (nk:label ctx "Label aligned right" nk:text/right) (nk:label-colored ctx "Blue text" nk:text/left (nk:rgb->color 0 0 255)) (nk:label-colored ctx "Yellow text" nk:text/left (nk:rgb->color 255 255 0)) (nk:text ctx "Text with \x00 ASCII NUL in it" nk:text/right) (nk:layout-row-static ctx 100 200 1) (nk:label-wrap ctx "This is a very long line to hopefully get this text to be wrapped into multiple lines to show line wrapping") (nk:layout-row-dynamic ctx 100 1) (nk:label-wrap ctx "This is another long text to show dynamic window changes on multiline text") (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/node "Button" nk:collapse/minimized) (nk:layout-row-static ctx 30 100 3) (when (nk:button-label ctx "Button") (print "Button pressed!")) (nk:button-behavior-set! ctx nk:button/repeater) (when (nk:button-label ctx "Repeater") (print "Repeater is being pressed!")) (nk:button-behavior-set! ctx nk:button/default) (nk:button-color ctx (nk:rgb->color 0 0 255)) (nk:layout-row-static ctx 25 25 8) (nk:button-symbol ctx nk:symbol/circle-solid) (nk:button-symbol ctx nk:symbol/circle-outline) (nk:button-symbol ctx nk:symbol/rect-solid) (nk:button-symbol ctx nk:symbol/rect-outline) (nk:button-symbol ctx nk:symbol/triangle-up) (nk:button-symbol ctx nk:symbol/triangle-down) (nk:button-symbol ctx nk:symbol/triangle-left) (nk:button-symbol ctx nk:symbol/triangle-right) (nk:layout-row-static ctx 30 100 2) (nk:button-symbol-label ctx nk:symbol/triangle-left "prev" nk:text/right) (nk:button-symbol-label ctx nk:symbol/triangle-right "next" nk:text/left) (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/node "Basic" nk:collapse/minimized) (nk:layout-row-static ctx 30 100 1) (set! checkbox (nk:check-label ctx "Checkbox" checkbox)) (nk:layout-row-static ctx 30 80 3) (set! option (if (nk:option-label ctx "optionA" (= option A)) A option)) (set! option (if (nk:option-label ctx "optionB" (= option B)) B option)) (set! option (if (nk:option-label ctx "optionC" (= option C)) C option)) (nk:layout-row ctx nk:layout/static 30 ratio) (nk:label ctx "Slider int" nk:text/left) (set! int-slider (nk:slider-int ctx 0 int-slider 10 1)) (nk:label ctx "Slider float" nk:text/left) (set! float-slider (nk:slider-float ctx 0 float-slider 5 0.5)) (nk:label ctx (format "Progressbar: ~a" prog-value) nk:text/left) (set! prog-value (nk:progress ctx prog-value 100 nk:modify/modifiable)) (nk:layout-row ctx nk:layout/static 25 ratio) (nk:label ctx "Property float:" nk:text/left) (set! property-float (nk:property-float ctx "Float:" 0 property-float 64 0.1 0.2)) (nk:label ctx "Property int:" nk:text/left) (set! property-int (nk:property-int ctx "Int:" 0 property-int 100 1 1)) (nk:label ctx "Property neg:" nk:text/left) (set! property-neg (nk:property-int ctx "Neg:" -10 property-neg 10 1 1)) (nk:layout-row-dynamic ctx 25 1) (nk:label ctx "Range:" nk:text/left) (nk:layout-row-dynamic ctx 25 3) (set! range-float-min (nk:property-float ctx "#min:" 0 range-float-min range-float-max 1 0.2)) (set! range-float-value (nk:property-float ctx "#float:" range-float-min range-float-value range-float-max 1 0.2)) (set! range-float-max (nk:property-float ctx "#max:" range-float-min range-float-max 100 1 0.2)) (set! range-int-min (nk:property-int ctx "#min:" -32767 range-int-min range-int-max 1 10)) (set! range-int-value (nk:property-int ctx "#neg:" range-int-min range-int-value range-int-max 1 10)) (set! range-int-max (nk:property-int ctx "#max:" range-int-min range-int-max 32767 1 10)) (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/node "Inactive" nk:collapse/minimized) ;; TODO (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/node "Selectable" nk:collapse/minimized) (when (nk:tree-push ctx nk:tree/node "List" nk:collapse/minimized) (nk:layout-row-static ctx 18 100 1) (vector-set! selected-list 0 (nk:selectable-label ctx "Selectable" nk:text/left (vector-ref selected-list 0))) (vector-set! selected-list 1 (nk:selectable-label ctx "Selectable" nk:text/left (vector-ref selected-list 1))) (nk:label ctx "Not selectable" nk:text/left) (vector-set! selected-list 2 (nk:selectable-label ctx "Selectable" nk:text/left (vector-ref selected-list 2))) (vector-set! selected-list 3 (nk:selectable-label ctx "Selectable" nk:text/left (vector-ref selected-list 3))) (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/node "Grid" nk:collapse/minimized) (nk:layout-row-static ctx 50 50 4) (vector-for-each (lambda (i x) (let* ((value (nk:selectable-label ctx "Z" nk:text/centered x)) (clicked? (not (eqv? x value)))) (when clicked? (vector-set! selected-grid i value) (let ((x (modulo i 4)) (y (quotient i 4))) (when (> x 0) (vector-toggle! selected-grid (sub1 i))) (when (< x 3) (vector-toggle! selected-grid (add1 i))) (when (> y 0) (vector-toggle! selected-grid (- i 4))) (when (< y 3) (vector-toggle! selected-grid (+ i 4))))))) selected-grid) (nk:tree-pop ctx)) (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/node "Combo" nk:collapse/minimized) ;; Combobox Widgets ;; In this library comboboxes are not limited to being a popup ;; list of selectable text. Instead it is a abstract concept of ;; having something that is *selected* or displayed, a popup window ;; which opens if something needs to be modified and the content ;; of the popup which causes the *selected* or displayed value to ;; change or if wanted close the combobox. ;; ;; While strange at first handling comboboxes in a abstract way ;; solves the problem of overloaded window content. For example ;; changing a color value requires 4 value modifier (slider, property,...) ;; for RGBA then you need a label and ways to display the current color. ;; If you want to go fancy you even add rgb and hsv ratio boxes. ;; While fine for one color if you have a lot of them it because ;; tedious to look at and quite wasteful in space. You could add ;; a popup which modifies the color but this does not solve the ;; fact that it still requires a lot of cluttered space to do. ;; ;; In these kind of instance abstract comboboxes are quite handy. All ;; value modifiers are hidden inside the combobox popup and only ;; the color is shown if not open. This combines the clarity of the ;; popup with the ease of use of just using the space for modifiers. ;; ;; Other instances are for example time and especially date picker, ;; which only show the currently activated time/data and hide the ;; selection logic inside the combobox popup. ;; default combobox (nk:layout-row-static ctx 25 200 1) (set! weapon-idx (nk:combo ctx weapons weapon-idx 25 (nk:make-vec2 200 200))) ;; slider color combobox (when (nk:combo-begin-color ctx combo-color (nk:make-vec2 200 200)) (nk:layout-row ctx nk:layout/dynamic 30 '(0.15 0.85)) (nk:label ctx "R:" nk:text/left) (nk:color-r-set! combo-color (nk:slider-int ctx 0 (nk:color-r combo-color) 255 5)) (nk:label ctx "G:" nk:text/left) (nk:color-g-set! combo-color (nk:slider-int ctx 0 (nk:color-g combo-color) 255 5)) (nk:label ctx "B:" nk:text/left) (nk:color-b-set! combo-color (nk:slider-int ctx 0 (nk:color-b combo-color) 255 5)) (nk:label ctx "A:" nk:text/left) (nk:color-a-set! combo-color (nk:slider-int ctx 0 (nk:color-a combo-color) 255 5)) (nk:combo-end ctx)) ;; complex color combobox (when (nk:combo-begin-color ctx (nk:colorf->color combo-color2) (nk:make-vec2 200 400)) (nk:layout-row-dynamic ctx 120 1) (set! combo-color2 (nk:color-picker ctx combo-color2 nk:color/rgba)) (nk:layout-row-dynamic ctx 25 2) (set! use-hsva? (if (nk:option-label ctx "RGB" (not use-hsva?)) #f use-hsva?)) (set! use-hsva? (if (nk:option-label ctx "HSV" use-hsva?) #t use-hsva?)) (nk:layout-row-dynamic ctx 25 1) (if use-hsva? (let* ((hsva (nk:colorf->hsva-f combo-color2)) (h (nk:property-float ctx "#H:" 0 (car hsva) 1.0 0.01 0.005)) (s (nk:property-float ctx "#S:" 0 (cadr hsva) 1.0 0.01 0.005)) (v (nk:property-float ctx "#V:" 0 (list-ref hsva 2) 1.0 0.01 0.005)) (a (nk:property-float ctx "#A:" 0 (list-ref hsva 3) 1.0 0.01 0.005))) (set! combo-color2 (nk:hsva-f->colorf h s v a))) (begin (nk:color-r-set! combo-color2 (nk:property-float ctx "#R:" 0 (nk:color-r combo-color2) 1.0 0.01 0.005)) (nk:color-g-set! combo-color2 (nk:property-float ctx "#G:" 0 (nk:color-g combo-color2) 1.0 0.01 0.005)) (nk:color-b-set! combo-color2 (nk:property-float ctx "#B:" 0 (nk:color-b combo-color2) 1.0 0.01 0.005)) (nk:color-a-set! combo-color2 (nk:property-float ctx "#A:" 0 (nk:color-a combo-color2) 1.0 0.01 0.005)))) (nk:combo-end ctx)) ;; progressbar combobox (let ((sum (+ prog-a prog-b prog-c prog-d))) (when (nk:combo-begin-label ctx (number->string sum) (nk:make-vec2 200 200)) (nk:layout-row-dynamic ctx 30 1) (set! prog-a (nk:progress ctx prog-a 100 nk:modify/modifiable)) (set! prog-b (nk:progress ctx prog-b 100 nk:modify/modifiable)) (set! prog-c (nk:progress ctx prog-c 100 nk:modify/modifiable)) (set! prog-d (nk:progress ctx prog-d 100 nk:modify/modifiable)) (nk:combo-end ctx))) ;; checkbox combobox (let ((sum (count identity check-values))) (when (nk:combo-begin-label ctx (number->string sum) (nk:make-vec2 200 200)) (nk:layout-row-dynamic ctx 30 1) (set! check-values (map-in-order (lambda (checked? weapon) (nk:check-label ctx weapon checked?)) check-values weapons)) (nk:combo-end ctx))) ;; complex text combobox (let ((label (cl-format #f "~{~,2f~^, ~}" position))) (when (nk:combo-begin-label ctx label (nk:make-vec2 200 200)) (nk:layout-row-dynamic ctx 25 1) (set! position (map-in-order (lambda (component label) (nk:property-float ctx label -1024 component 1024 1 0.5)) position '("#X:" "#Y:" "#Z:"))) (nk:combo-end ctx))) ;; chart combobox (let ((label (cl-format #f "~,2f" chart-selection))) (when (nk:combo-begin-label ctx label (nk:make-vec2 200 250)) (nk:layout-row-dynamic ctx 150 1) (let* ((values #(26 13 30 15 25 10 20 40 12 8 22 28 5)) (size (vector-length values))) (nk:chart-begin ctx nk:chart/column size 0 50) (vector-for-each (lambda (_i x) (let ((events (nk:chart-push ctx x))) (when (flag? nk:chart/clicked events) (set! chart-selection x) (nk:combo-close ctx)))) values) (nk:chart-end ctx)) (nk:combo-end ctx))) (when (not time-selected?) (set! selected-time (seconds->local-time))) (when (not date-selected?) (set! selected-date (seconds->local-time))) ;; time combobox (let ((label (time->string selected-time "%H:%M:%S"))) (when (nk:combo-begin-label ctx label (nk:make-vec2 200 250)) (set! time-selected? #t) (nk:layout-row-dynamic ctx 25 1) (vector-set! selected-time 0 (nk:property-int ctx "#S:" 0 (vector-ref selected-time 0) 59 1 1)) (vector-set! selected-time 1 (nk:property-int ctx "#M:" 0 (vector-ref selected-time 1) 59 1 1)) (vector-set! selected-time 2 (nk:property-int ctx "#S:" 0 (vector-ref selected-time 2) 23 1 1)) (nk:combo-end ctx))) ;; date combobox (let ((label (time->string selected-date "%d-%m-%Y"))) (when (nk:combo-begin-label ctx label (nk:make-vec2 350 400)) (let* ((month (vector-ref selected-date 4)) (months #("January" "February" "March" "April" "May" "June" "July" "August" "September" "October" "November" "December")) (month-label (vector-ref months month)) (week-days #("SUN" "MON" "TUE" "WED" "THU" "FRI" "SAT")) (month-days #(31 28 31 30 31 30 31 31 30 31 30 31)) (year (+ (vector-ref selected-date 5) 1900)) (leap-year? (or (and (zero? (modulo year 4)) (not (zero? (modulo year 100)))) (zero? (modulo year 400)))) (days (vector-ref month-days month)) (days (if (and (= month 1) leap-year?) (add1 days) days))) ;; header with month and year (set! date-selected? #t) (nk:layout-row-begin ctx nk:layout/dynamic 20 3) (nk:layout-row-push ctx 0.05) (when (nk:button-symbol ctx nk:symbol/triangle-left) (if (zero? month) (begin (vector-set! selected-date 4 11) (vector-set! selected-date 5 (max 0 (sub1 (vector-ref selected-date 5))))) (vector-set! selected-date 4 (sub1 month)))) (nk:layout-row-push ctx 0.9) (nk:label ctx (format "~a ~a" month-label year) nk:text/centered) (nk:layout-row-push ctx 0.05) (when (nk:button-symbol ctx nk:symbol/triangle-right) (if (= month 11) (begin (vector-set! selected-date 4 0) (vector-set! selected-date 5 (add1 (vector-ref selected-date 5)))) (vector-set! selected-date 4 (add1 month)))) (nk:layout-row-end ctx) ;; good old week day formula (let* ((year-n (if (< month 2) (sub1 year) year)) (y (modulo year-n 100)) (c (quotient year-n 100)) (y4 (floor (/ y 4))) (c4 (floor (/ c 4))) (m (floor (- (* 2.6 (add1 (modulo (+ month 10) 12))) 0.2))) (week-day (modulo (+ (modulo (- (+ 1 m y y4 c4) (* 2 c)) 7) 7) 7))) ;; weekdays (nk:layout-row-dynamic ctx 35 7) (vector-for-each (lambda (_i x) (nk:label ctx x nk:text/centered)) week-days) ;; days (when (> week-day 0) (nk:spacing ctx (inexact->exact week-day))) (let loop ((i 1)) (when (<= i days) (when (nk:button-label ctx (number->string i)) (vector-set! selected-date 3 i) (nk:combo-close ctx)) (loop (add1 i)))))) (nk:combo-end ctx))) (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/node "Input" nk:collapse/minimized) (nk:layout-row ctx nk:layout/static 25 '(120 150)) (nk:label ctx "Default:" nk:text/left) (vector-set! text 0 (nk:edit-string ctx nk:edit/simple (vector-ref text 0) 8)) (nk:label ctx "Int:" nk:text/left) (vector-set! text 1 (nk:edit-string ctx nk:edit/simple (vector-ref text 1) 64 nk:filter-decimal)) (nk:label ctx "Float:" nk:text/left) (vector-set! text 2 (nk:edit-string ctx nk:edit/simple (vector-ref text 2) 64 nk:filter-float)) (nk:label ctx "Hex:" nk:text/left) (vector-set! text 3 (nk:edit-string ctx nk:edit/simple (vector-ref text 3) 64 nk:filter-hex)) (nk:label ctx "Octal:" nk:text/left) (vector-set! text 4 (nk:edit-string ctx nk:edit/simple (vector-ref text 4) 64 nk:filter-oct)) (nk:label ctx "Binary:" nk:text/left) (vector-set! text 5 (nk:edit-string ctx nk:edit/simple (vector-ref text 5) 64 nk:filter-binary)) (nk:label ctx "Password:" nk:text/left) (let* ((password (vector-ref text 6)) (buffer (mask-text password)) (old-length (string-length buffer)) (buffer (nk:edit-string ctx nk:edit/field buffer 64)) (new-length (string-length buffer))) (cond ((> new-length old-length) (vector-set! text 6 (string-append password (substring buffer old-length new-length)))) ((< new-length old-length) (vector-set! text 6 (substring password 0 new-length))))) (nk:label ctx "Field:" nk:text/left) (set! field-buffer (nk:edit-string ctx nk:edit/field field-buffer 64)) (nk:label ctx "Box:" nk:text/left) (nk:layout-row-static ctx 180 278 1) (set! box-buffer (nk:edit-string ctx nk:edit/box box-buffer 512)) (nk:layout-row ctx nk:layout/static 25 '(120 150)) (receive (value edit-events) (nk:edit-string* ctx (->flag nk:edit/field nk:edit/sig-enter) (vector-ref text 7) 64 nk:filter-ascii) (vector-set! text 7 value) (when (or (nk:button-label ctx "Submit") (flag? nk:edit/committed edit-events)) (set! box-buffer (string-append box-buffer value "\n")) (vector-set! text 7 ""))) (nk:tree-pop ctx)) (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/tab "Chart" nk:collapse/minimized) (let ((step (/ (* 2 pi) 32))) ;; line chart (nk:layout-row-dynamic ctx 100 1) (let ((id 0) (index -1)) (when (nk:chart-begin ctx nk:chart/lines 32 -1 1) (let loop ((i 0)) (when (< i 32) (let ((events (nk:chart-push ctx (cos id)))) (when (flag? nk:chart/hovering events) (set! index (floor i))) (when (flag? nk:chart/clicked events) (set! line-index (floor i))) (set! id (+ id step))) (loop (add1 i)))) (nk:chart-end ctx)) (when (not (= index -1)) (let ((value (cos (* index step)))) (nk:tooltip ctx (cl-format #f "Value: ~,2f" value)))) (when (not (= line-index -1)) (nk:layout-row-dynamic ctx 20 1) (let ((value (cos (* line-index step)))) (nk:label ctx (cl-format #f "Selected value: ~,2f" value) nk:text/left)))) ;; column chart (nk:layout-row-dynamic ctx 100 1) (let ((id 0) (index -1)) (when (nk:chart-begin ctx nk:chart/column 32 0 1) (let loop ((i 0)) (when (< i 32) (let ((events (nk:chart-push ctx (abs (sin id))))) (when (flag? nk:chart/hovering events) (set! index (floor i))) (when (flag? nk:chart/clicked events) (set! col-index (floor i))) (set! id (+ id step))) (loop (add1 i)))) (nk:chart-end ctx)) (when (not (= index -1)) (let ((value (abs (sin (* step index))))) (nk:tooltip ctx (cl-format "Value: ~,2f" value)))) (when (not (= col-index -1)) (nk:layout-row-dynamic ctx 20 1) (let ((value (abs (sin (* step col-index))))) (nk:label ctx (cl-format "Selected value: ~,2f" value) nk:text/left)))) ;; mixed chart (nk:layout-row-dynamic ctx 100 1) (when (nk:chart-begin ctx nk:chart/column 32 0 1) (nk:chart-add-slot ctx nk:chart/lines 32 -1 1) (nk:chart-add-slot ctx nk:chart/lines 32 -1 1) (let loop ((i 0) (id 0)) (when (< i 32) (nk:chart-push-slot ctx (abs (sin id)) 0) (nk:chart-push-slot ctx (cos id) 1) (nk:chart-push-slot ctx (sin id) 2) (loop (add1 i) (+ id step))))) (nk:chart-end ctx) ;; mixed colored chart (nk:layout-row-dynamic ctx 100 1) (when (nk:chart-begin-colored ctx nk:chart/lines (nk:rgb->color 255 0 0) (nk:rgb->color 150 0 0) 32 0 1) (nk:chart-add-slot-colored ctx nk:chart/lines (nk:rgb->color 0 0 255) (nk:rgb->color 0 0 150) 32 -1 1) (nk:chart-add-slot-colored ctx nk:chart/lines (nk:rgb->color 0 255 0) (nk:rgb->color 0 150 0) 32 -1 1) (let loop ((i 0) (id 0)) (when (< i 32) (nk:chart-push-slot ctx (abs (sin id)) 0) (nk:chart-push-slot ctx (cos id) 1) (nk:chart-push-slot ctx (sin id) 2) (loop (add1 i) (+ id step))))) (nk:chart-end ctx)) (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/tab "Popup" nk:collapse/minimized) (let ((bounds #f)) ;; menu contextual (nk:layout-row-static ctx 30 150 1) (set! bounds (nk:widget-bounds ctx)) (nk:label ctx "Right click me for menu" nk:text/left) (when (nk:contextual-begin ctx 0 (nk:make-vec2 100 300) bounds) (nk:layout-row-dynamic ctx 25 1) (set! show-menu? (nk:check-label ctx "Menu" show-menu?)) (set! progress (nk:progress ctx progress 100 nk:modify/modifiable)) (set! slider (nk:slider-int ctx 0 slider 16 1)) (when (nk:contextual-item-label ctx "About" nk:text/centered) (set! show-app-about? #t)) (set! selected (map-in-order (lambda (value) (nk:selectable-label ctx (if value "Unselect" "Select") nk:text/left value)) selected)) (nk:contextual-end ctx)) ;; color contextual (nk:layout-row-begin ctx nk:layout/static 30 2) (nk:layout-row-push ctx 100) (nk:label ctx "Right Click here:" nk:text/left) (nk:layout-row-push ctx 50) (set! bounds (nk:widget-bounds ctx)) (nk:button-color ctx color) (nk:layout-row-end ctx) (when (nk:contextual-begin ctx 0 (nk:make-vec2 350 60) bounds) (nk:layout-row-dynamic ctx 30 4) (nk:color-r-set! color (nk:property-int ctx "#r:" 0 (nk:color-r color) 255 1 1)) (nk:color-g-set! color (nk:property-int ctx "#g:" 0 (nk:color-g color) 255 1 1)) (nk:color-b-set! color (nk:property-int ctx "#b:" 0 (nk:color-b color) 255 1 1)) (nk:color-a-set! color (nk:property-int ctx "#a:" 0 (nk:color-a color) 255 1 1)) (nk:contextual-end ctx)) ;; popup (nk:layout-row-begin ctx nk:layout/static 30 2) (nk:layout-row-push ctx 100) (nk:label ctx "Popup:" nk:text/left) (nk:layout-row-push ctx 50) (when (nk:button-label ctx "Popup") (set! popup-active? #t)) (nk:layout-row-end ctx) (if popup-active? (when (nk:popup-begin ctx nk:popup/static "Error" 0 (nk:make-rect 20 100 220 150)) (nk:layout-row-dynamic ctx 25 1) (nk:label ctx "A terrible error has occurred" nk:text/left) (nk:layout-row-dynamic ctx 25 2) (when (nk:button-label ctx "OK") (set! popup-active? #f) (nk:popup-close ctx)) (when (nk:button-label ctx "Cancel") (set! popup-active? #f) (nk:popup-close ctx)) (nk:popup-end ctx)) (set! popup-active? #f)) ;; tooltip (nk:layout-row-static ctx 30 150 1) (set! bounds (nk:widget-bounds ctx)) (nk:label ctx "Hover me for tooltip" nk:text/left) (when (nk:input-mouse-hovering-in-rect? (nk:context-input ctx) bounds) (nk:tooltip ctx "This is a tooltip"))) (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/tab "Layout" nk:collapse/minimized) (when (nk:tree-push ctx nk:tree/node "Widget" nk:collapse/minimized) (nk:layout-row-dynamic ctx 30 1) (nk:label ctx "Dynamic fixed column layout with generated position and size:" nk:text/left) (nk:layout-row-dynamic ctx 30 3) (nk:button-label ctx "button") (nk:button-label ctx "button") (nk:button-label ctx "button") (nk:layout-row-dynamic ctx 30 1) (nk:label ctx "static fixed column layout with generated position and size:" nk:text/left) (nk:layout-row-static ctx 30 100 3) (nk:button-label ctx "button") (nk:button-label ctx "button") (nk:button-label ctx "button") (nk:layout-row-dynamic ctx 30 1) (nk:label ctx "Dynamic list-based custom column layout with generated position and custom size:" nk:text/left) (nk:layout-row ctx nk:layout/dynamic 30 '(0.2 0.6 0.2)) (nk:button-label ctx "button") (nk:button-label ctx "button") (nk:button-label ctx "button") (nk:layout-row-dynamic ctx 30 1) (nk:label ctx "Static list-based custom column layout with generated position and custom size:" nk:text/left) (nk:layout-row ctx nk:layout/static 30 '(100 200 50)) (nk:button-label ctx "button") (nk:button-label ctx "button") (nk:button-label ctx "button") (nk:layout-row-dynamic ctx 30 1) (nk:label ctx "Dynamic immediate mode custom column layout with generated position and custom size:" nk:text/left) (nk:layout-row-begin ctx nk:layout/dynamic 30 3) (nk:layout-row-push ctx 0.2) (nk:button-label ctx "button") (nk:layout-row-push ctx 0.6) (nk:button-label ctx "button") (nk:layout-row-push ctx 0.2) (nk:button-label ctx "button") (nk:layout-row-end ctx) (nk:layout-row-dynamic ctx 30 1) (nk:label ctx "Static immediate mode custom column layout with generated position and custom size:" nk:text/left) (nk:layout-row-begin ctx nk:layout/static 30 3) (nk:layout-row-push ctx 100) (nk:button-label ctx "button") (nk:layout-row-push ctx 200) (nk:button-label ctx "button") (nk:layout-row-push ctx 50) (nk:button-label ctx "button") (nk:layout-row-end ctx) (nk:layout-row-dynamic ctx 30 1) (nk:label ctx "Static free space with custom position and custom size:" nk:text/left) (nk:layout-space-begin ctx nk:layout/static 120 4) (nk:layout-space-push ctx (nk:make-rect 100 0 100 30)) (nk:button-label ctx "button") (nk:layout-space-push ctx (nk:make-rect 0 15 100 30)) (nk:button-label ctx "button") (nk:layout-space-push ctx (nk:make-rect 200 15 100 30)) (nk:button-label ctx "button") (nk:layout-space-push ctx (nk:make-rect 100 30 100 30)) (nk:button-label ctx "button") (nk:layout-space-end ctx) (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/node "Group" nk:collapse/minimized) (nk:layout-row-dynamic ctx 30 3) (set! group-titlebar? (nk:check-label ctx "Titlebar" group-titlebar?)) (set! group-border? (nk:check-label ctx "Border" group-border?)) (set! group-no-scrollbar? (nk:check-label ctx "No Scrollbar" group-no-scrollbar?)) (nk:layout-row-begin ctx nk:layout/static 22 3) (nk:layout-row-push ctx 50) (nk:label ctx "size:" nk:text/left) (nk:layout-row-push ctx 130) (set! group-width (nk:property-int ctx "#Width:" 100 group-width 500 10 1)) (nk:layout-row-push ctx 130) (set! group-height (nk:property-int ctx "#Height:" 100 group-height 500 10 1)) (nk:layout-row-end ctx) (nk:layout-row-static ctx group-height group-width 2) (when (nk:group-begin ctx "Group" (group-flags)) (nk:layout-row-static ctx 18 100 1) (set! selected-group (map-in-order (lambda (value) (nk:selectable-label ctx (if value "Selected" "Unselected") nk:text/centered value)) selected-group)) (nk:group-end ctx)) (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/node "Tree" nk:collapse/minimized) (let ((sel root-selected)) (receive (open? sel) (nk:tree-element-push ctx nk:tree/node "Root" nk:collapse/minimized sel) (when open? (let ((node-select (car selected-leaves))) (when (not (eqv? sel root-selected)) (set! root-selected sel) (set! selected-leaves (make-list 8 sel))) (receive (open? node-select) (nk:tree-element-push ctx nk:tree/node "Node" nk:collapse/minimized node-select) (when open? (when (not (eqv? node-select (car selected-leaves))) (set-car! selected-leaves node-select) (set! selected-nodes (make-list node-select 4))) (nk:layout-row-static ctx 18 100 1) (set! selected-nodes (map-in-order (lambda (selected-node) (nk:selectable-symbol-label ctx nk:symbol/circle-solid (if selected-node "Selected" "Unselected") nk:text/right selected-node)) selected-nodes)) (nk:tree-element-pop ctx))) (nk:layout-row-static ctx 18 100 1) (set! selected-leaves (map-in-order (lambda (selected-leaf) (nk:selectable-symbol-label ctx nk:symbol/circle-solid (if selected-leaf "Selected" "Unselected") nk:text/right selected-leaf)) selected-leaves))) (nk:tree-element-pop ctx)))) (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/node "Notebook" nk:collapse/minimized) ;; TODO (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/node "Simple" nk:collapse/minimized) (nk:layout-row-dynamic ctx 300 2) (when (nk:group-begin ctx "Group_Without_Border" 0) (nk:layout-row-static ctx 18 150 1) (let loop ((i 0)) (when (< i 64) (nk:label ctx (cl-format #f "0x~2,'0x: scrollable region" i) nk:text/left) (loop (add1 i)))) (nk:group-end ctx)) (when (nk:group-begin ctx "Group_With_Border" nk:window/border) (nk:layout-row-dynamic ctx 25 2) (let loop ((i 0)) (when (< i 64) (let ((x (+ (bitwise-xor (* (modulo i 7) 10) 32) 64 (* (modulo i 2) 2)))) (nk:button-label ctx (cl-format #f "~8,'0d" x)) (loop (add1 i))))) (nk:group-end ctx)) (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/node "Complex" nk:collapse/minimized) (nk:layout-space-begin ctx nk:layout/static 500 64) (nk:layout-space-push ctx (nk:make-rect 0 0 150 500)) (when (nk:group-begin ctx "Group_left" nk:window/border) (nk:layout-row-static ctx 18 100 1) (set! left-selected-group (map-in-order (lambda (value) (nk:selectable-label ctx (if value "Selected" "Unselected") nk:text/centered value)) left-selected-group)) (nk:group-end ctx)) (nk:layout-space-push ctx (nk:make-rect 160 0 150 240)) (when (nk:group-begin ctx "Group_top" nk:window/border) (nk:layout-row-dynamic ctx 25 1) (nk:button-label ctx "#FFAA") (nk:button-label ctx "#FFBB") (nk:button-label ctx "#FFCC") (nk:button-label ctx "#FFDD") (nk:button-label ctx "#FFEE") (nk:button-label ctx "#FFFF") (nk:group-end ctx)) (nk:layout-space-push ctx (nk:make-rect 160 250 150 250)) (when (nk:group-begin ctx "Group_bottom" nk:window/border) (nk:layout-row-dynamic ctx 25 1) (nk:button-label ctx "#FFAA") (nk:button-label ctx "#FFBB") (nk:button-label ctx "#FFCC") (nk:button-label ctx "#FFDD") (nk:button-label ctx "#FFEE") (nk:button-label ctx "#FFFF") (nk:group-end ctx)) (nk:layout-space-push ctx (nk:make-rect 320 0 150 150)) (when (nk:group-begin ctx "Group_right_top" nk:window/border) (nk:layout-row-static ctx 18 100 1) (set! top-right-selected-group (map-in-order (lambda (value) (nk:selectable-label ctx (if value "Selected" "Unselected") nk:text/centered value)) top-right-selected-group)) (nk:group-end ctx)) (nk:layout-space-push ctx (nk:make-rect 320 160 150 150)) (when (nk:group-begin ctx "Group_right_center" nk:window/border) (nk:layout-row-static ctx 18 100 1) (set! center-right-selected-group (map-in-order (lambda (value) (nk:selectable-label ctx (if value "Selected" "Unselected") nk:text/centered value)) center-right-selected-group)) (nk:group-end ctx)) (nk:layout-space-push ctx (nk:make-rect 320 320 150 150)) (when (nk:group-begin ctx "Group_right_bottom" nk:window/border) (nk:layout-row-static ctx 18 100 1) (set! bottom-right-selected-group (map-in-order (lambda (value) (nk:selectable-label ctx (if value "Selected" "Unselected") nk:text/centered value)) bottom-right-selected-group)) (nk:group-end ctx)) (nk:layout-space-end ctx) (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/node "Splitter" nk:collapse/minimized) (let ((input (nk:context-input ctx))) (nk:layout-row-static ctx 20 310 1) (nk:label ctx "Use slider and spinner to change tile size" nk:text/left) (nk:label ctx "Drag the space between tiles to change tile ratio" nk:text/left) (when (nk:tree-push ctx nk:tree/node "Vertical" nk:collapse/minimized) (let ((row-layout (list vertical-a 8 vertical-b 8 vertical-c)) (bounds #f)) ;; header (nk:layout-row-static ctx 30 100 2) (nk:label ctx "left:" nk:text/left) (set! vertical-a (nk:slider-float ctx 10 vertical-a 200 10)) (nk:label ctx "middle:" nk:text/left) (set! vertical-b (nk:slider-float ctx 10 vertical-b 200 10)) (nk:label ctx "right:" nk:text/left) (set! vertical-c (nk:slider-float ctx 10 vertical-c 200 10)) ;; tiles (nk:layout-row ctx nk:layout/static 200 row-layout) ;; left space (when (nk:group-begin ctx "left" (->flag nk:window/border nk:window/no-scrollbar)) (nk:layout-row-dynamic ctx 25 1) (nk:button-label ctx "#FFAA") (nk:button-label ctx "#FFBB") (nk:button-label ctx "#FFCC") (nk:button-label ctx "#FFDD") (nk:button-label ctx "#FFEE") (nk:button-label ctx "#FFFF") (nk:group-end ctx)) ;; scaler (set! bounds (nk:widget-bounds ctx)) (nk:spacing ctx 1) (when (and (or (nk:input-mouse-hovering-in-rect? input bounds) (nk:input-mouse-previously-hovering-in-rect? input bounds)) (nk:input-mouse-down? input nk:button/left)) (let ((delta (nk:mouse-delta (nk:input-mouse input)))) (set! vertical-a (+ (car row-layout) (nk:vec2-x delta))) (set! vertical-b (- (list-ref row-layout 2) (nk:vec2-x delta))))) ;; middle space (when (nk:group-begin ctx "center" (->flag nk:window/border nk:window/no-scrollbar)) (nk:layout-row-dynamic ctx 25 1) (nk:button-label ctx "#FFAA") (nk:button-label ctx "#FFBB") (nk:button-label ctx "#FFCC") (nk:button-label ctx "#FFDD") (nk:button-label ctx "#FFEE") (nk:button-label ctx "#FFFF") (nk:group-end ctx)) ;; scaler (set! bounds (nk:widget-bounds ctx)) (nk:spacing ctx 1) (when (and (or (nk:input-mouse-hovering-in-rect? input bounds) (nk:input-mouse-previously-hovering-in-rect? input bounds)) (nk:input-mouse-down? input nk:button/left)) (let ((delta (nk:vec2-x (nk:mouse-delta (nk:input-mouse input))))) (set! vertical-b (+ (list-ref row-layout 2) delta)) (set! vertical-c (- (list-ref row-layout 4) delta)))) ;; right space (when (nk:group-begin ctx "right" (->flag nk:window/border nk:window/no-scrollbar)) (nk:layout-row-dynamic ctx 25 1) (nk:button-label ctx "#FFAA") (nk:button-label ctx "#FFBB") (nk:button-label ctx "#FFCC") (nk:button-label ctx "#FFDD") (nk:button-label ctx "#FFEE") (nk:button-label ctx "#FFFF") (nk:group-end ctx))) (nk:tree-pop ctx)) (when (nk:tree-push ctx nk:tree/node "Horizontal" nk:collapse/minimized) (let ((bounds #f)) ;; header (nk:layout-row-static ctx 30 100 2) (nk:label ctx "top:" nk:text/left) (set! horizontal-a (nk:slider-float ctx 10 horizontal-a 200 10)) (nk:label ctx "middle:" nk:text/left) (set! horizontal-b (nk:slider-float ctx 10 horizontal-b 200 10)) (nk:label ctx "bottom:" nk:text/left) (set! horizontal-c (nk:slider-float ctx 10 horizontal-c 200 10)) ;; top space (nk:layout-row-dynamic ctx horizontal-a 1) (when (nk:group-begin ctx "top" (->flag nk:window/border nk:window/no-scrollbar)) (nk:layout-row-dynamic ctx 25 3) (nk:button-label ctx "#FFAA") (nk:button-label ctx "#FFBB") (nk:button-label ctx "#FFCC") (nk:button-label ctx "#FFDD") (nk:button-label ctx "#FFEE") (nk:button-label ctx "#FFFF") (nk:group-end ctx)) ;; scaler (nk:layout-row-dynamic ctx 8 1) (set! bounds (nk:widget-bounds ctx)) (nk:spacing ctx 1) (when (and (or (nk:input-mouse-hovering-in-rect? input bounds) (nk:input-mouse-previously-hovering-in-rect? input bounds)) (nk:input-mouse-down? input nk:button/left)) (let ((delta (nk:vec2-y (nk:mouse-delta (nk:input-mouse input))))) (set! horizontal-a (+ horizontal-a delta)) (set! horizontal-b (- horizontal-b delta)))) ;; middle space (nk:layout-row-dynamic ctx horizontal-b 1) (when (nk:group-begin ctx "middle" (->flag nk:window/border nk:window/no-scrollbar)) (nk:layout-row-dynamic ctx 25 3) (nk:button-label ctx "#FFAA") (nk:button-label ctx "#FFBB") (nk:button-label ctx "#FFCC") (nk:button-label ctx "#FFDD") (nk:button-label ctx "#FFEE") (nk:button-label ctx "#FFFF") (nk:group-end ctx)) ;; scaler (nk:layout-row-dynamic ctx 8 1) (set! bounds (nk:widget-bounds ctx)) (when (and (or (nk:input-mouse-hovering-in-rect? input bounds) (nk:input-mouse-previously-hovering-in-rect? input bounds)) (nk:input-mouse-down? input nk:button/left)) (let ((delta (nk:vec2-y (nk:mouse-delta (nk:input-mouse input))))) (set! horizontal-b (+ horizontal-b delta)) (set! horizontal-c (- horizontal-c delta)))) ;; bottom space (nk:layout-row-dynamic ctx horizontal-c 1) (when (nk:group-begin ctx "bottom" (->flag nk:window/border nk:window/no-scrollbar)) (nk:layout-row-dynamic ctx 25 3) (nk:button-label ctx "#FFAA") (nk:button-label ctx "#FFBB") (nk:button-label ctx "#FFCC") (nk:button-label ctx "#FFDD") (nk:button-label ctx "#FFEE") (nk:button-label ctx "#FFFF") (nk:group-end ctx))) (nk:tree-pop ctx))) (nk:tree-pop ctx)) (nk:tree-pop ctx))) (nk:window-end ctx) (let-values (((width height) (glfw:get-window-size (glfw:window)))) (gl:viewport 0 0 width height)) (gl:clear gl:+color-buffer-bit+) (gl:clear-color (nk:color-r bg) (nk:color-g bg) (nk:color-b bg) (nk:color-a bg)) (nk:render nk:anti-aliasing/on) (glfw:swap-buffers (glfw:window)) (loop))) (nk:shutdown) (glfw:terminate)