Interzona

nodgui FAQ

Table of Contents

FAQ

Where is the documentation?

Nodgui shows a weak heritage from LTK, at this point the documentation for the original library can be confusing for the newcomer; i suggest, instead, these resources:

The rest of the documentation is this page and the rare docstrings at the moment.

If you want to help please open a pull request.

Where can I found documentation about a widget?

It is actually very simple: let's suppose you want to use a spinbox widget in your program and you have no idea how to do, the idea to solve this problem is like:

  1. open the file src/spinbox.lisp an look at the top of this file:

    (defargs spinbox ()
    cursor
    state
    style
    takefocus
    validate
    validatecommand
    xscrollcommand
    command
    format
    from
    increment
    to
    values
    wrap)
    

    the symbols listed are all the options for the spinbox TK command (in TCL language everything is a command) or the configuration variable that you can pass as initarg for (make instance 'spinbox ...) and, sometimes, changed after object instancing via configure (see the general documentation)

  2. for the meaning of this symbols refers to the original TK documentation

    As a general rule choose the link to the command with its name prefixed with "ttk::" (if exists).

    In our example point to:

    https://www.tcl.tk/man/tcl8.6/TkCmd/ttk_spinbox.htm

    and not

    https://www.tcl.tk/man/tcl8.6/TkCmd/spinbox.htm

    You can easily understand what all the options above are for.

Where can i find documentation for non standard widget?

How can I access the root window?

The root window is returned by the function: nodgui:root-toplevel.

How can i set the title and the class of the root window?

with-nodgui accepts keywords :title and :class to change the name and the class of the window respectively.

I have a bunch of widgets placed in a grid and I want those to scale themselves when the window is resized, there is a way to accomplish this?

Sure! Use grid-(column|row)-configure.

(grid-columnconfigure (root-toplevel) :all :weight 1)
(grid-rowconfigure    (root-toplevel) :all :weight 1)

You can replace :all with a row or column indices to apply this behaviour only to a subset of the columns or rows.

I have two listbox placed on a window, when I select an entry of one of them the selected item in the others is automatically deselected, i want to keep all the selection: how can I do that?

Use nodgui:listbox-export-selection

(nodgui:with-nodgui ()
  (let* ((listbox-1 (make-instance 'nodgui:listbox))
         (listbox-2 (make-instance 'nodgui:listbox))
         (entry     (make-instance 'nodgui:entry)))
    (nodgui:grid listbox-1 0 0)
    (nodgui:grid listbox-2 0 1)
    (nodgui:grid entry     1 0 :columnspan 2 :pady 2 :sticky :ew)
    (setf (nodgui:text entry) "baz")
    ;; note the call to listbox-export-selection for each listbox
    (nodgui:listbox-export-selection listbox-1 nil)
    (nodgui:listbox-export-selection listbox-2 nil)
    (nodgui:listbox-insert listbox-1 0 "foo")
    (nodgui:listbox-insert listbox-2 0 "bar")))

If you try to run the same code without the two nodgui:listbox-export-selection calls the selected text (even on the entry) will remove all the other selections.

How can I specify layout for when creating a widget via initialize-instance?

The method initialize-instance specialized on widget, a common ancestor of many GUI elements available (button, frame, etc) accepts the keyword argument: grid, pack and place. Pass a list of arguments, compatible with the corresponding layout function to this keyword argument to configure the layout for the widget you are creating, for example:

(make-instance 'nodgui:frame :grid '(0 ; first row
                                     1 ; second column
                                     :sticky :news
                                     :padx   10))

see for reference: https://codeberg.org/cage/nodgui/issues/9#issuecomment-1549116

How to quit a nodgui program?

Use exit-nodgui

(with-nodgui ()
  (let ((button (make-instance 'button :text "quit")))
    (setf (command button)
          (lambda ()
            (format t "quitting~%")
            (exit-nodgui)))
    (pack button)))

What are the differences between nodgui and LTK?

The two libraries diverged now, the API is no more compatible with LTK.

The major differences are:

  1. A reader macro for events i.e. #$<Alt-q>$ instead of "<Alt-q>" (a string), the macro will parse and check for trivial errors in the event definition syntax at compile time.

    (named-readtables:in-readtable nodgui.syntax:nodgui-syntax) ; do not forget that!
    
    [...]
    
    (bind (root-toplevel) #$<Alt-q>$ (lambda (event) ...
    

    Please note that a string is still accepted as event specifier.

  2. A DSL for TCL code that allow to mix TCL code and lisp expression, check for example the following code to create a bitmap:

    (named-readtables:in-readtable nodgui.syntax:nodgui-syntax) ; do not forget that!
    
    [...]
    
    (tclize `([list
                ,(loop for r from 0 below h collect
                    (tclize `([list ,(loop
    ...
    

    The tclize macro will transforms the backquoted forms in TCL code, the unquoted forms will be evaluated before the translation occurs;

  3. The function postscript returns a postscript file as string instead of writing a file on disk;
  4. Support for images in GIF, PNG, TGA, JPEG and raw RGB format, limited manipulation for the latest four formats is provided (scaling and rotation);
  5. Compatible only with TK 8.6;
  6. A general refactoring;
  7. Integrated with cl-colors library (can use X11 color names or RGB struct, see Colors Name);
  8. Many more widgets, some not even available with TK, included canvas with hardware accelerated rendering;
  9. Some bugs fixed (and more added of course :-) ).

Where can i find more code examples?

Check the file src/demo-tests.lisp

Can I contribute to this project?

Yes, of course! Please open an issue or a pull request on the web repository, if you do not feel comfortable with coding, documentation improvements are very welcome too! :)

Also i would appreciate testing if the library works on different environment than mine (Debian GNU/Linux with SBCL).

Why is tcclib a dependency?

I wrapped a few simple functions that can be used as a general utility.

match-path, comes for free as it is a standard TCL command

(defun match-path (text &key (root-directory nil) (join nil) (path nil) (type nil)))
"Returns a list of filesystem paths that match template in `text' (see: glob(7) for template's syntax) starting from `start-directory' (default: the current directory)"
(defun csv-stream (stream &key (separator ",") (quote-char "\""))
"Needs tcllib. Returns a closure that, when invoked with no argument, returns a list corresponding to a row of the table represented by the CSV data (or nil after the last row has been parsed), the data are split using `separator' and each field cn be quoted using `quote-char'."
(defun make-zip-file (zip-filepath glob-paths)
  "Creates a zip file in `zip-filepaths' adding a list of paths contained in `glob-paths'.
Each element of `glob-paths' uses globs e.g '(\"*.zip\" \"foo.*\")"
(defun zip-file-p (zip-filepath)
  "Returns non nil if the file pointed from `zip-file-path` is a zip file: note that the file must exists and readable).
Each element of `glob-paths' uses globs e.g '(\"*.zip\" \"foo.*\")"
(defun zip-file-list-contents (zip-filepath)
"Returns a list of strings, each item of the list is a file contained in zipfile pointed by `zip-filepath'"
(defun unzip-file (zip-filepath destination-path)
"Decompress a zip file in `zip-filepaths' on `destination-path'."
(defun cpu-info ()
  "Returns an alist of CPU information field (on GNU/Linux) are:
- :memory
- :vendor
- :family
- :model
- :brand
- :steppin
- :speed
- :features
- :cpus"
(defun mac-addresses ()
"Returns a list of MAC addresses for this machines, the primary is listed first"
(defun ip-addresses ()
"Returns a list of IP addresses for this machines."
(defun convert-units (from to)
  "Convert quantity to differents measure units e.g.:

(convert-units \"1 mm\" \"meter\")

Please see:

 https://core.tcl-lang.org/tcllib/doc/trunk/embedded/md/tcllib/files/modules/units/units.md

For more documentation"
(defun reduce-unit (unit-string)
  "Reduce `unit-string' to their atomic components e.g.:

(reduce-units \"Joule\"); => \"1000.0 gram meter meter / second second\"

Please see:

 https://core.tcl-lang.org/tcllib/doc/trunk/embedded/md/tcllib/files/modules/units/units.md

For more documentation."
(defun new-unit (unit equivalent-to)
  " Create a nes unit equivalent to `equivalent-to' e.g.
  (with-nodgui ()
    (new-unit \"furlong\" \"220 yards\")
    (convert-units \"10 furlong\" \"yards\")) ; => 2200.0

Please see:

 https://core.tcl-lang.org/tcllib/doc/trunk/embedded/md/tcllib/files/modules/units/units.md

For more documentation."
(defun file-writable-p (path)
"Return true if file in `path' is writable."
(defun replace-in-file (path start size data)
"Remove `size' octets from file pointed by `path' starting at position: `start', replacing with `data', return `t' on success."

Menu on Mac OS X shows a element, named wish, that I am not able to remove! Can I Fix this issue?

Menu on Mac OS X are a bit tricky but, fortunately, an user found a way to get an acceptable menu on this platform too, please see: this message.


This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Italy License.

Distribuited software and source code published are licensed under the GNU General Public License version 3.0 or later if not specified otherwise.
🢠 fediring website 🢡
random fediring member
Mastodon