pure go, cross-platform, MIT-licensed ui toolkit for developers

GoDoc

duit - developer ui toolkit

WARNING: this library is work in progress. backwards incompatible changes will be made.

details

duit is a pure go (*), cross platform, MIT-licensed ui toolkit for developers. the api is small and uncomplicated.

duit works on the bsd's, linux and macos. it should be easy to get running on plan 9. for now, use the windows subsystem for linux on windows.

(*) duit currently needs a helper tool called devdraw, from plan9port (aka plan 9 from user space). plan9port is available for most unix systems, with devdraw in an x11 and native macos variant.

screenshots

duit screenshot

you should just try duit. using it and interacting with it gives a more complete impression.

instructions

setting this up currently requires some effort:

  • install plan9port, see https://9fans.github.io/plan9port/ (use their install instructions)
  • install a nice font. i use & recommend lato for a modern look. duit will automatically pick it up through $font (through plan9port's fontsrv), e.g.: export font=/mnt/font/Lato-Regular/15a/font

you should now be able to run the code in examples/

devdraw is not yet available as a native binary for windows. for now, use the windows subsystem for linux (ubuntu) on windows along with Xming. see https://github.com/elrzn/acme-wsl for instructions.

created with duit

see https://github.com/mjl- for applications. applications created with duit by other developers:

  • be the first to add your application here! (:

more

Owner
Mechiel Lukkien
freelance software engineer
Mechiel Lukkien
Comments
  • Extending

    Extending

    This is awesome. The tab for mouse focus is a great way to solve a tough ux thing.

    I am going to try to build a little bit with this.

    It's using opengl under the hood or SDL ? I ask because I am trying to imagine how tough the Windows code will be :)

    Anyway great stuff !!

  • build failing on OSX

    build failing on OSX

    Its a bit confusing what with the repathing. Cant find it expects "devdraw".. .. Is it in the 9fans.net/go/draw gopath ?

    make build
    cd /Users/apple/workspace/go/src/github.com/mjl-/duit/examples/basic/ && go build main.go && ./main
    2018/04/19 10:04:54 new duit: drawfcall.New: exec: "devdraw": executable file not found in $PATH
    make: *** [build] Error 1
    
    

    My Make file:

    # Duit is a Desktop Gui sysem for golang.
    
    LIBPATH=github.com/mjl-/duit
    LIBGOPATH=$(GOPATH)/src/$(LIBPATH)
    
    PLAN9_LIBPATH=github.com/9fans/plan9
    PLAN9_LIBGOPATH=$(GOPATH)/src/$(PLAN9_LIBPATH)
    
    PLAN9A_LIBPATH=9fans.net/go/draw
    PLAN9A_LIBGOPATH=$(GOPATH)/src/$(PLAN9A_LIBPATH)
    
    
    
    print:
    	@echo LIBPATH $(LIBPATH)
    	@echo LIBGOPATH $(LIBGOPATH)
    
    	@echo PLAN9_LIBPATH $(PLAN9_LIBPATH)
    	@echo PLAN9_LIBGOPATH $(PLAN9_LIBGOPATH)
    
    	# check plan9 path is correct
    	stat $(PLAN9A_LIBGOPATH)
    
    dep:
    	# duit
    	go get -u -d $(LIBPATH)
    	cd $(LIBGOPATH) && dep ensure
    
    	# plan9
    	mkdir -p  $(PLAN9_LIBGOPATH) 
    	cd $(PLAN9_LIBGOPATH)/../ && rm -rf plan9 && git clone https://github.com/9fans/plan9port plan9
    
    	
    dep-clean:
    	rm -rf $(LIBGOPATH)
    	rm -rf $(PLAN9_LIBGOPATH)
    
    build-all:
    
    	cd $(LIBGOPATH) && make
    
    build:
    	cd $(LIBGOPATH)/examples/basic/ && go build main.go && ./main
    	
    
    
    
    
    
    
  • invalid version: unknown revision

    invalid version: unknown revision

    9fans.net/[email protected]: invalid version: unknown revision 000000000000

    liangzi@xuan 115 14:19 >./INSTALL 
    + Mailing list: https://groups.google.com/group/plan9port-dev
    + Issue tracker: https://github.com/9fans/plan9port/issues/
    + Submitting changes: https://github.com/9fans/plan9port/pulls
     
    * Resetting /config
    * Compiler version:
            gcc version 7.5.0 (SUSE Linux) 
    * Building mk...
    * Building everything (be patient)...
    * Installing everything in /home/xuan/src/plan9/plan9port-master/bin...        
    * Cleaning up...                                                            
    * Renaming hard-coded /usr/local/plan9 paths...                                
    * Building web manual...
    * Done.                                               
    
    * Add these to your profile environment.
            PLAN9=/home/xuan/src/plan9/plan9port-master export PLAN9
            PATH=$PATH:$PLAN9/bin export PATH
    
    liangzi@xuan 74 14:27 >PLAN9=/home/xuan/src/plan9/plan9port-master 
    ~/nfs_share/golang/duit
    liangzi@xuan 75 14:28 >export PLAN9
    ~/nfs_share/golang/duit
    liangzi@xuan 76 14:28 >PATH=$PATH:$PLAN9/bin export PATH
    
    
    liangzi@xuan 80 14:31 >vim basic.go
    ~/nfs_share/golang/duit
    liangzi@xuan 81 14:32 >go run basic.go 
    go: finding module for package github.com/mjl-/duit
    go: found github.com/mjl-/duit in github.com/mjl-/duit v0.0.0-20200330125617-580cb0b2843f
    go: github.com/mjl-/[email protected] requires
            9fans.net/[email protected]: invalid version: unknown revision 000000000000
    
    
    
  • AppDataDir is wrong for Linux/unix

    AppDataDir is wrong for Linux/unix

    In Linux, and unix in general, it is considered quite rude to create a file or directory in $HOME which does not begin with a dot.

    Hence you should use $HOME/.config instead of $HOME/lib for the AppDataDir. This would be consistent with Debian policy, the XDG Base Directory Specification, etc...

  • edit: add Size() method returning total size of Edit buffer

    edit: add Size() method returning total size of Edit buffer

    Sometimes it's helpful when moving the cursor to know where the end of the buffer is. I think you could use len(edit.Text()) but that looks expensive. Internally, Edit uses ui.text.Size() so I am exposing that through a Size() method.

  • llvm-goc: /home/oceanfish81/workarea/llvm-project/llvm/tools/gollvm/gofrontend/go/names.cc:595: std::string Type::mangled_name(Gogo *) const: assertion 'c < '0' || c > '9'' failed.

    llvm-goc: /home/oceanfish81/workarea/llvm-project/llvm/tools/gollvm/gofrontend/go/names.cc:595: std::string Type::mangled_name(Gogo *) const: assertion 'c < '0' || c > '9'' failed.

    Hi. I wasn't able to build your project, if using gollvm compiler.

    ~/golang_projects/duit$ go build -i -v -x WORK=/tmp/go-build288395935

    get https://proxy.golang.org/github.com/mjl-/go/@v/v0.0.0-20180429123528-fafada5f286e.info

    get https://proxy.golang.org/github.com/mjl-/go/@v/v0.0.0-20180429123528-fafada5f286e.info: 200 OK (0.832s)

    9fans.net/go/draw/drawfcall mkdir -p $WORK/b003/ cd $WORK /home/oceanfish81/gollvm_dist/bin/llvm-goc -fgo-importcfg=/dev/null -c -x c - -o /dev/null || true cd /home/oceanfish81/go/pkg/mod/github.com/mjl-/[email protected]/draw/drawfcall /home/oceanfish81/gollvm_dist/bin/llvm-goc -c -O2 -g -m64 -fdebug-prefix-map=$WORK=/tmp/go-build -gno-record-gcc-switches -fgo-pkgpath=9fans.net/go/draw/drawfcall -o $WORK/b003/go.o -I $WORK/b003/importcfgroot ./bit.go ./msg.go ./mux.go

    9fans.net/go/draw/drawfcall

    llvm-goc: /home/oceanfish81/workarea/llvm-project/llvm/tools/gollvm/gofrontend/go/names.cc:595: std::string Type::mangled_name(Gogo ) const: assertion 'c < '0' || c > '9'' failed. #0 0x0000000000d765f3 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0xd765f3) #1 0x0000000000d7468c llvm::sys::RunSignalHandlers() (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0xd7468c) #2 0x0000000000d76a85 SignalHandler(int) (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0xd76a85) #3 0x00007f73143713c0 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x153c0) #4 0x00007f7313ea218b raise /build/glibc-ZN95T4/glibc-2.31/signal/../sysdeps/unix/sysv/linux/raise.c:51:1 #5 0x00007f7313e81859 abort /build/glibc-ZN95T4/glibc-2.31/stdlib/abort.c:81:7 #6 0x000000000051b662 (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0x51b662) #7 0x00000000004b1397 Type::mangled_name(Gogo) const (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0x4b1397) #8 0x00000000004b3ec8 Gogo::type_descriptor_name(Type const*, Named_type*) (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0x4b3ec8) #9 0x0000000000548101 Sort_types::operator()(Type const*, Type const*) const (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0x548101) #10 0x0000000000547fa9 void std::__1::__sort<Sort_types&, Type const**>(Type const**, Type const**, Sort_types&) (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0x547fa9) #11 0x0000000000542a1a Export::assign_type_indices(std::__1::vector<Named_object*, std::__1::allocator<Named_object*> > const&) (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0x542a1a) #12 0x0000000000542261 Export::export_globals(std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&, std::__1::map<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, Package*, std::__1::less<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const, Package*> > > const&, std::__1::map<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator >, Package*, std::__1::less<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const, Package*> > > const&, std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator > const&, Import_init_set const&, Bindings const*, std::__1::unordered_set<Named_object*, std::__1::hash<Named_object*>, std::__1::equal_to<Named_object*>, std::__1::allocator<Named_object*> >) (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0x542261) #13 0x000000000049253d Gogo::do_exports() (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0x49253d) #14 0x0000000000479b28 go_parse_input_files(char const**, unsigned int, bool, bool) (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0x479b28) #15 0x000000000046e933 gollvm::driver::CompileGoImpl::invokeFrontEnd() (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0x46e933) #16 0x000000000047118b gollvm::driver::CompileGo::performAction(gollvm::driver::Compilation&, gollvm::driver::Action const&, llvm::SmallVector<gollvm::driver::Artifact, 3u> const&, gollvm::driver::Artifact const&) (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0x47118b) #17 0x0000000000467b12 gollvm::driver::Driver::processAction(gollvm::driver::Action*, gollvm::driver::Compilation&, bool) (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0x467b12) #18 0x0000000000467c22 gollvm::driver::Driver::processActions(gollvm::driver::Compilation&) (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0x467c22) #19 0x0000000000460f07 main (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0x460f07) #20 0x00007f7313e830b3 __libc_start_main /build/glibc-ZN95T4/glibc-2.31/csu/../csu/libc-start.c:342:3 #21 0x000000000045fb2e _start (/home/oceanfish81/gollvm_dist/bin/llvm-goc+0x45fb2e) PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash backtrace. Stack dump: 0. Program arguments: /home/oceanfish81/gollvm_dist/bin/llvm-goc -c -O2 -g -m64 -fdebug-prefix-map=/tmp/go-build288395935=/tmp/go-build -gno-record-gcc-switches -fgo-pkgpath=9fans.net/go/draw/drawfcall -o $WORK/b003/go.o -I $WORK/b003/importcfgroot ../../go/pkg/mod/github.com/mjl-/[email protected]/draw/drawfcall/bit.go ../../go/pkg/mod/github.com/mjl-/[email protected]/draw/drawfcall/msg.go ../../go/pkg/mod/github.com/mjl-/[email protected]/draw/drawfcall/mux.go

    Reported that already. llvm-goc could be installed by

    $sudo cp -R * /usr/

    after extracting this build.

    CC @thanm @cherrymui

  • new dui: drawfcall.New: exec:

    new dui: drawfcall.New: exec: "devdraw": executable file not found in $PATH

    hellojukay@local test $ go env
    GO111MODULE="on"
    GOARCH="amd64"
    GOBIN=""
    GOCACHE="/home/hellojukay/.cache/go-build"
    GOENV="/home/hellojukay/.config/go/env"
    GOEXE=""
    GOFLAGS=""
    GOHOSTARCH="amd64"
    GOHOSTOS="linux"
    
    package main
    
    import (
    	"flag"
    	"io"
    	"log"
    	"os"
    
    	"github.com/mjl-/duit"
    )
    
    func check(err error, msg string) {
    	if err != nil {
    		log.Fatalf("%s: %s\n", msg, err)
    	}
    }
    
    func main() {
    	log.SetFlags(0)
    	flag.Usage = func() {
    		log.Println("usage: duitedit file")
    		flag.PrintDefaults()
    	}
    	flag.Parse()
    	args := flag.Args()
    	if len(args) != 1 {
    		flag.Usage()
    		os.Exit(2)
    	}
    
    	f, err := os.Open(args[0])
    	check(err, "open")
    
    	dui, err := duit.NewDUI("ex/edit", nil)
    	check(err, "new dui")
    
    	edit, err := duit.NewEdit(f)
    	check(err, "new edit")
    
    	print := &duit.Button{
    		Text: "print",
    		Click: func() (e duit.Event) {
    			rd := edit.Reader()
    			n, err := io.Copy(os.Stdout, rd)
    			if err != nil {
    				log.Printf("error copying text: %s\n", err)
    			}
    			log.Printf("copied %d bytes\n", n)
    			return
    		},
    	}
    
    	dui.Top.UI = &duit.Box{Kids: duit.NewKids(print, edit)}
    	dui.Render()
    
    	for {
    		select {
    		case e := <-dui.Inputs:
    			dui.Input(e)
    
    		case err, ok := <-dui.Error:
    			if !ok {
    				return
    			}
    			log.Printf("duit: %s\n", err)
    		}
    	}
    }
    
    hellojukay@local test $ go build main.go 
    hellojukay@local test $ ./main 
    usage: duitedit file
    hellojukay@local test $ ./main main.go 
    new dui: drawfcall.New: exec: "devdraw": executable file not found in $PATH
    

    pure golang ???????

  • duit: add mouse chording cut/paste for Edit and Field

    duit: add mouse chording cut/paste for Edit and Field

    This is a patch that adds chorded cut + paste to the Edit and Field UIs. It's not the cleanest, but it's a fairly minimal set of changes that I think shouldn't disturb existing features.

  • prevent de-selection of items in single-select lists

    prevent de-selection of items in single-select lists

    I'm not sure if this behavior is intentional, so forgive me if it is, but clicking on an already-selected item in the List ui (for a non-multiple-select List) causes it to de-select, which doesn't feel normal to me. This change causes already-selected items to stay selected when clicked.

  • Edit: Search selected text with Button3

    Edit: Search selected text with Button3

    It would be nice to search the currently selected text in Edit UIs with Button3, like in acme. I implemented this in ktye/duit@b5e969b This udates the cursor to the match and scrolls it into view. What I couldn't work out is how to warp the mouse to the new selection.

  • how to reference widgets

    how to reference widgets

    As I understand, all widgets that should be referenced in another one, e.g. to change the text of a label, have to be declared upfront:

    label := &duit.Label{Text: "status: not logged in yet"}
    

    further down, the UI is declared in a nested structure:

    dui.Top.UI = &duit.Box{
     ...
    Kids: duit.NewKids(
    			status,
    			&duit.Grid{...}
    ...
    

    This is simple, but has the drawback, that you have to declare the widgets in a chaotic order. lxn/walk uses a simple trick here in it's declarative package: You can assign each widget to a pointer, and use this later as a reference.

    If we implement something like that in duit, it would look like:

      var label **duit.Label
      duit.Top.UI = &duit.Box{
       ...
       Kids: duit.NewKids(
           &duit.Label{ // we declare the widget in it's usual place
                Target: &label, // This get's evaluated later.
          },
          & duit.Button{
               // here we can use the label pointer in the callback.
         },
    }
    

    The needed change would be, that each UI element, needs a Target as a pointer to itself. The variables holding the pointer, have to be assigned when building the Top.UI. I don't know if we need to add another function for this, or use dui.Render. Each widget would check it's Target field and if it is not nil, set the pointer to itself.

    What do you think? Is it worth it?

UIKit - A declarative, reactive GUI toolkit for build cross platform apps with web technology with single codebase
 UIKit - A declarative, reactive GUI toolkit for build cross platform apps with web technology with single codebase

UIKit - A declarative, reactive GUI toolkit for build cross platform apps with web technology with single codebase

Apr 18, 2022
Cross platform GUI in Go based on Material Design
Cross platform GUI in Go based on Material Design

About Fyne is an easy to use UI toolkit and app API written in Go. It is designed to build applications that run on desktop and mobile devices with a

Jan 3, 2023
An experimental Go cross platform UI library.

GXUI - A Go cross platform UI library. Notice: Unfortunately due to a shortage of hours in a day, GXUI is no longer maintained. If you're looking for

Jan 6, 2023
Build cross-platform modern desktop apps in Go + HTML5
Build cross-platform modern desktop apps in Go + HTML5

Lorca A very small library to build modern HTML5 desktop apps in Go. It uses Chrome browser as a UI layer. Unlike Electron it doesn't bundle Chrome in

Jan 6, 2023
Tiny cross-platform webview library for C/C++/Golang. Uses WebKit (Gtk/Cocoa) and Edge (Windows)

webview A tiny cross-platform webview library for C/C++/Golang to build modern cross-platform GUIs. Also, there are Rust bindings, Python bindings, Ni

Dec 28, 2022
Build cross platform GUI apps with GO and HTML/JS/CSS (powered by Electron)

Thanks to go-astilectron build cross platform GUI apps with GO and HTML/JS/CSS. It is the official GO bindings of astilectron and is powered by Electr

Jan 9, 2023
Build cross platform GUI apps with GO and HTML/JS/CSS (powered by nwjs)
Build cross platform GUI apps with GO and HTML/JS/CSS (powered by nwjs)

gowd Build cross platform GUI apps with GO and HTML/JS/CSS (powered by nwjs) How to use this library: Download and install nwjs Install this library g

Dec 11, 2022
RobotGo, Go Native cross-platform GUI automation @vcaesar

Robotgo Golang Desktop Automation. Control the mouse, keyboard, bitmap, read the screen, Window Handle and global event listener. RobotGo supports Mac

Jan 7, 2023
Cross-platform Go library to place an icon in the host operating system's taskbar.

trayhost Package trayhost is a cross-platform Go library to place an icon in the host operating system's taskbar. Platform Support macOS - Fully imple

Nov 6, 2022
Cross-platform GUI for go is never this easy and clean.
Cross-platform GUI for go is never this easy and clean.

gimu Strongly suggest NOT to use this project anymore, the auto-generated cgo wrapper of Nuklear has a random crash issue which is hard to fix (becaus

Jul 12, 2022
Go cross-platform library for displaying dialogs and input boxes

dlgs dlgs is a cross-platform library for displaying dialogs and input boxes. Installation go get -u github.com/gen2brain/dlgs Documentation Document

Dec 24, 2022
A cross-platform app-development module for Go.
A cross-platform app-development module for Go.

The cross-platform Go module for building apps (pronounced klo-va-seed). Usecases As a lightweight alternative to Electron Write your frontend and nat

Dec 1, 2022
Cross platform rapid GUI framework for golang based on Dear ImGui.
Cross platform rapid GUI framework for golang based on Dear ImGui.

giu Cross platform rapid GUI framework for golang based on Dear ImGui and the great golang binding imgui-go. Any contribution (features, widgets, tuto

Dec 28, 2022
Tiny cross-platform webview library for C/C++/Golang. Uses WebKit (Gtk/Cocoa) and Edge (Windows)

webview A tiny cross-platform webview library for C/C++/Golang to build modern cross-platform GUIs. Also, there are Rust bindings, Python bindings, Ni

Jan 1, 2023
Cross-Platform GUI Framework for Go

⚠️ I'm currently working on this project as part of my master's thesis at the Berlin University of Applied Sciences and Technology. It is under active

Oct 31, 2022
Cross-platform Go/Golang GUI library.

中文 | English GoVCL Cross-platform Golang GUI library, The core binding is liblcl, a common cross-platform GUI library created by Lazarus. GoVCL is a n

Dec 30, 2022
Pglet - Web UI framework for backend developers
Pglet - Web UI framework for backend developers

Pglet - Web UI framework for backend developers

Nov 15, 2022
A Windows GUI toolkit for the Go Programming Language
A Windows GUI toolkit for the Go Programming Language

About Walk Walk is a "Windows Application Library Kit" for the Go Programming Language. Its primarily useful for Desktop GUI development, but there is

Dec 30, 2022
Go Web UI Toolkit - Public Releases and Development
 Go Web UI Toolkit - Public Releases and Development

Welcome! Gowut (Go Web UI Toolkit) is a full-featured, easy to use, platform independent Web UI Toolkit written in pure Go, no platform dependent nati

Dec 5, 2022