Lots of gui updates, more widgets-layouts-containers-etc. Also fixes gui-use-light-theme to work more reliably.

This commit is contained in:
sloum 2022-04-21 15:05:33 -07:00
parent 8dd7392320
commit bc3d0e07d9
4 changed files with 174 additions and 55 deletions

View File

@ -12,24 +12,37 @@
(define e1 (widget-make-entry "Link Text" #f (lambda (s) (if (regex-match? ".+" s) #t "Invalid entry"))))
(define l2 (widget-make-label "URL"))
(define e2 (widget-make-entry "Link URL" #f (lambda (s) (if (regex-match? "[http|https|gemini|gopher|ftp]://.+\..+" s) #t "URL missing scheme"))))
(define cb (widget-make-checkbox "Light Theme"
(lambda (state)
(if state
(gui-use-light-theme app #t)
(gui-use-light-theme app #f)))))
(define b (widget-make-button "Submit"
(lambda ()
(define t (widget-get-text e1))
(define u (widget-get-text e2))
(widget-set-text e1 "")
(widget-set-text e2 "")
(container-add-to contents (container "hbox" (widget-make-spacer) (widget-make-hyperlink t u)))) 0))
(if (not (or (equal? "" u) (equal? "" t)))
(begin
(widget-set-text e1 "")
(widget-set-text e2 "")
(container-add-to contents (container "hbox" (widget-make-spacer) (widget-make-hyperlink t u)))))) 0))
(define sel (widget-make-select ["Seitan" "Tofu" "Veggies" "Kimchi"] (lambda (choice) (display choice (gui-use-light-theme app) "\n")) 0))
(define md (widget-make-markdown "# Title 1\n\nThis is just some paragraph text to see how things will go if I add a _decent_ amount of text.\n\n- List item 1\n- List item 2\n\n[md-link](https://git.rawtext.club)\n" #t))
; Set up the container(s)
(set! contents (container "vbox" l (widget-make-separator) (container "form" l1 e1 l2 e2) b (widget-make-separator) (container "hbox" (widget-make-spacer) (widget-make-hyperlink "by sloum" "http://sloum.colorfield.space/"))))
(set! contents (container "vbox" l md (widget-make-separator) (container "form" l1 e1 l2 e2) cb sel b (widget-make-separator) (container "hbox" (widget-make-spacer) (widget-make-hyperlink "by sloum" "http://sloum.colorfield.space/"))))
(define scroller (container-scroll contents))
; Configure the window
(gui-add-window app "main")
(window-set-content app "main" contents)
(window-resize app "main" (* (car (container-size contents)) 4) (car (cdr (container-size contents))))
(window-set-content app "main" scroller)
(window-resize app "main" 400 500)
(window-center app "main")
(window-set-title app "main" "Log In Form")
; Go time.
(window-show-and-run app "main")

134
gui.go
View File

@ -2,16 +2,11 @@
package main
// TODO add:
// widget-make-text-grid
// widget-make-check
// widget-make-select
import (
"fmt"
"image/color"
"net/url"
"os"
"reflect"
"strconv"
"strings"
@ -105,19 +100,25 @@ var guiLib = vars{
return out
},
"gui-use-light-theme": func(a ...expression) expression {
if len(a) < 1 {
v := os.Getenv("FYNE_THEME")
if v == "light" {
return true
} else {
return false
}
if len(a) == 0 {
return exception("'gui-use-light-theme' expects a gui-root as its first argument and, optionally, a bool as its second argument, no arguments were given")
}
b := AnythingToBool(a[0]).(bool)
app, ok := a[0].(*GUI)
if !ok {
return exception("'gui-use-light-theme' expects a gui-root as its first argument, a non-gui-root value was given")
}
// If the current theme is == to the light theme return true, else false
if len(a) == 1 {
return reflect.DeepEqual(app.gui.Settings().Theme(), theme.LightTheme())
}
b := AnythingToBool(a[1]).(bool)
if b {
os.Setenv("FYNE_THEME", "light")
app.gui.Settings().SetTheme(theme.LightTheme())
} else {
os.Unsetenv("FYNE_THEME")
app.gui.Settings().SetTheme(theme.DarkTheme())
}
return b
},
@ -502,6 +503,75 @@ var guiLib = vars{
}
return l
},
"widget-make-select": func(a ...expression) expression {
if len(a) < 2 {
return exception("'widget-make-select' expects a list of options as strings, a callback (lambda), and an optional alignment number too few arguments were given")
}
elist, ok := a[0].([]expression)
if !ok {
return exception("'widget-make-select' expected a list as its first argument, but was given a non-list value")
}
list := ExpressionSliceToStringSlice(elist)
var b guiWidget
switch f := a[1].(type) {
case func(...expression) expression:
b = widget.NewSelect(list, func(in string) { f(in) })
case proc:
b = widget.NewSelect(list, func(in string) { apply(f, []expression{in}) })
default:
return exception("'widget-make-select' was given a non-procedure value as its second argument")
}
if len(a) >= 3 {
align, ok := a[2].(number)
if !ok {
return exception("'widget-make-button' expects a number (-1, 0, or 1) as its optional third argument (alignment), a non-number value was given")
}
switch int(align) {
case -1:
b.(*widget.Select).Alignment = fyne.TextAlignLeading
case 0:
b.(*widget.Select).Alignment = fyne.TextAlignCenter
case 1:
b.(*widget.Select).Alignment = fyne.TextAlignTrailing
default:
return exception("'widget-make-select' expects a number (-1, 0, or 1) as its optional third argument (alignment), a number outside of the range was given")
}
}
return b
},
"widget-make-markdown": func(a ...expression) expression {
if len(a) == 0 {
return exception("'widget-make-markdown' expects a string but was given no arguments")
}
var b guiWidget
b = widget.NewRichTextFromMarkdown(String(a[0], false))
if len(a) >= 2 {
wrap := AnythingToBool(a[1]).(bool)
if wrap {
b.(*widget.RichText).Wrapping = fyne.TextWrapWord
}
}
return b
},
"widget-make-checkbox": func(a ...expression) expression {
if len(a) < 2 {
return exception("'widget-make-checkbox' expects a text string and a callback (lambda), too few arguments were given")
}
var b guiWidget
switch f := a[1].(type) {
case func(...expression) expression:
b = widget.NewCheck(String(a[0], false), func(in bool) { f(in) })
case proc:
b = widget.NewCheck(String(a[0], false), func(in bool) { apply(f, []expression{in}) })
default:
return exception("'widget-make-checkbox' was given a non-procedure value as its second argument")
}
return b
},
"widget-make-hyperlink": func(a ...expression) expression {
if len(a) < 2 {
return exception("'widget-make-hyperlink' expects a text string and a URL string, too few arguments were given")
@ -594,15 +664,37 @@ var guiLib = vars{
var spacer guiObject = layout.NewSpacer()
return spacer
},
"container-scroll": func(a ...expression) expression {
if len(a) < 1 {
return exception("'container-scroll' expects at least one widget or layout, no values were given")
}
list, err := ExpToCanvasObjectList(a)
if err != nil || len(list) < 1 {
return exception("'container-scroll' was given a non-widget value")
}
return guiContainer(container.NewScroll(list[0]))
},
"container": func(a ...expression) expression {
if len(a) < 2 {
return exception("'container' expects two arguments, a string representing the layout type and at least one widget or layout, no values were given")
return exception("'container' expects at least two arguments, a string representing the layout type and at least one widget or layout (or in some layout types an additional value), no values were given")
}
list, err := ExpToCanvasObjectList(a[1:])
containerType := String(a[0], false)
widgetStart := 1
cols := 0
if containerType == "grid" {
if len(a) < 3 {
return exception("'container' with layout 'grid' expects at least three arguments, a string representing the layout type, a number representing the column count, and at least one widget or layout, no values were given")
}
if count, ok := a[1].(number); ok {
widgetStart = 2
cols = int(float64(count))
}
}
list, err := ExpToCanvasObjectList(a[widgetStart:])
if err != nil {
return exception("'container' was given a non-widget value")
}
switch String(a[0], false) {
switch containerType {
case "none":
return guiContainer(container.NewWithoutLayout(list...))
case "hbox":
@ -617,6 +709,8 @@ var guiLib = vars{
return guiContainer(container.NewMax(list...))
case "padded":
return guiContainer(container.NewPadded(list...))
case "grid":
return guiContainer(container.NewGridWithColumns(cols, list...))
default:
return exception("'container-with-layout' was given an invalid layout type")
}
@ -708,7 +802,7 @@ var guiLib = vars{
},
"dialog-info": func(a ...expression) expression {
if len(a) < 4 {
return exception("'dialog-info' expected four arguments: a GUI, a string representing a gui-window-id, a title string, and a message string; an insufficient number of arguments was given")
return exception("'dialog-info' expected four arguments: a GUI, a string representing a window-name, a title string, and a message string; an insufficient number of arguments was given")
}
app, ok := a[0].(*GUI)
if !ok {

View File

@ -5,40 +5,44 @@ package main
const guiIsOn = "(gui)"
var guiUsageStrings = map[string]string{
"gui-create": "(gui-create) => GUI-Root\n\nCreates the application root for a gui application. See: `gui-add-window` for information about adding content to a gui-root. In general you will always want to use `define` when creating a GUI-Root as everything is done by passing it as a reference later on in the development process for GUI applications",
"dialog-error": "(dialog-error [gui-root] [window-name: string] [error: string]) => ()\n\nShows an error message. The dialog that is opened is not a system native dialog and will be constrained by the window size",
"dialog-info": "(dialog-info [gui-root] [window-name: string] [title: string] [message: string]) => ()\n\nShows an information window with the given title and message. The dialog that is opened is not a system native dialog and will be constrained by the window size",
"dialog-open-file": "(dialog-open-file [app: gui-root] [window-name: string] [callback: lambda]) => ()\n\nCreates an 'open file' dialog. The given lambda should take one argument, a string representing the selected file path. The dialog that is opened is not a system native dialog and will be constrained by the window size",
"dialog-save-file": "(dialog-save-file [app: gui-root] [window-name: string] [callback: lambda]) => ()\n\nCreates an 'save file' dialog. The given lambda should take one argument, a string representing the selected file path. The dialog that is opened is not a system native dialog and will be constrained by the window size",
"container": "(container [layout: string] [[columns: number]] [contents: gui-widget|container...])\n\n`container` is the basic layout unit of the slope gui system. It can hold any number of other widgets or containers. The columns value is shown as optional, despite having a mandatory value after it, because it is only available for the `grid` layout. Do not pass `columns` for any other layout. The available layout strings are:\n\n\tnone - No layout\n\n\thbox - arranges items in a horizontal row. Every element will have the same height (the height of the tallest item in the container) and objects will be left-aligned at their minimum width\n\n\tvbox - arranges items in a vertical column. Every element will have the same width (the width of the widest item in the container) and objects will be top-aligned at their minimum height\n\n\tform - arranges items in pairs where the first column is at minimum width. This is normally useful for labelling elements in a form, where the label is in the first column and the item it describes is in the second. You should always add an even number of elements to a form layout\n\n\tgrid - positions elements into the given number of columns from left to right top to bottom. All grid elements will be evenly sized\n\n\tcenter - positions all container elements in the center of the container. Every object will be set to its minimum size\n\n\tmax - positions all container elements to fill the available space. The objects will all be full-sized and drawn in the order they were added to the container (last-most is on top)\n\n\tpadded - positions all container elements to fill the available space but with a small padding around the outside. The size of the padding is theme specific. The objects will all be drawn in the order they were added to the container (last-most is on top)",
"container-add-to": "(container-add-to [parent: gui-container] [child: gui-widget|gui-container]) => #t\n\nAdds the given child widget/container to the given parent container",
"container-scroll": "(container-scroll [gui-container]) => gui-container\n\nTakes a single, unlike the other containers, container (which can in turn contain widgets or other containers). The minimum size of the container it is passed will be ignored and scroll bars will be added as needed. Note that since `container-scroll` does not accept more than one `gui-container` a call to `container-add-to` targeting a container generated by `container-scroll` will result in a runtime panic",
"container-size": "(container-size [gui-container]) => list\n\nReturns a two item list containing the given gui-container's width and height (in that order)",
"gui-add-window": "(gui-add-window [app: gui-root] [name: string])\n\nAdds a window to the given gui-root as returned by `gui-create`. Name will be used to refer to the newly created window in other procedures. A string is prefered and called for in the procedure signature, but any other value can be used and will be stringified",
"gui-create": "(gui-create) => GUI-Root\n\nCreates the application root for a gui application. See: `gui-add-window` for information about adding content to a gui-root. In general you will always want to use `define` when creating a GUI-Root as everything is done by passing it as a reference later on in the development process for GUI applications",
"gui-list-windows": "(gui-list-windows [app: gui-root]) => list\n\nReturns a list containing the name of each window associated with the given gui-root",
"gui-use-light-theme": "(gui-use-light-theme [[bool]]) => bool\n\nIf no arguments are given `gui-use-light-theme` will check is a light theme is being used and return #t if so, #f if not. Any value passed to `gui-use-light-theme` will be coerced to a bool. If the given value is #t then the gui will be set to use the light them, otherwise the dark theme will be used",
"window-set-content": "(window-set-content [app: gui-root] [window-name: string] [content: gui-widget|gui-container]) => #t\n\nSets the content for the given window. This is usually a `container`, but could be a `widget`. #t or an exception will be returned",
"window-resize": "(window-resize [app: gui-root] [window-name: string] [width: number] [height: number]) => #t\n\nResizes the given app's given window to the width and height that were given, if possible. This is a finicky function in the underlying library and seems to behave unexpectedly or not at all",
"window-show": "(window-show [app: gui-root] [window-name: string]) => #t\n\nShows the given window. There is no effect when called on an already visible window",
"window-hide": "(window-hide [app: gui-root] [window-name: string]) => #t\n\nHides the given window. There is no effect when called on an already hidden window",
"window-close": "(window-close [app: gui-root] [window-name: string]) => #t\n\nCloses the given window. When called on an already closed window the behavior is undefined",
"window-set-title": "(window-set-title [app: gui-root] [window-name: string] [title: string]) => #t\n\nSets the title of the window to the given title string. If a non-string value is passed as title a stringified version of the value will be used",
"window-set-fullscreen": "(window-set-fullscreen [app: gui-root] [window-name: string] [set-to-full-screen: bool]) => #t\n\nSets the given window to full screen if #t is given and removes it from full screen if #f is given",
"window-show-and-run": "(window-show-and-run [app: gui-root] [window-name: string]) => #t\n\nRuns the gui with the given window visible. This is the main procedure for starting the gui and will block once evaluated until the window is closed",
"window-center": "(window-center [app: gui-root] [window-name: string]) => #t\n\nCenters the given window on the screen",
"window-allow-resize": "(window-allow-resize [app: gui-root] [window-name: string] [bool]) => #t\n\nSets whether or not to allow the user to resize the given window",
"widget-show": "(widget-show [gui-widget]) => #t\n\nShows the given gui-widget. The widget will only become visible if it is in a visible grouping (window, container, layout, etc). Calling on an already visible widget will have no effect",
"widget-hide": "(widget-show [gui-widget]) => #t\n\nHides the given gui-widget. Calling on an already hidden widget will have no effect",
"widget-resize": "(widget-resize [gui-widget] [width: number] [height: number]) => gui-widget\n\nIn general the size of widgets is defined by the container/layout. However, in cases where it is not, `widget-resize` can be used. If used in a situation where it cannot be used, there will be no effect. Returns the widget with the new size",
"widget-size": "(widget-size [gui-widget]) => list\n\nReturns the given widget's current width and height, in that order, in a two item list",
"widget-add-to-size": "(widget-add-to-size [gui-widget] [width-change: number] [height-change: number]) => gui-widget\n\nUpdates the width and height of the given widget by adding the width-change value to the current width and the height-change value to the current height. Returns the updated widget",
"widget-make-entry": "(widget-make-entry [placeholder-text: string] [[wrap-text: bool]] [[validation-callback: lambda]]) => gui-widget\n\nCreates an entry widget with the given placeholder value. For accessibility purposes it is always advised to also have a label widget describing this widget. If a validation lambda is given it should take a string value as its argument and should validate based on that string. If it successfully validates `#t` or any non-string value should be returned, otherwise a string explaining the error should be returned",
"widget-make-password": "(widget-make-password [placeholder-text: string] [[wrap-text: bool]] [[validation-callback: lambda]]) => gui-widget\n\nCreates an password widget with the given placeholder value. For accessibility purposes it is always advised to also have a label widget describing this widget. If a validation lambda is given it should take a string value as its argument and should validate based on that string. If it successfully validates `#t` or any non-string value should be returned, otherwise a string explaining the error should be returned",
"widget-make-multiline": "(widget-make-multiline [placeholder-text: string] [[wrap-text: bool]] [[validation-callback: lambda]]) => gui-widget\n\nCreates a multiline text entry widget with the given placeholder value. For accessibility purposes it is always advised to also have a label widget describing this widget. If a validation lambda is given it should take a string value as its argument and should validate based on that string. If it successfully validates `#t` or any non-string value should be returned, otherwise a string explaining the error should be returned",
"widget-make-label": "(widget-make-label [text: string] [[alignment: number]] [[wrap-text: bool]]) => gui-widget\n\nCreates a label widget with the given text. If alignment is given it should be one of:\n\n\t-1: Align Leading\n\t 0: Align Center\n\t 1: Align Trailing",
"widget-make-hyperlink": "(widget-make-hyperlink [text: string] [url: string]) => gui-widget\n\nCreates a hyperlink widget with the given text linking to the given URL. If the URL cannot be parsed as a valid URL an exception will be returned",
"widget-make-button": "(widget-make-button [text: string] [callback: lambda] [[alignment: number]]) => gui-widget\n\nCreates a button widget with the given text. The callback should accept no arguments and should only create side effects (the return value will be discarded). If alignment is given it should be one of:\n\n\t-1: Align Leading\n\t 0: Align Center\n\t 1: Align Trailing",
"widget-get-text": "(widget-get-text [gui-widget]) => string\n\nRetrieves the text of the given widget",
"widget-set-text": "(widget-set-text [gui-widget] [string]) => string\n\nSets the text of the given widget to the given string and returns the string",
"widget-hide": "(widget-show [gui-widget]) => #t\n\nHides the given gui-widget. Calling on an already hidden widget will have no effect",
"widget-make-button": "(widget-make-button [text: string] [callback: lambda] [[alignment: number]]) => gui-widget\n\nCreates a button widget with the given text. The callback should accept no arguments and should only create side effects (the return value will be discarded). If alignment is given it should be one of:\n\n\t-1: Align Leading\n\t 0: Align Center\n\t 1: Align Trailing",
"widget-make-checkbox": "(widget-make-checkbox [text: string] [callback: lambda]) => gui-widget\n\nCreates a button widget with the given text. The callback should accept one argument representing the boolean state of the checkbox and should only create side effects (the return value will be discarded)",
"widget-make-entry": "(widget-make-entry [placeholder-text: string] [[wrap-text: bool]] [[validation-callback: lambda]]) => gui-widget\n\nCreates an entry widget with the given placeholder value. For accessibility purposes it is always advised to also have a label widget describing this widget. If a validation lambda is given it should take a string value as its argument and should validate based on that string. If it successfully validates `#t` or any non-string value should be returned, otherwise a string explaining the error should be returned",
"widget-make-hyperlink": "(widget-make-hyperlink [text: string] [url: string]) => gui-widget\n\nCreates a hyperlink widget with the given text linking to the given URL. If the URL cannot be parsed as a valid URL an exception will be returned",
"widget-make-label": "(widget-make-label [text: string] [[alignment: number]] [[wrap-text: bool]]) => gui-widget\n\nCreates a label widget with the given text. If alignment is given it should be one of:\n\n\t-1: Align Leading\n\t 0: Align Center\n\t 1: Align Trailing",
"widget-make-markdown": "(widget-make-markdown [markdown-text: string] [[wrap-text: bool]]) => gui-widget\n\nCreates a markdown text block. The markdown-text string should be markdown, which will be parsed and rendered. wrap-text defaults to #f. If set to #t the text will be wrapped at word boundaries using the minimum size of the container",
"widget-make-multiline": "(widget-make-multiline [placeholder-text: string] [[wrap-text: bool]] [[validation-callback: lambda]]) => gui-widget\n\nCreates a multiline text entry widget with the given placeholder value. For accessibility purposes it is always advised to also have a label widget describing this widget. If a validation lambda is given it should take a string value as its argument and should validate based on that string. If it successfully validates `#t` or any non-string value should be returned, otherwise a string explaining the error should be returned",
"widget-make-password": "(widget-make-password [placeholder-text: string] [[wrap-text: bool]] [[validation-callback: lambda]]) => gui-widget\n\nCreates an password widget with the given placeholder value. For accessibility purposes it is always advised to also have a label widget describing this widget. If a validation lambda is given it should take a string value as its argument and should validate based on that string. If it successfully validates `#t` or any non-string value should be returned, otherwise a string explaining the error should be returned",
"widget-make-select": "(widget-make-select [options: list] [callback: lambda] [[alignment: number]]) => gui-widget\n\nCreates a select widget with the given options. Any non-string options will be converted to string. The callback should accept a string argument representing the selected element and should only create side effects (the return value will be discarded). If alignment is given it should be one of:\n\n\t-1: Align Leading\n\t 0: Align Center\n\t 1: Align Trailing",
"widget-make-separator": "(widget-make-separator) => gui-widget\n\nReturns a separator widget, which takes the form of a separator line that will go horizontal or vertical automatically depending on the container/layout",
"widget-make-spacer": "(widget-make-spacer) => gui-widget\n\nReturns a spacer widget which will fill up the available space in the container, pushing other widgets away from it in a direction decided based on the container/layou",
"container": "(container [layout: string] [contents: gui-widget|container...])\n\n`container` is the basic layout unit of the slope gui system. It can hold any number of other widgets or containers. The available layout strings are:\n\n\tnone - No layout\n\n\thbox - arranges items in a horizontal row. Every element will have the same height (the height of the tallest item in the container) and objects will be left-aligned at their minimum width\n\n\tvbox - arranges items in a vertical column. Every element will have the same width (the width of the widest item in the container) and objects will be top-aligned at their minimum height\n\n\tform - arranges items in pairs where the first column is at minimum width. This is normally useful for labelling elements in a form, where the label is in the first column and the item it describes is in the second. You should always add an even number of elements to a form layout\n\n\tcenter - positions all container elements in the center of the container. Every object will be set to its minimum size\n\n\tmax - positions all container elements to fill the available space. The objects will all be full-sized and drawn in the order they were added to the container (last-most is on top)\n\n\tpadded - positions all container elements to fill the available space but with a small padding around the outside. The size of the padding is theme specific. The objects will all be drawn in the order they were added to the container (last-most is on top)",
"container-size": "(container-size [gui-container]) => list\n\nReturns a two item list containing the given gui-container's width and height (in that order)",
"container-add-to": "(container-add-to [parent: gui-container] [child: gui-widget|gui-container]) => #t\n\nAdds the given child widget/container to the given parent container",
"dialog-open-file": "",
"dialog-save-file": "",
"dialog-info": "",
"dialog-error": "",
"widget-set-text": "(widget-set-text [gui-widget] [string]) => string\n\nSets the text of the given widget to the given string and returns the string",
"widget-resize": "(widget-resize [gui-widget] [width: number] [height: number]) => gui-widget\n\nIn general the size of widgets is defined by the container/layout. However, in cases where it is not, `widget-resize` can be used. If used in a situation where it cannot be used, there will be no effect. Returns the widget with the new size",
"widget-show": "(widget-show [gui-widget]) => #t\n\nShows the given gui-widget. The widget will only become visible if it is in a visible grouping (window, container, layout, etc). Calling on an already visible widget will have no effect",
"widget-size": "(widget-size [gui-widget]) => list\n\nReturns the given widget's current width and height, in that order, in a two item list",
"window-allow-resize": "(window-allow-resize [app: gui-root] [window-name: string] [bool]) => #t\n\nSets whether or not to allow the user to resize the given window",
"window-center": "(window-center [app: gui-root] [window-name: string]) => #t\n\nCenters the given window on the screen",
"window-close": "(window-close [app: gui-root] [window-name: string]) => #t\n\nCloses the given window. When called on an already closed window the behavior is undefined",
"window-hide": "(window-hide [app: gui-root] [window-name: string]) => #t\n\nHides the given window. There is no effect when called on an already hidden window",
"window-resize": "(window-resize [app: gui-root] [window-name: string] [width: number] [height: number]) => #t\n\nResizes the given app's given window to the width and height that were given, if possible. This is a finicky function in the underlying library and seems to behave unexpectedly or not at all",
"window-set-content": "(window-set-content [app: gui-root] [window-name: string] [content: gui-widget|gui-container]) => #t\n\nSets the content for the given window. This is usually a `container`, but could be a `widget`. #t or an exception will be returned",
"window-set-fullscreen": "(window-set-fullscreen [app: gui-root] [window-name: string] [set-to-full-screen: bool]) => #t\n\nSets the given window to full screen if #t is given and removes it from full screen if #f is given",
"window-set-title": "(window-set-title [app: gui-root] [window-name: string] [title: string]) => #t\n\nSets the title of the window to the given title string. If a non-string value is passed as title a stringified version of the value will be used",
"window-show": "(window-show [app: gui-root] [window-name: string]) => #t\n\nShows the given window. There is no effect when called on an already visible window",
"window-show-and-run": "(window-show-and-run [app: gui-root] [window-name: string]) => #t\n\nRuns the gui with the given window visible. This is the main procedure for starting the gui and will block once evaluated until the window is closed",
}

View File

@ -273,6 +273,14 @@ func StringSliceToExpressionSlice(s []string) expression {
return e
}
func ExpressionSliceToStringSlice(e []expression) []string {
s := make([]string, len(e))
for i := range s {
s[i] = String(e[i], false)
}
return s
}
func loadFiles(files []expression) {
for _, v := range files {
err := RunFile(ExpandedAbsFilepath(v.(string)), true)