Explorar el Código

d01 Обновление вендоринга

SVI hace 3 años
padre
commit
ae98ccd7df
Se han modificado 100 ficheros con 12468 adiciones y 1 borrados
  1. 23 0
      vendor/github.com/AllenDang/giu/.gitignore
  2. 100 0
      vendor/github.com/AllenDang/giu/.golangci.yml
  3. 17 0
      vendor/github.com/AllenDang/giu/.travis.yml
  4. 191 0
      vendor/github.com/AllenDang/giu/Alignment.go
  5. 156 0
      vendor/github.com/AllenDang/giu/Canvas.go
  6. 552 0
      vendor/github.com/AllenDang/giu/ClickableWidgets.go
  7. 220 0
      vendor/github.com/AllenDang/giu/CodeEditor.go
  8. 101 0
      vendor/github.com/AllenDang/giu/Context.go
  9. 12 0
      vendor/github.com/AllenDang/giu/Direction.go
  10. 173 0
      vendor/github.com/AllenDang/giu/EventHandler.go
  11. 86 0
      vendor/github.com/AllenDang/giu/Events.go
  12. 692 0
      vendor/github.com/AllenDang/giu/ExtraWidgets.go
  13. 503 0
      vendor/github.com/AllenDang/giu/Flags.go
  14. 304 0
      vendor/github.com/AllenDang/giu/FontAtlasProsessor.go
  15. 379 0
      vendor/github.com/AllenDang/giu/ImageWidgets.go
  16. 104 0
      vendor/github.com/AllenDang/giu/InputHandler.go
  17. 148 0
      vendor/github.com/AllenDang/giu/Keycode.go
  18. 1 1
      vendor/github.com/AllenDang/giu/LICENSE
  19. 50 0
      vendor/github.com/AllenDang/giu/Layout.go
  20. 47 0
      vendor/github.com/AllenDang/giu/ListClipper.go
  21. 131 0
      vendor/github.com/AllenDang/giu/Markdown.go
  22. 399 0
      vendor/github.com/AllenDang/giu/MasterWindow.go
  23. 60 0
      vendor/github.com/AllenDang/giu/MemoryEditor.go
  24. 179 0
      vendor/github.com/AllenDang/giu/Msgbox.go
  25. 467 0
      vendor/github.com/AllenDang/giu/Plot.go
  26. 105 0
      vendor/github.com/AllenDang/giu/Popups.go
  27. 107 0
      vendor/github.com/AllenDang/giu/ProgressIndicator.go
  28. 219 0
      vendor/github.com/AllenDang/giu/README.md
  29. 226 0
      vendor/github.com/AllenDang/giu/SliderWidgets.go
  30. 173 0
      vendor/github.com/AllenDang/giu/SplitLayout.go
  31. 48 0
      vendor/github.com/AllenDang/giu/StackWidget.go
  32. 479 0
      vendor/github.com/AllenDang/giu/Style.go
  33. 212 0
      vendor/github.com/AllenDang/giu/TableWidgets.go
  34. 456 0
      vendor/github.com/AllenDang/giu/TextWidgets.go
  35. 78 0
      vendor/github.com/AllenDang/giu/Texture.go
  36. 11 0
      vendor/github.com/AllenDang/giu/TextureFilters.go
  37. 216 0
      vendor/github.com/AllenDang/giu/Utils.go
  38. 745 0
      vendor/github.com/AllenDang/giu/Widgets.go
  39. 202 0
      vendor/github.com/AllenDang/giu/Window.go
  40. 7 0
      vendor/github.com/AllenDang/giu/build_windows.go
  41. 5 0
      vendor/github.com/AllenDang/giu/doc.go
  42. 21 0
      vendor/github.com/AllenDang/go-findfont/LICENSE
  43. 57 0
      vendor/github.com/AllenDang/go-findfont/README.md
  44. 110 0
      vendor/github.com/AllenDang/go-findfont/findfont.go
  45. 14 0
      vendor/github.com/AllenDang/go-findfont/fontdirs_darwin.go
  46. 36 0
      vendor/github.com/AllenDang/go-findfont/fontdirs_unix.go
  47. 18 0
      vendor/github.com/AllenDang/go-findfont/fontdirs_windows.go
  48. 7 0
      vendor/github.com/AllenDang/imgui-go/.gitignore
  49. BIN
      vendor/github.com/AllenDang/imgui-go/.go.mod.swp
  50. 33 0
      vendor/github.com/AllenDang/imgui-go/Assert.go
  51. 17 0
      vendor/github.com/AllenDang/imgui-go/BackendFlags.go
  52. 89 0
      vendor/github.com/AllenDang/imgui-go/CONTRIBUTING.md
  53. 43 0
      vendor/github.com/AllenDang/imgui-go/ColorEditFlags.go
  54. 41 0
      vendor/github.com/AllenDang/imgui-go/ColorPickerFlags.go
  55. 23 0
      vendor/github.com/AllenDang/imgui-go/ComboFlags.go
  56. 17 0
      vendor/github.com/AllenDang/imgui-go/Conditions.go
  57. 38 0
      vendor/github.com/AllenDang/imgui-go/ConfigFlags.go
  58. 68 0
      vendor/github.com/AllenDang/imgui-go/Context.go
  59. 61 0
      vendor/github.com/AllenDang/imgui-go/DragDrop.go
  60. 32 0
      vendor/github.com/AllenDang/imgui-go/DragDropWrapper.cpp
  61. 24 0
      vendor/github.com/AllenDang/imgui-go/DragDropWrapper.h
  62. 60 0
      vendor/github.com/AllenDang/imgui-go/DrawCommand.go
  63. 39 0
      vendor/github.com/AllenDang/imgui-go/DrawCommandWrapper.cpp
  64. 19 0
      vendor/github.com/AllenDang/imgui-go/DrawCommandWrapper.h
  65. 42 0
      vendor/github.com/AllenDang/imgui-go/DrawData.go
  66. 25 0
      vendor/github.com/AllenDang/imgui-go/DrawDataWrapper.cpp
  67. 16 0
      vendor/github.com/AllenDang/imgui-go/DrawDataWrapper.h
  68. 226 0
      vendor/github.com/AllenDang/imgui-go/DrawList.go
  69. 206 0
      vendor/github.com/AllenDang/imgui-go/DrawListWrapper.cpp
  70. 78 0
      vendor/github.com/AllenDang/imgui-go/DrawListWrapper.h
  71. 13 0
      vendor/github.com/AllenDang/imgui-go/FocusFlags.go
  72. 19 0
      vendor/github.com/AllenDang/imgui-go/Font.go
  73. 193 0
      vendor/github.com/AllenDang/imgui-go/FontAtlas.go
  74. 121 0
      vendor/github.com/AllenDang/imgui-go/FontAtlasWrapper.cpp
  75. 44 0
      vendor/github.com/AllenDang/imgui-go/FontAtlasWrapper.h
  76. 117 0
      vendor/github.com/AllenDang/imgui-go/FontConfig.go
  77. 80 0
      vendor/github.com/AllenDang/imgui-go/FontConfigWrapper.cpp
  78. 27 0
      vendor/github.com/AllenDang/imgui-go/FontConfigWrapper.h
  79. 43 0
      vendor/github.com/AllenDang/imgui-go/FontGlyphRangesBuilderWrapper.cpp
  80. 21 0
      vendor/github.com/AllenDang/imgui-go/FontGlyphRangesBuilderWrapper.h
  81. 43 0
      vendor/github.com/AllenDang/imgui-go/FontGlyphRnagesBuilder.go
  82. 8 0
      vendor/github.com/AllenDang/imgui-go/FontWrapper.cpp
  83. 14 0
      vendor/github.com/AllenDang/imgui-go/FontWrapper.h
  84. 15 0
      vendor/github.com/AllenDang/imgui-go/GlyphRanges.go
  85. 17 0
      vendor/github.com/AllenDang/imgui-go/HoveredFlags.go
  86. 250 0
      vendor/github.com/AllenDang/imgui-go/IO.go
  87. 218 0
      vendor/github.com/AllenDang/imgui-go/IOWrapper.cpp
  88. 52 0
      vendor/github.com/AllenDang/imgui-go/IOWrapper.h
  89. 273 0
      vendor/github.com/AllenDang/imgui-go/InputText.go
  90. 113 0
      vendor/github.com/AllenDang/imgui-go/InputTextCallbackDataWrapper.cpp
  91. 34 0
      vendor/github.com/AllenDang/imgui-go/InputTextCallbackDataWrapper.h
  92. 28 0
      vendor/github.com/AllenDang/imgui-go/Keys.go
  93. 21 0
      vendor/github.com/AllenDang/imgui-go/LICENSE.txt
  94. 38 0
      vendor/github.com/AllenDang/imgui-go/ListClipper.cpp
  95. 82 0
      vendor/github.com/AllenDang/imgui-go/ListClipper.go
  96. 21 0
      vendor/github.com/AllenDang/imgui-go/ListClipper.h
  97. 25 0
      vendor/github.com/AllenDang/imgui-go/MouseCursorFlags.go
  98. 522 0
      vendor/github.com/AllenDang/imgui-go/PlatformGlfw.go
  99. 84 0
      vendor/github.com/AllenDang/imgui-go/PlatformInterface.go
  100. 88 0
      vendor/github.com/AllenDang/imgui-go/README.md

+ 23 - 0
vendor/github.com/AllenDang/giu/.gitignore

@@ -0,0 +1,23 @@
+# Binaries for programs and plugins
+*.exe
+*.exe~
+*.dll
+*.so
+*.dylib
+
+# vim cache files
+*.swp
+
+# JetBrains idea configuration
+.idea
+
+# Test binary, built with `go test -c`
+*.test
+
+# Output of the go coverage tool, specifically when used with LiteIDE
+*.out
+
+# Dependency directories (remove the comment below to include it)
+vendor/
+
+/cmd/gmdeploy/gmdeploy

+ 100 - 0
vendor/github.com/AllenDang/giu/.golangci.yml

@@ -0,0 +1,100 @@
+---
+linters-settings:
+  dupl:
+    threshold: 100
+  funlen:
+    lines: 100
+    statements: 50
+  goconst:
+    min-len: 2
+    min-occurrences: 2
+  gocritic:
+    enabled-tags:
+      - diagnostic
+      - experimental
+      - opinionated
+      - performance
+      - style
+    disabled-checks:
+  gocyclo:
+    min-complexity: 15
+  goimports:
+    local-prefixes: github.com/AllenDang/giu
+  govet:
+    check-shadowing: true
+  # lll:
+  #   line-length: 140
+  maligned:
+    suggest-new: true
+  misspell:
+    locale: US
+
+linters:
+  disable-all: true
+  enable:
+    - asciicheck
+    - bodyclose
+    - deadcode
+    - depguard
+    - dogsled
+    - dupl
+    - errcheck
+    - errorlint
+    - exportloopref
+    - forcetypeassert
+    #- funlen
+    - gci
+    - godot
+    #- gochecknoglobals
+    #- gochecknoinits
+    - gocognit
+    - goconst
+    - gocritic
+    - gocyclo
+    - goerr113
+    - gofmt
+    - gofumpt
+    - goheader
+    - goimports
+    #- gomnd
+    - goprintffuncname
+    - gosec
+    - gosimple
+    - govet
+    - ifshort
+    - importas
+    - ineffassign
+    # - lll
+    - makezero
+    - misspell
+    - nakedret
+    - nilerr
+    - nolintlint
+    - prealloc
+    - predeclared
+    - promlinter
+      #- revive
+    - rowserrcheck
+    - staticcheck
+    - structcheck
+    - stylecheck
+    - typecheck
+    - unconvert
+    - unparam
+    - unused
+    - varcheck
+    - wastedassign
+    - whitespace
+    - wrapcheck
+    #- wsl
+
+run:
+  timeout: 5m
+  skip-dirs:
+    - .github
+    - build
+    - web
+
+issues:
+  max-same-issues: 0
+  exclude-use-default: false

+ 17 - 0
vendor/github.com/AllenDang/giu/.travis.yml

@@ -0,0 +1,17 @@
+sudo: false
+
+addons:
+  apt_packages:
+    - libgl1-mesa-dev
+    - xorg-dev
+
+language: go
+
+go:
+  - 1.13.x
+  - tip
+
+matrix:
+  allow_failures:
+    - go: tip
+  fast_finish: true 

+ 191 - 0
vendor/github.com/AllenDang/giu/Alignment.go

@@ -0,0 +1,191 @@
+package giu
+
+import (
+	"fmt"
+	"image"
+
+	"github.com/AllenDang/imgui-go"
+)
+
+// AlignmentType represents a bype of alignment to use with AlignSetter.
+type AlignmentType byte
+
+const (
+	// AlignLeft is here just for clearity.
+	// if set, no action is taken so don't use it.
+	AlignLeft AlignmentType = iota
+	// AlignCenter centers widget.
+	AlignCenter
+	// AlignRight aligns a widget to right side of window.
+	AlignRight
+)
+
+// AlignManually allows to apply alignment manually.
+// As long as AlignSetter is really EXPERIMENTAL feature
+// and may fail randomly, the following method is supposed to
+// always work, as long as you set it up correctly.
+// To use it just pass a single widget with its exact width.
+// be sure to apply widget's size by using "Size" method!
+// forceApplyWidth argument allows you to ask giu to force-set width
+// of `widget`
+// NOTE that forcing width doesn't work for each widget type! For example
+// Button won't work because its size is set by argument to imgui call
+// not PushWidth api.
+func AlignManually(alignmentType AlignmentType, widget Widget, widgetWidth float32, forceApplyWidth bool) Widget {
+	return Custom(func() {
+		spacingX, _ := GetItemSpacing()
+		availableW, _ := GetAvailableRegion()
+
+		var dummyX float32
+
+		switch alignmentType {
+		case AlignLeft:
+			widget.Build()
+			return
+		case AlignCenter:
+			dummyX = (availableW-widgetWidth)/2 - spacingX
+		case AlignRight:
+			dummyX = availableW - widgetWidth - spacingX
+		}
+
+		Dummy(dummyX, 0).Build()
+
+		if forceApplyWidth {
+			PushItemWidth(widgetWidth)
+			defer PopItemWidth()
+		}
+
+		imgui.SameLine()
+		widget.Build()
+	})
+}
+
+var _ Widget = &AlignmentSetter{}
+
+// AlignmentSetter allows to align to right / center a widget or widgets group.
+// NOTE: Because of AlignSetter uses experimental GetWidgetWidth,
+// it is experimental too.
+// usage: see examples/align
+//
+// list of known bugs:
+// - BUG: DatePickerWidget doesn't work properly
+// - BUG: there is some bug with SelectableWidget
+// - BUG: ComboWidget and ComboCustomWidgets doesn't work properly.
+type AlignmentSetter struct {
+	alignType AlignmentType
+	layout    Layout
+	id        string
+}
+
+// Align sets widgets alignment.
+func Align(at AlignmentType) *AlignmentSetter {
+	return &AlignmentSetter{
+		alignType: at,
+		id:        GenAutoID("alignSetter"),
+	}
+}
+
+// To sets a layout, alignment should be applied to.
+func (a *AlignmentSetter) To(widgets ...Widget) *AlignmentSetter {
+	a.layout = Layout(widgets)
+	return a
+}
+
+// ID allows to manually set AlignmentSetter ID
+// NOTE: there isn't any known reason to use this method, however
+// it is here for some random cases. YOU DON'T NEED TO USE IT
+// in normal conditions.
+func (a *AlignmentSetter) ID(id string) *AlignmentSetter {
+	a.id = id
+	return a
+}
+
+// Build implements Widget interface.
+func (a *AlignmentSetter) Build() {
+	if a.layout == nil {
+		return
+	}
+
+	a.layout.Range(func(item Widget) {
+		// if item is inil, just skip it
+		if item == nil {
+			return
+		}
+
+		switch item.(type) {
+		// ok, it doesn't make sense to align again :-)
+		case *AlignmentSetter:
+			item.Build()
+			return
+		// there is a bug with selectables and combos, so skip them for now
+		case *SelectableWidget, *ComboWidget, *ComboCustomWidget:
+			item.Build()
+			return
+		}
+
+		currentPos := GetCursorPos()
+		w := GetWidgetWidth(item)
+		availableW, _ := GetAvailableRegion()
+		// we need to increase available region by 2 * window padding (X),
+		// because GetCursorPos considers it
+		paddingW, _ := GetWindowPadding()
+		availableW += 2 * paddingW
+
+		// set cursor position to align the widget
+		switch a.alignType {
+		case AlignLeft:
+			SetCursorPos(currentPos)
+		case AlignCenter:
+			SetCursorPos(image.Pt(int(availableW/2-w/2), currentPos.Y))
+		case AlignRight:
+			SetCursorPos(image.Pt(int(availableW-w), currentPos.Y))
+		default:
+			panic(fmt.Sprintf("giu: (*AlignSetter).Build: unknown align type %d", a.alignType))
+		}
+
+		// build aligned widget
+		item.Build()
+	})
+}
+
+// GetWidgetWidth returns a width of widget
+// NOTE: THIS IS A BETA SOLUTION and may contain bugs
+// in most cases, you may want to use supported by imgui GetItemRectSize.
+// There is an upstream issue for this problem:
+// https://github.com/ocornut/imgui/issues/3714
+//
+// This function is just a workaround used in giu.
+//
+// NOTE: user-definied widgets, which contains more than one
+// giu widget will be processed incorrectly (only width of the last built
+// widget will be processed)
+//
+// here is a list of known bugs:
+// - BUG: user can interact with invisible widget (created by GetWidgetWidth)
+//   - https://github.com/AllenDang/giu/issues/341
+//   - https://github.com/ocornut/imgui/issues/4588
+//
+// if you find anything else, please report it on
+// https://github.com/AllenDang/giu Any contribution is appreciated!
+func GetWidgetWidth(w Widget) (result float32) {
+	imgui.PushID(GenAutoID("GetWIdgetWidthMeasurement"))
+	defer imgui.PopID()
+
+	// save cursor position before rendering
+	currentPos := GetCursorPos()
+
+	// render widget in `dry` mode
+	imgui.PushStyleVarFloat(imgui.StyleVarAlpha, 0)
+	w.Build()
+	imgui.PopStyleVar()
+
+	// save widget's width
+	// check cursor position
+	imgui.SameLine()
+	spacingW, _ := GetItemSpacing()
+	result = float32(GetCursorPos().X-currentPos.X) - spacingW
+
+	SetCursorPos(currentPos)
+
+	return result
+}

+ 156 - 0
vendor/github.com/AllenDang/giu/Canvas.go

@@ -0,0 +1,156 @@
+package giu
+
+import (
+	"image"
+	"image/color"
+
+	"github.com/AllenDang/imgui-go"
+)
+
+// Canvas represents imgui.DrawList
+// from imgui.h:
+//       A single draw command list (generally one per window,
+//       conceptually you may see this as a dynamic "mesh" builder)
+//
+// for more details and use cases see examples/canvas.
+type Canvas struct {
+	drawlist imgui.DrawList
+}
+
+// GetCanvas returns current draw list (for current window).
+// it will fail if called out of window's layout.
+func GetCanvas() *Canvas {
+	return &Canvas{
+		drawlist: imgui.GetWindowDrawList(),
+	}
+}
+
+// AddLine draws a line (from p1 to p2).
+func (c *Canvas) AddLine(p1, p2 image.Point, col color.Color, thickness float32) {
+	c.drawlist.AddLine(ToVec2(p1), ToVec2(p2), ToVec4Color(col), thickness)
+}
+
+// DrawFlags represents imgui.DrawFlags.
+type DrawFlags int
+
+// draw flags enum:.
+const (
+	DrawFlagsNone DrawFlags = 0
+	// PathStroke(), AddPolyline(): specify that shape should be closed (portant: this is always == 1 for legacy reason).
+	DrawFlagsClosed DrawFlags = 1 << 0
+	// AddRect(), AddRectFilled(), PathRect(): enable rounding top-left corner only (when rounding > 0.0f, we default to all corners).
+	// Was 0x01.
+	DrawFlagsRoundCornersTopLeft DrawFlags = 1 << 4
+	// AddRect(), AddRectFilled(), PathRect(): enable rounding top-right corner only (when rounding > 0.0f, we default to all corners).
+	// Was 0x02.
+	DrawFlagsRoundCornersTopRight DrawFlags = 1 << 5
+	// AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-left corner only (when rounding > 0.0f, we default to all corners).
+	// Was 0x04.
+	DrawFlagsRoundCornersBottomLeft DrawFlags = 1 << 6
+	// AddRect(), AddRectFilled(), PathRect(): enable rounding bottom-right corner only (when rounding > 0.0f,
+	// we default to all corners). Wax 0x08.
+	DrawFlagsRoundCornersBottomRight DrawFlags = 1 << 7
+	// AddRect(), AddRectFilled(), PathRect(): disable rounding on all corners (when rounding > 0.0f). This is NOT zero, NOT an implicit flag!
+	DrawFlagsRoundCornersNone   DrawFlags = 1 << 8
+	DrawFlagsRoundCornersTop    DrawFlags = DrawFlagsRoundCornersTopLeft | DrawFlagsRoundCornersTopRight
+	DrawFlagsRoundCornersBottom DrawFlags = DrawFlagsRoundCornersBottomLeft | DrawFlagsRoundCornersBottomRight
+	DrawFlagsRoundCornersLeft   DrawFlags = DrawFlagsRoundCornersBottomLeft | DrawFlagsRoundCornersTopLeft
+	DrawFlagsRoundCornersRight  DrawFlags = DrawFlagsRoundCornersBottomRight | DrawFlagsRoundCornersTopRight
+	DrawFlagsRoundCornersAll    DrawFlags = DrawFlagsRoundCornersTopLeft | DrawFlagsRoundCornersTopRight |
+		DrawFlagsRoundCornersBottomLeft | DrawFlagsRoundCornersBottomRight
+	// Default to ALL corners if none of the RoundCornersXX flags are specified.
+	DrawFlagsRoundCornersDefault DrawFlags = DrawFlagsRoundCornersAll
+	DrawFlagsRoundCornersMask    DrawFlags = DrawFlagsRoundCornersAll | DrawFlagsRoundCornersNone
+)
+
+// AddRect draws a rectangle.
+func (c *Canvas) AddRect(pMin, pMax image.Point, col color.Color, rounding float32, roundingCorners DrawFlags, thickness float32) {
+	c.drawlist.AddRect(ToVec2(pMin), ToVec2(pMax), ToVec4Color(col), rounding, int(roundingCorners), thickness)
+}
+
+// AddRectFilled draws a rectangle filled with `col`.
+func (c *Canvas) AddRectFilled(pMin, pMax image.Point, col color.Color, rounding float32, roundingCorners DrawFlags) {
+	c.drawlist.AddRectFilled(ToVec2(pMin), ToVec2(pMax), ToVec4Color(col), rounding, int(roundingCorners))
+}
+
+// AddText draws text.
+func (c *Canvas) AddText(pos image.Point, col color.Color, text string) {
+	c.drawlist.AddText(ToVec2(pos), ToVec4Color(col), tStr(text))
+}
+
+// AddBezierCubic draws bezier cubic.
+func (c *Canvas) AddBezierCubic(pos0, cp0, cp1, pos1 image.Point, col color.Color, thickness float32, numSegments int) {
+	c.drawlist.AddBezierCubic(ToVec2(pos0), ToVec2(cp0), ToVec2(cp1), ToVec2(pos1), ToVec4Color(col), thickness, numSegments)
+}
+
+// AddTriangle draws a triangle.
+func (c *Canvas) AddTriangle(p1, p2, p3 image.Point, col color.Color, thickness float32) {
+	c.drawlist.AddTriangle(ToVec2(p1), ToVec2(p2), ToVec2(p3), ToVec4Color(col), thickness)
+}
+
+// AddTriangleFilled draws a filled triangle.
+func (c *Canvas) AddTriangleFilled(p1, p2, p3 image.Point, col color.Color) {
+	c.drawlist.AddTriangleFilled(ToVec2(p1), ToVec2(p2), ToVec2(p3), ToVec4Color(col))
+}
+
+// AddCircle draws a circle.
+func (c *Canvas) AddCircle(center image.Point, radius float32, col color.Color, segments int, thickness float32) {
+	c.drawlist.AddCircle(ToVec2(center), radius, ToVec4Color(col), segments, thickness)
+}
+
+// AddCircleFilled draws a filled circle.
+func (c *Canvas) AddCircleFilled(center image.Point, radius float32, col color.Color) {
+	c.drawlist.AddCircleFilled(ToVec2(center), radius, ToVec4Color(col))
+}
+
+// AddQuad draws a quad.
+func (c *Canvas) AddQuad(p1, p2, p3, p4 image.Point, col color.Color, thickness float32) {
+	c.drawlist.AddQuad(ToVec2(p1), ToVec2(p2), ToVec2(p3), ToVec2(p4), ToVec4Color(col), thickness)
+}
+
+// AddQuadFilled draws a filled quad.
+func (c *Canvas) AddQuadFilled(p1, p2, p3, p4 image.Point, col color.Color) {
+	c.drawlist.AddQuadFilled(ToVec2(p1), ToVec2(p2), ToVec2(p3), ToVec2(p4), ToVec4Color(col))
+}
+
+// Stateful path API, add points then finish with PathFillConvex() or PathStroke().
+
+func (c *Canvas) PathClear() {
+	c.drawlist.PathClear()
+}
+
+func (c *Canvas) PathLineTo(pos image.Point) {
+	c.drawlist.PathLineTo(ToVec2(pos))
+}
+
+func (c *Canvas) PathLineToMergeDuplicate(pos image.Point) {
+	c.drawlist.PathLineToMergeDuplicate(ToVec2(pos))
+}
+
+func (c *Canvas) PathFillConvex(col color.Color) {
+	c.drawlist.PathFillConvex(ToVec4Color(col))
+}
+
+func (c *Canvas) PathStroke(col color.Color, closed bool, thickness float32) {
+	c.drawlist.PathStroke(ToVec4Color(col), closed, thickness)
+}
+
+func (c *Canvas) PathArcTo(center image.Point, radius, min, max float32, numSegments int) {
+	c.drawlist.PathArcTo(ToVec2(center), radius, min, max, numSegments)
+}
+
+func (c *Canvas) PathArcToFast(center image.Point, radius float32, min12, max12 int) {
+	c.drawlist.PathArcToFast(ToVec2(center), radius, min12, max12)
+}
+
+func (c *Canvas) PathBezierCubicCurveTo(p1, p2, p3 image.Point, numSegments int) {
+	c.drawlist.PathBezierCubicCurveTo(ToVec2(p1), ToVec2(p2), ToVec2(p3), numSegments)
+}
+
+func (c *Canvas) AddImage(texture *Texture, pMin, pMax image.Point) {
+	c.drawlist.AddImage(texture.id, ToVec2(pMin), ToVec2(pMax))
+}
+
+func (c *Canvas) AddImageV(texture *Texture, pMin, pMax, uvMin, uvMax image.Point, col color.Color) {
+	c.drawlist.AddImageV(texture.id, ToVec2(pMin), ToVec2(pMax), ToVec2(uvMin), ToVec2(uvMax), ToVec4Color(col))
+}

+ 552 - 0
vendor/github.com/AllenDang/giu/ClickableWidgets.go

@@ -0,0 +1,552 @@
+package giu
+
+import (
+	"fmt"
+	"image"
+	"image/color"
+
+	"github.com/AllenDang/imgui-go"
+	"golang.org/x/image/colornames"
+)
+
+var _ Widget = &ButtonWidget{}
+
+// ButtonWidget represents a ImGui button widget.
+type ButtonWidget struct {
+	id       string
+	width    float32
+	height   float32
+	disabled bool
+	onClick  func()
+}
+
+// Button creates a new button widget.
+func Button(label string) *ButtonWidget {
+	return &ButtonWidget{
+		id:      GenAutoID(label),
+		width:   0,
+		height:  0,
+		onClick: nil,
+	}
+}
+
+// Buttonf creates button with formated label
+// NOTE: works like fmt.Sprintf (see `go doc fmt`).
+func Buttonf(format string, args ...any) *ButtonWidget {
+	return Button(fmt.Sprintf(format, args...))
+}
+
+// OnClick sets callback called when button is clicked
+// NOTE: to set double click, see EventHandler.go.
+func (b *ButtonWidget) OnClick(onClick func()) *ButtonWidget {
+	b.onClick = onClick
+	return b
+}
+
+// Disabled sets button's disabled state
+// NOTE: same effect as Style().SetDisabled.
+func (b *ButtonWidget) Disabled(d bool) *ButtonWidget {
+	b.disabled = d
+	return b
+}
+
+// Size sets button's size.
+func (b *ButtonWidget) Size(width, height float32) *ButtonWidget {
+	b.width, b.height = width, height
+	return b
+}
+
+// Build implements Widget interface.
+func (b *ButtonWidget) Build() {
+	if b.disabled {
+		imgui.BeginDisabled(true)
+		defer imgui.EndDisabled()
+	}
+
+	if imgui.ButtonV(tStr(b.id), imgui.Vec2{X: b.width, Y: b.height}) && b.onClick != nil {
+		b.onClick()
+	}
+}
+
+var _ Widget = &ArrowButtonWidget{}
+
+// ArrowButtonWidget represents a square button with an arrow.
+type ArrowButtonWidget struct {
+	id      string
+	dir     Direction
+	onClick func()
+}
+
+// ArrowButton creates ArrowButtonWidget.
+func ArrowButton(dir Direction) *ArrowButtonWidget {
+	return &ArrowButtonWidget{
+		id:      GenAutoID("ArrowButton"),
+		dir:     dir,
+		onClick: nil,
+	}
+}
+
+// OnClick adds callback called when button is clicked.
+func (b *ArrowButtonWidget) OnClick(onClick func()) *ArrowButtonWidget {
+	b.onClick = onClick
+	return b
+}
+
+// ID allows to manually set widget's id.
+func (b *ArrowButtonWidget) ID(id string) *ArrowButtonWidget {
+	b.id = id
+	return b
+}
+
+// Build implements Widget interface.
+func (b *ArrowButtonWidget) Build() {
+	if imgui.ArrowButton(b.id, uint8(b.dir)) && b.onClick != nil {
+		b.onClick()
+	}
+}
+
+var _ Widget = &SmallButtonWidget{}
+
+// SmallButtonWidget is like a button but without frame padding.
+type SmallButtonWidget struct {
+	id      string
+	onClick func()
+}
+
+// SmallButton constructs a new small button widget.
+func SmallButton(id string) *SmallButtonWidget {
+	return &SmallButtonWidget{
+		id:      GenAutoID(id),
+		onClick: nil,
+	}
+}
+
+// SmallButtonf allows to set formated label for small button.
+// It calls SmallButton(fmt.Sprintf(label, args...)).
+func SmallButtonf(format string, args ...any) *SmallButtonWidget {
+	return SmallButton(fmt.Sprintf(format, args...))
+}
+
+// OnClick adds OnClick event.
+func (b *SmallButtonWidget) OnClick(onClick func()) *SmallButtonWidget {
+	b.onClick = onClick
+	return b
+}
+
+// Build implements Widget interface.
+func (b *SmallButtonWidget) Build() {
+	if imgui.SmallButton(tStr(b.id)) && b.onClick != nil {
+		b.onClick()
+	}
+}
+
+var _ Widget = &InvisibleButtonWidget{}
+
+// InvisibleButtonWidget is a clickable region.
+// NOTE: you may want to display other widgets on this button.
+// to do so, you may move drawing cursor back by Get/SetCursor(Screen)Pos.
+type InvisibleButtonWidget struct {
+	id      string
+	width   float32
+	height  float32
+	onClick func()
+}
+
+// InvisibleButton constructs a new invisible button widget.
+func InvisibleButton() *InvisibleButtonWidget {
+	return &InvisibleButtonWidget{
+		id:      GenAutoID("InvisibleButton"),
+		width:   0,
+		height:  0,
+		onClick: nil,
+	}
+}
+
+// Size sets button's size.
+func (b *InvisibleButtonWidget) Size(width, height float32) *InvisibleButtonWidget {
+	b.width, b.height = width, height
+	return b
+}
+
+// OnClick sets click event.
+func (b *InvisibleButtonWidget) OnClick(onClick func()) *InvisibleButtonWidget {
+	b.onClick = onClick
+	return b
+}
+
+// ID allows to manually set widget's id (no need to use in normal conditions).
+func (b *InvisibleButtonWidget) ID(id string) *InvisibleButtonWidget {
+	b.id = id
+	return b
+}
+
+// Build implements Widget interface.
+func (b *InvisibleButtonWidget) Build() {
+	if imgui.InvisibleButton(tStr(b.id), imgui.Vec2{X: b.width, Y: b.height}) && b.onClick != nil {
+		b.onClick()
+	}
+}
+
+var _ Widget = &ImageButtonWidget{}
+
+// ImageButtonWidget is similar to ButtonWidget but with image texture instead of text label.
+type ImageButtonWidget struct {
+	texture      *Texture
+	width        float32
+	height       float32
+	uv0          image.Point
+	uv1          image.Point
+	framePadding int
+	bgColor      color.Color
+	tintColor    color.Color
+	onClick      func()
+}
+
+// ImageButton  constructs image buton widget.
+func ImageButton(texture *Texture) *ImageButtonWidget {
+	return &ImageButtonWidget{
+		texture:      texture,
+		width:        50,
+		height:       50,
+		uv0:          image.Point{X: 0, Y: 0},
+		uv1:          image.Point{X: 1, Y: 1},
+		framePadding: -1,
+		bgColor:      colornames.Black,
+		tintColor:    colornames.White,
+		onClick:      nil,
+	}
+}
+
+// Build implements Widget interface.
+func (b *ImageButtonWidget) Build() {
+	if b.texture == nil || b.texture.id == 0 {
+		return
+	}
+
+	if imgui.ImageButtonV(
+		b.texture.id,
+		imgui.Vec2{X: b.width, Y: b.height},
+		ToVec2(b.uv0), ToVec2(b.uv1),
+		b.framePadding, ToVec4Color(b.bgColor),
+		ToVec4Color(b.tintColor),
+	) && b.onClick != nil {
+		b.onClick()
+	}
+}
+
+// Size sets BUTTONS size.
+// NOTE: image size is button size - 2 * frame padding.
+func (b *ImageButtonWidget) Size(width, height float32) *ImageButtonWidget {
+	b.width, b.height = width, height
+	return b
+}
+
+// OnClick sets click event.
+func (b *ImageButtonWidget) OnClick(onClick func()) *ImageButtonWidget {
+	b.onClick = onClick
+	return b
+}
+
+// UV sets image's uv.
+func (b *ImageButtonWidget) UV(uv0, uv1 image.Point) *ImageButtonWidget {
+	b.uv0, b.uv1 = uv0, uv1
+	return b
+}
+
+// BgColor sets button's background color.
+func (b *ImageButtonWidget) BgColor(bgColor color.Color) *ImageButtonWidget {
+	b.bgColor = bgColor
+	return b
+}
+
+// TintColor sets tit color for image.
+func (b *ImageButtonWidget) TintColor(tintColor color.Color) *ImageButtonWidget {
+	b.tintColor = tintColor
+	return b
+}
+
+// FramePadding sets button's frame padding (set 0 to fit image to the frame).
+func (b *ImageButtonWidget) FramePadding(padding int) *ImageButtonWidget {
+	b.framePadding = padding
+	return b
+}
+
+var _ Widget = &ImageButtonWithRgbaWidget{}
+
+// ImageButtonWithRgbaWidget does similar to ImageButtonWIdget,
+// but implements image.Image instead of giu.Texture. It is probably
+// more useful than the original ImageButtonWIdget.
+type ImageButtonWithRgbaWidget struct {
+	*ImageButtonWidget
+	rgba image.Image
+	id   string
+}
+
+// ImageButtonWithRgba creates a new widget.
+func ImageButtonWithRgba(rgba image.Image) *ImageButtonWithRgbaWidget {
+	return &ImageButtonWithRgbaWidget{
+		id:                GenAutoID("ImageButtonWithRgba"),
+		ImageButtonWidget: ImageButton(nil),
+		rgba:              rgba,
+	}
+}
+
+// Size sets button's size.
+func (b *ImageButtonWithRgbaWidget) Size(width, height float32) *ImageButtonWithRgbaWidget {
+	b.ImageButtonWidget.Size(width, height)
+	return b
+}
+
+// OnClick sets click events.
+func (b *ImageButtonWithRgbaWidget) OnClick(onClick func()) *ImageButtonWithRgbaWidget {
+	b.ImageButtonWidget.OnClick(onClick)
+	return b
+}
+
+// UV sets image's uv color.
+func (b *ImageButtonWithRgbaWidget) UV(uv0, uv1 image.Point) *ImageButtonWithRgbaWidget {
+	b.ImageButtonWidget.UV(uv0, uv1)
+	return b
+}
+
+// BgColor sets button's background color.
+func (b *ImageButtonWithRgbaWidget) BgColor(bgColor color.Color) *ImageButtonWithRgbaWidget {
+	b.ImageButtonWidget.BgColor(bgColor)
+	return b
+}
+
+// TintColor sets image's tint color.
+func (b *ImageButtonWithRgbaWidget) TintColor(tintColor color.Color) *ImageButtonWithRgbaWidget {
+	b.ImageButtonWidget.TintColor(tintColor)
+	return b
+}
+
+// FramePadding sets frame padding (see (*ImageButtonWidget).TintColor).
+func (b *ImageButtonWithRgbaWidget) FramePadding(padding int) *ImageButtonWithRgbaWidget {
+	b.ImageButtonWidget.FramePadding(padding)
+	return b
+}
+
+// Build implements Widget interface.
+func (b *ImageButtonWithRgbaWidget) Build() {
+	if state := Context.GetState(b.id); state == nil {
+		Context.SetState(b.id, &imageState{})
+
+		NewTextureFromRgba(b.rgba, func(tex *Texture) {
+			Context.SetState(b.id, &imageState{texture: tex})
+		})
+	} else {
+		var isOk bool
+		imgState, isOk := state.(*imageState)
+		Assert(isOk, "ImageButtonWithRgbaWidget", "Build", "got unexpected type of widget's state")
+		b.ImageButtonWidget.texture = imgState.texture
+	}
+
+	b.ImageButtonWidget.Build()
+}
+
+var _ Widget = &CheckboxWidget{}
+
+// CheckboxWidget adds a checkbox.
+type CheckboxWidget struct {
+	text     string
+	selected *bool
+	onChange func()
+}
+
+// Checkbox creates a new CheckboxWidget.
+func Checkbox(text string, selected *bool) *CheckboxWidget {
+	return &CheckboxWidget{
+		text:     GenAutoID(text),
+		selected: selected,
+		onChange: nil,
+	}
+}
+
+// OnChange adds callback called when checkbox's state was changed.
+func (c *CheckboxWidget) OnChange(onChange func()) *CheckboxWidget {
+	c.onChange = onChange
+	return c
+}
+
+// Build implements Widget interface.
+func (c *CheckboxWidget) Build() {
+	if imgui.Checkbox(tStr(c.text), c.selected) && c.onChange != nil {
+		c.onChange()
+	}
+}
+
+var _ Widget = &RadioButtonWidget{}
+
+// RadioButtonWidget is a small, round button.
+// It is common to use it for single-choice questions.
+// see examples/widgets.
+type RadioButtonWidget struct {
+	text     string
+	active   bool
+	onChange func()
+}
+
+// RadioButton creates a radio buton.
+func RadioButton(text string, active bool) *RadioButtonWidget {
+	return &RadioButtonWidget{
+		text:     GenAutoID(text),
+		active:   active,
+		onChange: nil,
+	}
+}
+
+// OnChange adds callback when button's state gets changed.
+func (r *RadioButtonWidget) OnChange(onChange func()) *RadioButtonWidget {
+	r.onChange = onChange
+	return r
+}
+
+// Build implements Widget interface.
+func (r *RadioButtonWidget) Build() {
+	if imgui.RadioButton(tStr(r.text), r.active) && r.onChange != nil {
+		r.onChange()
+	}
+}
+
+var _ Widget = &SelectableWidget{}
+
+// SelectableWidget is a window-width button with a label which can get selected (highlighted).
+// useful for certain lists.
+type SelectableWidget struct {
+	label    string
+	selected bool
+	flags    SelectableFlags
+	width    float32
+	height   float32
+	onClick  func()
+	onDClick func()
+}
+
+// Selectable constructs a selectable widget.
+func Selectable(label string) *SelectableWidget {
+	return &SelectableWidget{
+		label:    GenAutoID(label),
+		selected: false,
+		flags:    0,
+		width:    0,
+		height:   0,
+		onClick:  nil,
+	}
+}
+
+// Selectablef creates a selectable widget with formated label.
+func Selectablef(format string, args ...any) *SelectableWidget {
+	return Selectable(fmt.Sprintf(format, args...))
+}
+
+// Selected sets if selectable widget is selected.
+func (s *SelectableWidget) Selected(selected bool) *SelectableWidget {
+	s.selected = selected
+	return s
+}
+
+// Flags add flags.
+func (s *SelectableWidget) Flags(flags SelectableFlags) *SelectableWidget {
+	s.flags = flags
+	return s
+}
+
+// Size sets selectable's size.
+func (s *SelectableWidget) Size(width, height float32) *SelectableWidget {
+	s.width, s.height = width, height
+	return s
+}
+
+// OnClick sets on click event.
+func (s *SelectableWidget) OnClick(onClick func()) *SelectableWidget {
+	s.onClick = onClick
+	return s
+}
+
+// OnDClick handles mouse left button's double click event.
+// SelectableFlagsAllowDoubleClick will set once tonDClick callback is notnull.
+// NOTE: IT IS DEPRECATED and could be removed. Use EventHandler instead.
+func (s *SelectableWidget) OnDClick(onDClick func()) *SelectableWidget {
+	s.onDClick = onDClick
+	return s
+}
+
+// Build implements Widget interface.
+func (s *SelectableWidget) Build() {
+	// If onDClick is set, check flags and set related flag when necessary
+	if s.onDClick != nil && s.flags&SelectableFlagsAllowDoubleClick != 0 {
+		s.flags |= SelectableFlagsAllowDoubleClick
+	}
+
+	if imgui.SelectableV(tStr(s.label), s.selected, int(s.flags), imgui.Vec2{X: s.width, Y: s.height}) && s.onClick != nil {
+		s.onClick()
+	}
+
+	if s.onDClick != nil && IsItemActive() && IsMouseDoubleClicked(MouseButtonLeft) {
+		s.onDClick()
+	}
+}
+
+var _ Widget = &TreeNodeWidget{}
+
+// TreeNodeWidget is a a wide button with open/close state.
+// if is opened, the `layout` is displayed below the widget.
+// It can be used to create certain lists, advanced settings sections e.t.c.
+type TreeNodeWidget struct {
+	label        string
+	flags        TreeNodeFlags
+	layout       Layout
+	eventHandler func()
+}
+
+// TreeNode creates a new tree node widget.
+func TreeNode(label string) *TreeNodeWidget {
+	return &TreeNodeWidget{
+		label:        tStr(label),
+		flags:        0,
+		layout:       nil,
+		eventHandler: nil,
+	}
+}
+
+// TreeNodef adds TreeNode with formatted label.
+func TreeNodef(format string, args ...any) *TreeNodeWidget {
+	return TreeNode(fmt.Sprintf(format, args...))
+}
+
+// Flags sets flags.
+func (t *TreeNodeWidget) Flags(flags TreeNodeFlags) *TreeNodeWidget {
+	t.flags = flags
+	return t
+}
+
+// Event create TreeNode with eventHandler
+// You could detect events (e.g. IsItemClicked IsMouseDoubleClicked etc...) and handle them for TreeNode inside eventHandler.
+// Deprecated: Use EventHandler instead!
+func (t *TreeNodeWidget) Event(handler func()) *TreeNodeWidget {
+	t.eventHandler = handler
+	return t
+}
+
+// Layout sets layout to be displayed when tree node is opened.
+func (t *TreeNodeWidget) Layout(widgets ...Widget) *TreeNodeWidget {
+	t.layout = Layout(widgets)
+	return t
+}
+
+// Build implements Widget interface.
+func (t *TreeNodeWidget) Build() {
+	open := imgui.TreeNodeV(t.label, int(t.flags))
+
+	if t.eventHandler != nil {
+		t.eventHandler()
+	}
+
+	if open {
+		t.layout.Build()
+		if (t.flags & imgui.TreeNodeFlagsNoTreePushOnOpen) == 0 {
+			imgui.TreePop()
+		}
+	}
+}

+ 220 - 0
vendor/github.com/AllenDang/giu/CodeEditor.go

@@ -0,0 +1,220 @@
+package giu
+
+import (
+	"fmt"
+
+	"github.com/AllenDang/imgui-go"
+)
+
+// LanguageDefinition represents code editor's language definition.
+type LanguageDefinition byte
+
+// language definitions:.
+const (
+	LanguageDefinitionSQL LanguageDefinition = iota
+	LanguageDefinitionCPP
+	LanguageDefinitionLua
+	LanguageDefinitionC
+)
+
+var _ Disposable = &codeEditorState{}
+
+type codeEditorState struct {
+	editor imgui.TextEditor
+}
+
+// Dispose implements Disposable interface.
+func (s *codeEditorState) Dispose() {
+	// noop
+}
+
+// static check if code editor implements Widget interface.
+var _ Widget = &CodeEditorWidget{}
+
+// CodeEditorWidget represents imgui.TextEditor.
+type CodeEditorWidget struct {
+	title string
+	width,
+	height float32
+	border bool
+}
+
+// CodeEditor creates new code editor widget.
+func CodeEditor() *CodeEditorWidget {
+	return &CodeEditorWidget{
+		title: GenAutoID("##CodeEditor"),
+	}
+}
+
+// ID allows to manually set editor's ID.
+// It isn't necessary to use it in a normal conditions.
+func (ce *CodeEditorWidget) ID(id string) *CodeEditorWidget {
+	ce.title = id
+	return ce
+}
+
+// ShowWhitespaces sets if whitespaces are shown in code editor.
+func (ce *CodeEditorWidget) ShowWhitespaces(s bool) *CodeEditorWidget {
+	ce.getState().editor.SetShowWhitespaces(s)
+	return ce
+}
+
+// TabSize sets editor's tab size.
+func (ce *CodeEditorWidget) TabSize(size int) *CodeEditorWidget {
+	ce.getState().editor.SetTabSize(size)
+	return ce
+}
+
+// LanguageDefinition sets code editor language definition.
+func (ce *CodeEditorWidget) LanguageDefinition(definition LanguageDefinition) *CodeEditorWidget {
+	s := ce.getState()
+	lookup := map[LanguageDefinition]func(){
+		LanguageDefinitionSQL: s.editor.SetLanguageDefinitionSQL,
+		LanguageDefinitionCPP: s.editor.SetLanguageDefinitionCPP,
+		LanguageDefinitionLua: s.editor.SetLanguageDefinitionLua,
+		LanguageDefinitionC:   s.editor.SetLanguageDefinitionC,
+	}
+
+	setter, correctDefinition := lookup[definition]
+	if !correctDefinition {
+		panic(fmt.Sprintf("giu/CodeEditor.go: unknown language definition %d", definition))
+	}
+
+	setter()
+
+	return ce
+}
+
+// Text sets editor's text.
+func (ce *CodeEditorWidget) Text(str string) *CodeEditorWidget {
+	ce.getState().editor.SetText(str)
+	return ce
+}
+
+// ErrorMarkers sets error markers.
+func (ce *CodeEditorWidget) ErrorMarkers(markers imgui.ErrorMarkers) *CodeEditorWidget {
+	ce.getState().editor.SetErrorMarkers(markers)
+	return ce
+}
+
+// HandleKeyboardInputs sets if editor should handle keyboard input.
+func (ce *CodeEditorWidget) HandleKeyboardInputs(b bool) *CodeEditorWidget {
+	ce.getState().editor.SetHandleKeyboardInputs(b)
+	return ce
+}
+
+// Size sets editor's size.
+func (ce *CodeEditorWidget) Size(w, h float32) *CodeEditorWidget {
+	ce.width, ce.height = w, h
+	return ce
+}
+
+// Border sets editors borders.
+func (ce *CodeEditorWidget) Border(border bool) *CodeEditorWidget {
+	ce.border = border
+	return ce
+}
+
+// HasSelection returns true if some text is selected.
+func (ce *CodeEditorWidget) HasSelection() bool {
+	return ce.getState().editor.HasSelection()
+}
+
+// GetSelectedText returns selected text.
+func (ce *CodeEditorWidget) GetSelectedText() string {
+	return ce.getState().editor.GetSelectedText()
+}
+
+// GetText returns whole text from editor.
+func (ce *CodeEditorWidget) GetText() string {
+	return ce.getState().editor.GetText()
+}
+
+// GetCurrentLineText returns current line.
+func (ce *CodeEditorWidget) GetCurrentLineText() string {
+	return ce.getState().editor.GetCurrentLineText()
+}
+
+// GetCursorPos returns cursor position.
+// (in characters).
+func (ce *CodeEditorWidget) GetCursorPos() (x, y int) {
+	return ce.getState().editor.GetCursorPos()
+}
+
+// GetSelectionStart returns star pos of selection.
+func (ce *CodeEditorWidget) GetSelectionStart() (x, y int) {
+	return ce.getState().editor.GetSelectionStart()
+}
+
+// InsertText inserts the `text`.
+func (ce *CodeEditorWidget) InsertText(text string) {
+	ce.getState().editor.InsertText(text)
+}
+
+// GetWordUnderCursor returns the word under the cursor.
+func (ce *CodeEditorWidget) GetWordUnderCursor() string {
+	return ce.getState().editor.GetWordUnderCursor()
+}
+
+// SelectWordUnderCursor selects the word under cursor.
+func (ce *CodeEditorWidget) SelectWordUnderCursor() {
+	ce.getState().editor.SelectWordUnderCursor()
+}
+
+// IsTextChanged returns true if the editable text was changed in the frame.
+func (ce *CodeEditorWidget) IsTextChanged() bool {
+	return ce.getState().editor.IsTextChanged()
+}
+
+// GetScreenCursorPos returns cursor position on the screen.
+// (in pixels).
+func (ce *CodeEditorWidget) GetScreenCursorPos() (x, y int) {
+	return ce.getState().editor.GetScreenCursorPos()
+}
+
+// Copy copies selection.
+func (ce *CodeEditorWidget) Copy() {
+	ce.getState().editor.Copy()
+}
+
+// Cut cuts selection.
+func (ce *CodeEditorWidget) Cut() {
+	ce.getState().editor.Cut()
+}
+
+// Paste does the same as Ctrl+V.
+func (ce *CodeEditorWidget) Paste() {
+	ce.getState().editor.Paste()
+}
+
+// Delete deletes the selection.
+func (ce *CodeEditorWidget) Delete() {
+	ce.getState().editor.Delete()
+}
+
+// Build implements Widget interface.
+func (ce *CodeEditorWidget) Build() {
+	s := ce.getState()
+
+	// register text in font atlas
+	tStr(s.editor.GetText())
+
+	// build editor
+	s.editor.Render(ce.title, imgui.Vec2{X: ce.width, Y: ce.height}, ce.border)
+}
+
+func (ce *CodeEditorWidget) getState() (state *codeEditorState) {
+	if s := Context.GetState(ce.title); s == nil {
+		state = &codeEditorState{
+			editor: imgui.NewTextEditor(),
+		}
+
+		Context.SetState(ce.title, state)
+	} else {
+		var isOk bool
+		state, isOk = s.(*codeEditorState)
+		Assert(isOk, "CodeEditorWidget", "getState", "unexpected widget's state type")
+	}
+
+	return state
+}

+ 101 - 0
vendor/github.com/AllenDang/giu/Context.go

@@ -0,0 +1,101 @@
+package giu
+
+import (
+	"sync"
+
+	"github.com/AllenDang/imgui-go"
+	"gopkg.in/eapache/queue.v1"
+)
+
+// Context represents a giu context.
+var Context context
+
+// Disposable should be implemented by all states stored in context.
+// Dispose method is called when state is removed from context.
+type Disposable interface {
+	Dispose()
+}
+
+type state struct {
+	valid bool
+	data  Disposable
+}
+
+type context struct {
+	// TODO: should be handled by mainthread tbh
+	// see https://github.com/faiface/mainthread/pull/4
+	isRunning bool
+
+	renderer imgui.Renderer
+	platform imgui.Platform
+
+	widgetIndexCounter int
+
+	// Indicate whether current application is running
+	isAlive bool
+
+	// States will used by custom widget to store data
+	state sync.Map
+
+	InputHandler InputHandler
+
+	textureLoadingQueue *queue.Queue
+}
+
+func (c *context) GetRenderer() imgui.Renderer {
+	return c.renderer
+}
+
+func (c *context) GetPlatform() imgui.Platform {
+	return c.platform
+}
+
+func (c *context) IO() imgui.IO {
+	return imgui.CurrentIO()
+}
+
+func (c *context) invalidAllState() {
+	c.state.Range(func(k, v any) bool {
+		if s, ok := v.(*state); ok {
+			s.valid = false
+		}
+		return true
+	})
+}
+
+func (c *context) cleanState() {
+	c.state.Range(func(k, v any) bool {
+		if s, ok := v.(*state); ok {
+			if !s.valid {
+				c.state.Delete(k)
+				s.data.Dispose()
+			}
+		}
+		return true
+	})
+
+	// Reset widgetIndexCounter
+	c.widgetIndexCounter = 0
+}
+
+func (c *context) SetState(id string, data Disposable) {
+	c.state.Store(id, &state{valid: true, data: data})
+}
+
+func (c *context) GetState(id string) any {
+	if v, ok := c.state.Load(id); ok {
+		if s, ok := v.(*state); ok {
+			s.valid = true
+			return s.data
+		}
+	}
+
+	return nil
+}
+
+// Get widget index for current layout.
+func (c *context) GetWidgetIndex() int {
+	i := c.widgetIndexCounter
+	c.widgetIndexCounter++
+	return i
+}

+ 12 - 0
vendor/github.com/AllenDang/giu/Direction.go

@@ -0,0 +1,12 @@
+package giu
+
+// Direction represents a ArrowButton direction.
+type Direction uint8
+
+// directions.
+const (
+	DirectionLeft Direction = iota
+	DirectionRight
+	DirectionUp
+	DirectionDown
+)

+ 173 - 0
vendor/github.com/AllenDang/giu/EventHandler.go

@@ -0,0 +1,173 @@
+package giu
+
+var _ Disposable = &eventHandlerState{}
+
+type eventHandlerState struct {
+	isActive bool
+}
+
+// Dispose implements Disposable interface.
+func (s *eventHandlerState) Dispose() {
+	// noop
+}
+
+type mouseEvent struct {
+	mouseButton MouseButton
+	callback    func()
+	cond        func(MouseButton) bool
+}
+
+type keyEvent struct {
+	key      Key
+	callback func()
+	cond     func(Key) bool
+}
+
+var _ Widget = &EventHandler{}
+
+// EventHandler is a universal event handler for giu widgets.
+// put giu.Event()... after any widget to handle any event.
+type EventHandler struct {
+	hover       func()
+	mouseEvents []mouseEvent
+	keyEvents   []keyEvent
+	onActivate,
+	onDeactivate,
+	onActive func()
+}
+
+// Event adds a new event to widget above.
+func Event() *EventHandler {
+	return &EventHandler{
+		mouseEvents: make([]mouseEvent, 0),
+		keyEvents:   make([]keyEvent, 0),
+	}
+}
+
+// OnHover sets callback when item gets hovered.
+func (eh *EventHandler) OnHover(onHover func()) *EventHandler {
+	eh.hover = onHover
+	return eh
+}
+
+// OnActive sets a callback when ite IS ACTIVE (not activated).
+func (eh *EventHandler) OnActive(cb func()) *EventHandler {
+	eh.onActive = cb
+	return eh
+}
+
+// OnActivate sets callback when item gets activated.
+func (eh *EventHandler) OnActivate(cb func()) *EventHandler {
+	eh.onActivate = cb
+	return eh
+}
+
+// OnDeactivate sets callback when item gets deactivated.
+func (eh *EventHandler) OnDeactivate(cb func()) *EventHandler {
+	eh.onDeactivate = cb
+	return eh
+}
+
+// Key events
+
+// OnKeyDown sets callback when key `key` is down.
+func (eh *EventHandler) OnKeyDown(key Key, cb func()) *EventHandler {
+	eh.keyEvents = append(eh.keyEvents, keyEvent{key, cb, IsKeyDown})
+	return eh
+}
+
+// OnKeyPressed sets callback when key `key` is pressed.
+func (eh *EventHandler) OnKeyPressed(key Key, cb func()) *EventHandler {
+	eh.keyEvents = append(eh.keyEvents, keyEvent{key, cb, IsKeyPressed})
+	return eh
+}
+
+// OnKeyReleased sets callback when key `key` is released.
+func (eh *EventHandler) OnKeyReleased(key Key, cb func()) *EventHandler {
+	eh.keyEvents = append(eh.keyEvents, keyEvent{key, cb, IsKeyReleased})
+	return eh
+}
+
+// Mouse events
+
+// OnClick sets callback when mouse button `mouseButton` is clicked.
+func (eh *EventHandler) OnClick(mouseButton MouseButton, callback func()) *EventHandler {
+	eh.mouseEvents = append(eh.mouseEvents, mouseEvent{mouseButton, callback, IsMouseClicked})
+	return eh
+}
+
+// OnDClick sets callback when mouse button `mouseButton` is double-clicked.
+func (eh *EventHandler) OnDClick(mouseButton MouseButton, callback func()) *EventHandler {
+	eh.mouseEvents = append(eh.mouseEvents, mouseEvent{mouseButton, callback, IsMouseDoubleClicked})
+	return eh
+}
+
+// OnMouseDown sets callback when mouse button `mouseButton` is down.
+func (eh *EventHandler) OnMouseDown(mouseButton MouseButton, callback func()) *EventHandler {
+	eh.mouseEvents = append(eh.mouseEvents, mouseEvent{mouseButton, callback, IsMouseDown})
+	return eh
+}
+
+// OnMouseReleased sets callback when mouse button `mouseButton` is released.
+func (eh *EventHandler) OnMouseReleased(mouseButton MouseButton, callback func()) *EventHandler {
+	eh.mouseEvents = append(eh.mouseEvents, mouseEvent{mouseButton, callback, IsMouseReleased})
+	return eh
+}
+
+// Build implements Widget interface
+// nolint:gocognit,gocyclo // will fix later
+func (eh *EventHandler) Build() {
+	isActive := IsItemActive()
+
+	if eh.onActivate != nil || eh.onDeactivate != nil {
+		var state *eventHandlerState
+		stateID := GenAutoID("eventHandlerState")
+		if s := Context.GetState(stateID); s != nil {
+			var isOk bool
+			state, isOk = s.(*eventHandlerState)
+			Assert(isOk, "EventHandler", "Build", "unexpected type of state received")
+		} else {
+			newState := &eventHandlerState{}
+			Context.SetState(stateID, newState)
+			state = newState
+		}
+
+		if eh.onActivate != nil && isActive && !state.isActive {
+			state.isActive = true
+			eh.onActivate()
+		}
+
+		if eh.onDeactivate != nil && !isActive && state.isActive {
+			state.isActive = false
+			eh.onDeactivate()
+		}
+	}
+
+	if isActive && eh.onActive != nil {
+		eh.onActive()
+	}
+
+	if !IsItemHovered() {
+		return
+	}
+
+	if eh.hover != nil {
+		eh.hover()
+	}
+
+	if len(eh.keyEvents) > 0 {
+		for _, event := range eh.keyEvents {
+			if event.callback != nil && event.cond(event.key) {
+				event.callback()
+			}
+		}
+	}
+
+	if len(eh.mouseEvents) > 0 {
+		for _, event := range eh.mouseEvents {
+			if event.callback != nil && event.cond(event.mouseButton) {
+				event.callback()
+			}
+		}
+	}
+}

+ 86 - 0
vendor/github.com/AllenDang/giu/Events.go

@@ -0,0 +1,86 @@
+package giu
+
+import "github.com/AllenDang/imgui-go"
+
+// MouseButton represents imgui.MoseButton.
+type MouseButton int
+
+// mouse buttons.
+const (
+	MouseButtonLeft   MouseButton = 0
+	MouseButtonRight  MouseButton = 1
+	MouseButtonMiddle MouseButton = 2
+)
+
+// IsItemHovered returns true if mouse is over the item.
+func IsItemHovered() bool {
+	return imgui.IsItemHovered()
+}
+
+// IsItemClicked returns true if mouse is clicked
+// NOTE: if you're looking for clicking detection, see EventHandler.go.
+func IsItemClicked(mouseButton MouseButton) bool {
+	return imgui.IsItemClicked(int(mouseButton))
+}
+
+// IsItemActive returns true if item is active.
+func IsItemActive() bool {
+	return imgui.IsItemActive()
+}
+
+// IsKeyDown returns true if key `key` is down.
+func IsKeyDown(key Key) bool {
+	return imgui.IsKeyDown(int(key))
+}
+
+// IsKeyPressed returns true if key `key` is pressed.
+func IsKeyPressed(key Key) bool {
+	return imgui.IsKeyPressed(int(key))
+}
+
+// IsKeyReleased returns true if key `key` is released.
+func IsKeyReleased(key Key) bool {
+	return imgui.IsKeyReleased(int(key))
+}
+
+// IsMouseDown returns true if mouse button `button` is down.
+func IsMouseDown(button MouseButton) bool {
+	return imgui.IsMouseDown(int(button))
+}
+
+// IsMouseClicked returns true if mouse button `button` is clicked
+// NOTE: if you're looking for clicking detection, see EventHandler.go.
+func IsMouseClicked(button MouseButton) bool {
+	return imgui.IsMouseClicked(int(button))
+}
+
+// IsMouseReleased returns true if mouse button `button` is released.
+func IsMouseReleased(button MouseButton) bool {
+	return imgui.IsMouseReleased(int(button))
+}
+
+// IsMouseDoubleClicked returns true if mouse button `button` is double clicked.
+func IsMouseDoubleClicked(button MouseButton) bool {
+	return imgui.IsMouseDoubleClicked(int(button))
+}
+
+// IsWindowAppearing returns true if window is appearing.
+func IsWindowAppearing() bool {
+	return imgui.IsWindowAppearing()
+}
+
+// IsWindowCollapsed returns true if window is disappearing.
+func IsWindowCollapsed() bool {
+	return imgui.IsWindowCollapsed()
+}
+
+// IsWindowFocused returns true if window is focused
+// NOTE: see also (*Window).HasFocus and (*Window).BringToFront.
+func IsWindowFocused(flags FocusedFlags) bool {
+	return imgui.IsWindowFocused(int(flags))
+}
+
+// IsWindowHovered returns true if the window is hovered.
+func IsWindowHovered(flags HoveredFlags) bool {
+	return imgui.IsWindowHovered(int(flags))
+}

+ 692 - 0
vendor/github.com/AllenDang/giu/ExtraWidgets.go

@@ -0,0 +1,692 @@
+package giu
+
+import (
+	"fmt"
+	"image"
+	"time"
+
+	"github.com/AllenDang/imgui-go"
+)
+
+var _ Widget = &HSplitterWidget{}
+
+type HSplitterWidget struct {
+	id     string
+	width  float32
+	height float32
+	delta  *float32
+}
+
+func HSplitter(delta *float32) *HSplitterWidget {
+	return &HSplitterWidget{
+		id:     GenAutoID("HSplitter"),
+		width:  0,
+		height: 0,
+		delta:  delta,
+	}
+}
+
+func (h *HSplitterWidget) Size(width, height float32) *HSplitterWidget {
+	aw, ah := GetAvailableRegion()
+
+	if width == 0 {
+		h.width = aw
+	} else {
+		h.width = width
+	}
+
+	if height == 0 {
+		h.height = ah
+	} else {
+		h.height = height
+	}
+
+	return h
+}
+
+func (h *HSplitterWidget) ID(id string) *HSplitterWidget {
+	h.id = id
+	return h
+}
+
+// Build implements Widget interface
+// nolint:dupl // will fix later
+func (h *HSplitterWidget) Build() {
+	// Calc line position.
+	width := 40
+	height := 2
+
+	pt := GetCursorScreenPos()
+
+	centerX := int(h.width / 2)
+	centerY := int(h.height / 2)
+
+	ptMin := image.Pt(centerX-width/2, centerY-height/2)
+	ptMax := image.Pt(centerX+width/2, centerY+height/2)
+
+	style := imgui.CurrentStyle()
+	c := Vec4ToRGBA(style.GetColor(imgui.StyleColorScrollbarGrab))
+
+	// Place a invisible button to capture event.
+	imgui.InvisibleButton(h.id, imgui.Vec2{X: h.width, Y: h.height})
+	if imgui.IsItemActive() {
+		*(h.delta) = imgui.CurrentIO().GetMouseDelta().Y
+	} else {
+		*(h.delta) = 0
+	}
+	if imgui.IsItemHovered() {
+		imgui.SetMouseCursor(imgui.MouseCursorResizeNS)
+		c = Vec4ToRGBA(style.GetColor(imgui.StyleColorScrollbarGrabActive))
+	}
+
+	// Draw a line in the very center
+	canvas := GetCanvas()
+	canvas.AddRectFilled(pt.Add(ptMin), pt.Add(ptMax), c, 0, 0)
+}
+
+var _ Widget = &VSplitterWidget{}
+
+type VSplitterWidget struct {
+	id     string
+	width  float32
+	height float32
+	delta  *float32
+}
+
+func VSplitter(delta *float32) *VSplitterWidget {
+	return &VSplitterWidget{
+		id:     GenAutoID("VSplitter"),
+		width:  0,
+		height: 0,
+		delta:  delta,
+	}
+}
+
+func (v *VSplitterWidget) Size(width, height float32) *VSplitterWidget {
+	aw, ah := GetAvailableRegion()
+
+	if width == 0 {
+		v.width = aw
+	} else {
+		v.width = width
+	}
+
+	if height == 0 {
+		v.height = ah
+	} else {
+		v.height = height
+	}
+
+	return v
+}
+
+func (v *VSplitterWidget) ID(id string) *VSplitterWidget {
+	v.id = id
+	return v
+}
+
+// Build implements Widget interface
+// nolint:dupl // will fix later
+func (v *VSplitterWidget) Build() {
+	// Calc line position.
+	width := 2
+	height := 40
+
+	pt := GetCursorScreenPos()
+
+	centerX := int(v.width / 2)
+	centerY := int(v.height / 2)
+
+	ptMin := image.Pt(centerX-width/2, centerY-height/2)
+	ptMax := image.Pt(centerX+width/2, centerY+height/2)
+
+	style := imgui.CurrentStyle()
+	c := Vec4ToRGBA(style.GetColor(imgui.StyleColorScrollbarGrab))
+
+	// Place a invisible button to capture event.
+	imgui.InvisibleButton(v.id, imgui.Vec2{X: v.width, Y: v.height})
+	if imgui.IsItemActive() {
+		*(v.delta) = imgui.CurrentIO().GetMouseDelta().X
+	} else {
+		*(v.delta) = 0
+	}
+
+	if imgui.IsItemHovered() {
+		imgui.SetMouseCursor(imgui.MouseCursorResizeEW)
+		c = Vec4ToRGBA(style.GetColor(imgui.StyleColorScrollbarGrabActive))
+	}
+
+	// Draw a line in the very center
+	canvas := GetCanvas()
+	canvas.AddRectFilled(pt.Add(ptMin), pt.Add(ptMax), c, 0, 0)
+}
+
+type TreeTableRowWidget struct {
+	label    string
+	flags    TreeNodeFlags
+	layout   Layout
+	children []*TreeTableRowWidget
+}
+
+func TreeTableRow(label string, widgets ...Widget) *TreeTableRowWidget {
+	return &TreeTableRowWidget{
+		label:  GenAutoID(label),
+		layout: widgets,
+	}
+}
+
+func (ttr *TreeTableRowWidget) Children(rows ...*TreeTableRowWidget) *TreeTableRowWidget {
+	ttr.children = rows
+	return ttr
+}
+
+func (ttr *TreeTableRowWidget) Flags(flags TreeNodeFlags) *TreeTableRowWidget {
+	ttr.flags = flags
+	return ttr
+}
+
+// BuildTreeTableRow executes table row building steps.
+func (ttr *TreeTableRowWidget) BuildTreeTableRow() {
+	imgui.TableNextRow(0, 0)
+	imgui.TableNextColumn()
+
+	open := false
+	if len(ttr.children) > 0 {
+		open = imgui.TreeNodeV(tStr(ttr.label), int(ttr.flags))
+	} else {
+		ttr.flags |= TreeNodeFlagsLeaf | TreeNodeFlagsNoTreePushOnOpen
+		imgui.TreeNodeV(tStr(ttr.label), int(ttr.flags))
+	}
+
+	for _, w := range ttr.layout {
+		switch w.(type) {
+		case *TooltipWidget,
+			*ContextMenuWidget, *PopupModalWidget:
+			// noop
+		default:
+			imgui.TableNextColumn()
+		}
+
+		w.Build()
+	}
+
+	if len(ttr.children) > 0 && open {
+		for _, c := range ttr.children {
+			c.BuildTreeTableRow()
+		}
+
+		imgui.TreePop()
+	}
+}
+
+var _ Widget = &TreeTableWidget{}
+
+type TreeTableWidget struct {
+	id           string
+	flags        TableFlags
+	size         imgui.Vec2
+	columns      []*TableColumnWidget
+	rows         []*TreeTableRowWidget
+	freezeRow    int
+	freezeColumn int
+}
+
+func TreeTable() *TreeTableWidget {
+	return &TreeTableWidget{
+		id:      GenAutoID("TreeTable"),
+		flags:   TableFlagsBordersV | TableFlagsBordersOuterH | TableFlagsResizable | TableFlagsRowBg | TableFlagsNoBordersInBody,
+		rows:    nil,
+		columns: nil,
+	}
+}
+
+// Freeze columns/rows so they stay visible when scrolled.
+func (tt *TreeTableWidget) Freeze(col, row int) *TreeTableWidget {
+	tt.freezeColumn = col
+	tt.freezeRow = row
+	return tt
+}
+
+func (tt *TreeTableWidget) Size(width, height float32) *TreeTableWidget {
+	tt.size = imgui.Vec2{X: width, Y: height}
+	return tt
+}
+
+func (tt *TreeTableWidget) Flags(flags TableFlags) *TreeTableWidget {
+	tt.flags = flags
+	return tt
+}
+
+func (tt *TreeTableWidget) Columns(cols ...*TableColumnWidget) *TreeTableWidget {
+	tt.columns = cols
+	return tt
+}
+
+func (tt *TreeTableWidget) Rows(rows ...*TreeTableRowWidget) *TreeTableWidget {
+	tt.rows = rows
+	return tt
+}
+
+// Build implements Widget interface.
+func (tt *TreeTableWidget) Build() {
+	if len(tt.rows) == 0 {
+		return
+	}
+
+	colCount := len(tt.columns)
+	if colCount == 0 {
+		colCount = len(tt.rows[0].layout) + 1
+	}
+
+	if imgui.BeginTable(tt.id, colCount, imgui.TableFlags(tt.flags), tt.size, 0) {
+		if tt.freezeColumn >= 0 && tt.freezeRow >= 0 {
+			imgui.TableSetupScrollFreeze(tt.freezeColumn, tt.freezeRow)
+		}
+
+		if len(tt.columns) > 0 {
+			for _, col := range tt.columns {
+				col.BuildTableColumn()
+			}
+			imgui.TableHeadersRow()
+		}
+
+		for _, row := range tt.rows {
+			row.BuildTreeTableRow()
+		}
+
+		imgui.EndTable()
+	}
+}
+
+var _ Widget = &CustomWidget{}
+
+type CustomWidget struct {
+	builder func()
+}
+
+// Build implements Widget interface.
+func (c *CustomWidget) Build() {
+	if c.builder != nil {
+		c.builder()
+	}
+}
+
+func Custom(builder func()) *CustomWidget {
+	return &CustomWidget{
+		builder: builder,
+	}
+}
+
+var _ Widget = &ConditionWidget{}
+
+type ConditionWidget struct {
+	cond       bool
+	layoutIf   Layout
+	layoutElse Layout
+}
+
+func Condition(cond bool, layoutIf, layoutElse Layout) *ConditionWidget {
+	return &ConditionWidget{
+		cond:       cond,
+		layoutIf:   layoutIf,
+		layoutElse: layoutElse,
+	}
+}
+
+// Build implements Widget interface.
+func (c *ConditionWidget) Build() {
+	if c.cond {
+		if c.layoutIf != nil {
+			c.layoutIf.Build()
+		}
+	} else {
+		if c.layoutElse != nil {
+			c.layoutElse.Build()
+		}
+	}
+}
+
+// RangeBuilder batch create widgets and render only which is visible.
+func RangeBuilder(id string, values []any, builder func(int, any) Widget) Layout {
+	var layout Layout
+
+	layout = append(layout, Custom(func() { imgui.PushID(id) }))
+
+	if len(values) > 0 && builder != nil {
+		for i, v := range values {
+			valueRef := v
+			widget := builder(i, valueRef)
+			layout = append(layout, widget)
+		}
+	}
+
+	layout = append(layout, Custom(func() { imgui.PopID() }))
+
+	return layout
+}
+
+type ListBoxState struct {
+	selectedIndex int
+}
+
+func (s *ListBoxState) Dispose() {
+	// Nothing to do here.
+}
+
+var _ Widget = &ListBoxWidget{}
+
+type ListBoxWidget struct {
+	id       string
+	width    float32
+	height   float32
+	border   bool
+	items    []string
+	menus    []string
+	onChange func(selectedIndex int)
+	onDClick func(selectedIndex int)
+	onMenu   func(selectedIndex int, menu string)
+}
+
+func ListBox(id string, items []string) *ListBoxWidget {
+	return &ListBoxWidget{
+		id:       id,
+		width:    0,
+		height:   0,
+		border:   true,
+		items:    items,
+		menus:    nil,
+		onChange: nil,
+		onDClick: nil,
+		onMenu:   nil,
+	}
+}
+
+func (l *ListBoxWidget) Size(width, height float32) *ListBoxWidget {
+	l.width, l.height = width, height
+	return l
+}
+
+func (l *ListBoxWidget) Border(b bool) *ListBoxWidget {
+	l.border = b
+	return l
+}
+
+func (l *ListBoxWidget) ContextMenu(menuItems []string) *ListBoxWidget {
+	l.menus = menuItems
+	return l
+}
+
+func (l *ListBoxWidget) OnChange(onChange func(selectedIndex int)) *ListBoxWidget {
+	l.onChange = onChange
+	return l
+}
+
+func (l *ListBoxWidget) OnDClick(onDClick func(selectedIndex int)) *ListBoxWidget {
+	l.onDClick = onDClick
+	return l
+}
+
+func (l *ListBoxWidget) OnMenu(onMenu func(selectedIndex int, menu string)) *ListBoxWidget {
+	l.onMenu = onMenu
+	return l
+}
+
+// Build implements Widget interface
+// nolint:gocognit // will fix later
+func (l *ListBoxWidget) Build() {
+	var state *ListBoxState
+	if s := Context.GetState(l.id); s == nil {
+		state = &ListBoxState{selectedIndex: 0}
+		Context.SetState(l.id, state)
+	} else {
+		var isOk bool
+		state, isOk = s.(*ListBoxState)
+		Assert(isOk, "ListBoxWidget", "Build", "wrong state type recovered")
+	}
+
+	child := Child().Border(l.border).Size(l.width, l.height).Layout(Layout{
+		Custom(func() {
+			clipper := imgui.NewListClipper()
+			defer clipper.Delete()
+
+			clipper.Begin(len(l.items))
+
+			for clipper.Step() {
+				for i := clipper.DisplayStart(); i < clipper.DisplayEnd(); i++ {
+					selected := i == state.selectedIndex
+					item := l.items[i]
+					Selectable(item).Selected(selected).Flags(SelectableFlagsAllowDoubleClick).OnClick(func() {
+						if state.selectedIndex != i {
+							state.selectedIndex = i
+							if l.onChange != nil {
+								l.onChange(i)
+							}
+						}
+					}).Build()
+
+					if IsItemHovered() && IsMouseDoubleClicked(MouseButtonLeft) && l.onDClick != nil {
+						l.onDClick(state.selectedIndex)
+					}
+
+					// Build context menus
+					var menus Layout
+					for _, m := range l.menus {
+						index := i
+						menu := m
+						menus = append(menus, MenuItem(fmt.Sprintf("%s##%d", menu, index)).OnClick(func() {
+							if l.onMenu != nil {
+								l.onMenu(index, menu)
+							}
+						}))
+					}
+
+					if len(menus) > 0 {
+						ContextMenu().Layout(menus).Build()
+					}
+				}
+			}
+
+			clipper.End()
+		}),
+	})
+
+	child.Build()
+}
+
+var _ Widget = &DatePickerWidget{}
+
+type DatePickerWidget struct {
+	id          string
+	date        *time.Time
+	width       float32
+	onChange    func()
+	format      string
+	startOfWeek time.Weekday
+}
+
+func DatePicker(id string, date *time.Time) *DatePickerWidget {
+	return &DatePickerWidget{
+		id:          GenAutoID(id),
+		date:        date,
+		width:       100,
+		startOfWeek: time.Sunday,
+		onChange:    func() {}, // small hack - prevent giu from setting nil cb (skip nil check later)
+	}
+}
+
+func (d *DatePickerWidget) Size(width float32) *DatePickerWidget {
+	d.width = width
+	return d
+}
+
+func (d *DatePickerWidget) OnChange(onChange func()) *DatePickerWidget {
+	if onChange != nil {
+		d.onChange = onChange
+	}
+	return d
+}
+
+func (d *DatePickerWidget) Format(format string) *DatePickerWidget {
+	d.format = format
+	return d
+}
+
+func (d *DatePickerWidget) StartOfWeek(weekday time.Weekday) *DatePickerWidget {
+	d.startOfWeek = weekday
+	return d
+}
+
+func (d *DatePickerWidget) getFormat() string {
+	if d.format == "" {
+		return "2006-01-02" // default
+	}
+	return d.format
+}
+
+func (d *DatePickerWidget) offsetDay(offset int) time.Weekday {
+	day := (int(d.startOfWeek) + offset) % 7
+	// offset may be negative, thus day can be negative
+	day = (day + 7) % 7
+	return time.Weekday(day)
+}
+
+// Build implements Widget interface.
+func (d *DatePickerWidget) Build() {
+	if d.date == nil {
+		return
+	}
+
+	imgui.PushID(d.id)
+	defer imgui.PopID()
+
+	if d.width > 0 {
+		PushItemWidth(d.width)
+		defer PopItemWidth()
+	}
+
+	if imgui.BeginComboV(d.id+"##Combo", d.date.Format(d.getFormat()), imgui.ComboFlagsHeightLargest) {
+		// --- [Build year widget] ---
+		imgui.AlignTextToFramePadding()
+
+		const yearButtonSize = 25
+
+		Row(
+			Label(tStr(" Year")),
+			Labelf("%14d", d.date.Year()),
+			Button("-##"+d.id+"year").OnClick(func() {
+				*d.date = d.date.AddDate(-1, 0, 0)
+				d.onChange()
+			}).Size(yearButtonSize, yearButtonSize),
+			Button("+##"+d.id+"year").OnClick(func() {
+				*d.date = d.date.AddDate(1, 0, 0)
+				d.onChange()
+			}).Size(yearButtonSize, yearButtonSize),
+		).Build()
+
+		// --- [Build month widgets] ---
+		Row(
+			Label("Month"),
+			Labelf("%10s(%02d)", d.date.Month().String(), d.date.Month()),
+			Button("-##"+d.id+"month").OnClick(func() {
+				*d.date = d.date.AddDate(0, -1, 0)
+				d.onChange()
+			}).Size(yearButtonSize, yearButtonSize),
+			Button("+##"+d.id+"month").OnClick(func() {
+				*d.date = d.date.AddDate(0, 1, 0)
+				d.onChange()
+			}).Size(yearButtonSize, yearButtonSize),
+		).Build()
+
+		// --- [Build day widgets] ---
+		days := d.getDaysGroups()
+
+		// Create calendar (widget)
+		columns := make([]*TableColumnWidget, 7)
+
+		for i := 0; i < 7; i++ {
+			firstChar := d.offsetDay(i).String()[0:1]
+			columns[i] = TableColumn(firstChar)
+		}
+
+		// Build day widgets
+		var rows []*TableRowWidget
+
+		for _, week := range days {
+			var row []Widget
+
+			for _, day := range week {
+				day := day // hack for golang ranges
+				if day == 0 {
+					row = append(row, Label(" "))
+					continue
+				}
+
+				row = append(row, d.calendarField(day))
+			}
+
+			rows = append(rows, TableRow(row...))
+		}
+
+		Table().Flags(TableFlagsBorders | TableFlagsSizingStretchSame).Columns(columns...).Rows(rows...).Build()
+
+		imgui.EndCombo()
+	}
+}
+
+// store month days sorted in weeks.
+func (d *DatePickerWidget) getDaysGroups() (days [][]int) {
+	firstDay := time.Date(d.date.Year(), d.date.Month(), 1, 0, 0, 0, 0, time.Local)
+	lastDay := firstDay.AddDate(0, 1, 0).Add(time.Nanosecond * -1)
+
+	// calculate first week
+	days = append(days, make([]int, 7))
+
+	monthDay := 1
+	emptyDaysInFirstWeek := (int(firstDay.Weekday()) - int(d.startOfWeek) + 7) % 7
+	for i := emptyDaysInFirstWeek; i < 7; i++ {
+		days[0][i] = monthDay
+		monthDay++
+	}
+
+	// Build rest rows
+	for ; monthDay <= lastDay.Day(); monthDay++ {
+		if len(days[len(days)-1]) == 7 {
+			days = append(days, []int{})
+		}
+
+		days[len(days)-1] = append(days[len(days)-1], monthDay)
+	}
+
+	// Pad last row
+	lastRowLen := len(days[len(days)-1])
+	if lastRowLen < 7 {
+		for i := lastRowLen; i < 7; i++ {
+			days[len(days)-1] = append(days[len(days)-1], 0)
+		}
+	}
+
+	return days
+}
+
+func (d *DatePickerWidget) calendarField(day int) Widget {
+	today := time.Now()
+	highlightColor := imgui.CurrentStyle().GetColor(imgui.StyleColorPlotHistogram)
+	return Custom(func() {
+		isToday := d.date.Year() == today.Year() && d.date.Month() == today.Month() && day == today.Day()
+		if isToday {
+			imgui.PushStyleColor(imgui.StyleColorText, highlightColor)
+		}
+
+		Selectable(fmt.Sprintf("%02d", day)).Selected(isToday).OnClick(func() {
+			*d.date = time.Date(
+				d.date.Year(), d.date.Month(), day,
+				0, 0, 0, 0,
+				d.date.Location())
+			d.onChange()
+		}).Build()
+
+		if isToday {
+			imgui.PopStyleColor()
+		}
+	})
+}

+ 503 - 0
vendor/github.com/AllenDang/giu/Flags.go

@@ -0,0 +1,503 @@
+package giu
+
+import "github.com/AllenDang/imgui-go"
+
+// InputTextFlags represents input text flags.
+type InputTextFlags int
+
+// input text flags.
+const (
+	// InputTextFlagsNone sets everything default.
+	InputTextFlagsNone InputTextFlags = imgui.InputTextFlagsNone
+	// InputTextFlagsCharsDecimal allows 0123456789.+-.
+	InputTextFlagsCharsDecimal InputTextFlags = imgui.InputTextFlagsCharsDecimal
+	// InputTextFlagsCharsHexadecimal allow 0123456789ABCDEFabcdef.
+	InputTextFlagsCharsHexadecimal InputTextFlags = imgui.InputTextFlagsCharsHexadecimal
+	// InputTextFlagsCharsUppercase turns a..z into A..Z.
+	InputTextFlagsCharsUppercase InputTextFlags = imgui.InputTextFlagsCharsUppercase
+	// InputTextFlagsCharsNoBlank filters out spaces, tabs.
+	InputTextFlagsCharsNoBlank InputTextFlags = imgui.InputTextFlagsCharsNoBlank
+	// InputTextFlagsAutoSelectAll selects entire text when first taking mouse focus.
+	InputTextFlagsAutoSelectAll InputTextFlags = imgui.InputTextFlagsAutoSelectAll
+	// InputTextFlagsEnterReturnsTrue returns 'true' when Enter is pressed (as opposed to when the value was modified).
+	InputTextFlagsEnterReturnsTrue InputTextFlags = imgui.InputTextFlagsEnterReturnsTrue
+	// InputTextFlagsCallbackCompletion for callback on pressing TAB (for completion handling).
+	InputTextFlagsCallbackCompletion InputTextFlags = imgui.InputTextFlagsCallbackCompletion
+	// InputTextFlagsCallbackHistory for callback on pressing Up/Down arrows (for history handling).
+	InputTextFlagsCallbackHistory InputTextFlags = imgui.InputTextFlagsCallbackHistory
+	// InputTextFlagsCallbackAlways for callback on each iteration. User code may query cursor position, modify text buffer.
+	InputTextFlagsCallbackAlways InputTextFlags = imgui.InputTextFlagsCallbackAlways
+	// InputTextFlagsCallbackCharFilter for callback on character inputs to replace or discard them.
+	// Modify 'EventChar' to replace or discard, or return 1 in callback to discard.
+	InputTextFlagsCallbackCharFilter InputTextFlags = imgui.InputTextFlagsCallbackCharFilter
+	// InputTextFlagsAllowTabInput when pressing TAB to input a '\t' character into the text field.
+	InputTextFlagsAllowTabInput InputTextFlags = imgui.InputTextFlagsAllowTabInput
+	// InputTextFlagsCtrlEnterForNewLine in multi-line mode, unfocus with Enter, add new line with Ctrl+Enter
+	// (default is opposite: unfocus with Ctrl+Enter, add line with Enter).
+	InputTextFlagsCtrlEnterForNewLine InputTextFlags = imgui.InputTextFlagsCtrlEnterForNewLine
+	// InputTextFlagsNoHorizontalScroll disables following the cursor horizontally.
+	InputTextFlagsNoHorizontalScroll InputTextFlags = imgui.InputTextFlagsNoHorizontalScroll
+	// InputTextFlagsAlwaysInsertMode sets insert mode.
+	InputTextFlagsAlwaysInsertMode InputTextFlags = imgui.InputTextFlagsAlwaysInsertMode
+	// InputTextFlagsReadOnly sets read-only mode.
+	InputTextFlagsReadOnly InputTextFlags = imgui.InputTextFlagsReadOnly
+	// InputTextFlagsPassword sets password mode, display all characters as '*'.
+	InputTextFlagsPassword InputTextFlags = imgui.InputTextFlagsPassword
+	// InputTextFlagsNoUndoRedo disables undo/redo. Note that input text owns the text data while active,
+	// if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID().
+	InputTextFlagsNoUndoRedo InputTextFlags = imgui.InputTextFlagsNoUndoRedo
+	// InputTextFlagsCharsScientific allows 0123456789.+-*/eE (Scientific notation input).
+	InputTextFlagsCharsScientific InputTextFlags = imgui.InputTextFlagsCharsScientific
+)
+
+// WindowFlags represents a window flags (see (*WindowWidget).Flags.
+type WindowFlags int
+
+// window flags.
+const (
+	// WindowFlagsNone default = 0.
+	WindowFlagsNone WindowFlags = imgui.WindowFlagsNone
+	// WindowFlagsNoTitleBar disables title-bar.
+	WindowFlagsNoTitleBar WindowFlags = imgui.WindowFlagsNoTitleBar
+	// WindowFlagsNoResize disables user resizing with the lower-right grip.
+	WindowFlagsNoResize WindowFlags = imgui.WindowFlagsNoResize
+	// WindowFlagsNoMove disables user moving the window.
+	WindowFlagsNoMove WindowFlags = imgui.WindowFlagsNoMove
+	// WindowFlagsNoScrollbar disables scrollbars. Window can still scroll with mouse or programmatically.
+	WindowFlagsNoScrollbar WindowFlags = imgui.WindowFlagsNoScrollbar
+	// WindowFlagsNoScrollWithMouse disables user vertically scrolling with mouse wheel. On child window, mouse wheel
+	// will be forwarded to the parent unless NoScrollbar is also set.
+	WindowFlagsNoScrollWithMouse WindowFlags = imgui.WindowFlagsNoScrollWithMouse
+	// WindowFlagsNoCollapse disables user collapsing window by double-clicking on it.
+	WindowFlagsNoCollapse WindowFlags = imgui.WindowFlagsNoCollapse
+	// WindowFlagsAlwaysAutoResize resizes every window to its content every frame.
+	WindowFlagsAlwaysAutoResize WindowFlags = imgui.WindowFlagsAlwaysAutoResize
+	// WindowFlagsNoBackground disables drawing background color (WindowBg, etc.) and outside border. Similar as using
+	// SetNextWindowBgAlpha(0.0f).
+	WindowFlagsNoBackground WindowFlags = imgui.WindowFlagsNoBackground
+	// WindowFlagsNoSavedSettings will never load/save settings in .ini file.
+	WindowFlagsNoSavedSettings WindowFlags = imgui.WindowFlagsNoSavedSettings
+	// WindowFlagsNoMouseInputs disables catching mouse, hovering test with pass through.
+	WindowFlagsNoMouseInputs WindowFlags = imgui.WindowFlagsNoMouseInputs
+	// WindowFlagsMenuBar has a menu-bar.
+	WindowFlagsMenuBar WindowFlags = imgui.WindowFlagsMenuBar
+	// WindowFlagsHorizontalScrollbar allows horizontal scrollbar to appear (off by default). You may use
+	// SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo
+	// in the "Horizontal Scrolling" section.
+	WindowFlagsHorizontalScrollbar WindowFlags = imgui.WindowFlagsHorizontalScrollbar
+	// WindowFlagsNoFocusOnAppearing disables taking focus when transitioning from hidden to visible state.
+	WindowFlagsNoFocusOnAppearing WindowFlags = imgui.WindowFlagsNoFocusOnAppearing
+	// WindowFlagsNoBringToFrontOnFocus disables bringing window to front when taking focus. e.g. clicking on it or
+	// programmatically giving it focus.
+	WindowFlagsNoBringToFrontOnFocus WindowFlags = imgui.WindowFlagsNoBringToFrontOnFocus
+	// WindowFlagsAlwaysVerticalScrollbar always shows vertical scrollbar, even if ContentSize.y < Size.y .
+	WindowFlagsAlwaysVerticalScrollbar WindowFlags = imgui.WindowFlagsAlwaysVerticalScrollbar
+	// WindowFlagsAlwaysHorizontalScrollbar always shows horizontal scrollbar, even if ContentSize.x < Size.x .
+	WindowFlagsAlwaysHorizontalScrollbar WindowFlags = imgui.WindowFlagsAlwaysHorizontalScrollbar
+	// WindowFlagsAlwaysUseWindowPadding ensures child windows without border uses style.WindowPadding (ignored by
+	// default for non-bordered child windows, because more convenient).
+	WindowFlagsAlwaysUseWindowPadding WindowFlags = imgui.WindowFlagsAlwaysUseWindowPadding
+	// WindowFlagsNoNavInputs has no gamepad/keyboard navigation within the window.
+	WindowFlagsNoNavInputs WindowFlags = imgui.WindowFlagsNoNavInputs
+	// WindowFlagsNoNavFocus has no focusing toward this window with gamepad/keyboard navigation
+	// (e.g. skipped by CTRL+TAB).
+	WindowFlagsNoNavFocus WindowFlags = imgui.WindowFlagsNoNavFocus
+	// WindowFlagsUnsavedDocument appends '*' to title without affecting the ID, as a convenience to avoid using the
+	// ### operator. When used in a tab/docking context, tab is selected on closure and closure is deferred by one
+	// frame to allow code to cancel the closure (with a confirmation popup, etc.) without flicker.
+	WindowFlagsUnsavedDocument WindowFlags = imgui.WindowFlagsUnsavedDocument
+
+	// WindowFlagsNoNav combines WindowFlagsNoNavInputs and WindowFlagsNoNavFocus.
+	WindowFlagsNoNav WindowFlags = imgui.WindowFlagsNoNav
+	// WindowFlagsNoDecoration combines WindowFlagsNoTitleBar, WindowFlagsNoResize, WindowFlagsNoScrollbar and
+	// WindowFlagsNoCollapse.
+	WindowFlagsNoDecoration WindowFlags = imgui.WindowFlagsNoDecoration
+	// WindowFlagsNoInputs combines WindowFlagsNoMouseInputs, WindowFlagsNoNavInputs and WindowFlagsNoNavFocus.
+	WindowFlagsNoInputs WindowFlags = imgui.WindowFlagsNoInputs
+)
+
+// ComboFlags represents imgui.ComboFlags.
+type ComboFlags int
+
+// combo flags list.
+const (
+	// ComboFlagsNone default = 0.
+	ComboFlagsNone ComboFlags = imgui.ComboFlagsNone
+	// ComboFlagsPopupAlignLeft aligns the popup toward the left by default.
+	ComboFlagsPopupAlignLeft ComboFlags = imgui.ComboFlagsPopupAlignLeft
+	// ComboFlagsHeightSmall has max ~4 items visible.
+	// Tip: If you want your combo popup to be a specific size you can use SetNextWindowSizeConstraints() prior to calling BeginCombo().
+	ComboFlagsHeightSmall ComboFlags = imgui.ComboFlagsHeightSmall
+	// ComboFlagsHeightRegular has max ~8 items visible (default).
+	ComboFlagsHeightRegular ComboFlags = imgui.ComboFlagsHeightRegular
+	// ComboFlagsHeightLarge has max ~20 items visible.
+	ComboFlagsHeightLarge ComboFlags = imgui.ComboFlagsHeightLarge
+	// ComboFlagsHeightLargest has as many fitting items as possible.
+	ComboFlagsHeightLargest ComboFlags = imgui.ComboFlagsHeightLargest
+	// ComboFlagsNoArrowButton displays on the preview box without the square arrow button.
+	ComboFlagsNoArrowButton ComboFlags = imgui.ComboFlagsNoArrowButton
+	// ComboFlagsNoPreview displays only a square arrow button.
+	ComboFlagsNoPreview ComboFlags = imgui.ComboFlagsNoPreview
+)
+
+// SelectableFlags represents imgui.SelectableFlags.
+type SelectableFlags int
+
+// selectable flags list.
+const (
+	// SelectableFlagsNone default = 0.
+	SelectableFlagsNone SelectableFlags = imgui.SelectableFlagsNone
+	// SelectableFlagsDontClosePopups makes clicking the selectable not close any parent popup windows.
+	SelectableFlagsDontClosePopups SelectableFlags = imgui.SelectableFlagsDontClosePopups
+	// SelectableFlagsSpanAllColumns allows the selectable frame to span all columns (text will still fit in current column).
+	SelectableFlagsSpanAllColumns SelectableFlags = imgui.SelectableFlagsSpanAllColumns
+	// SelectableFlagsAllowDoubleClick generates press events on double clicks too.
+	SelectableFlagsAllowDoubleClick SelectableFlags = imgui.SelectableFlagsAllowDoubleClick
+	// SelectableFlagsDisabled disallows selection and displays text in a greyed out color.
+	SelectableFlagsDisabled SelectableFlags = imgui.SelectableFlagsDisabled
+)
+
+// TabItemFlags represents tab item flags.
+type TabItemFlags int
+
+// tab item flags list.
+const (
+	// TabItemFlagsNone default = 0.
+	TabItemFlagsNone TabItemFlags = imgui.TabItemFlagsNone
+	// TabItemFlagsUnsavedDocument Append '*' to title without affecting the ID, as a convenience to avoid using the
+	// ### operator. Also: tab is selected on closure and closure is deferred by one frame to allow code to undo it
+	// without flicker.
+	TabItemFlagsUnsavedDocument TabItemFlags = imgui.TabItemFlagsUnsavedDocument
+	// TabItemFlagsSetSelected Trigger flag to programmatically make the tab selected when calling BeginTabItem().
+	TabItemFlagsSetSelected TabItemFlags = imgui.TabItemFlagsSetSelected
+	// TabItemFlagsNoCloseWithMiddleMouseButton  Disable behavior of closing tabs (that are submitted with
+	// p_open != NULL) with middle mouse button. You can still repro this behavior on user's side with if
+	// (IsItemHovered() && IsMouseClicked(2)) *p_open = false.
+	TabItemFlagsNoCloseWithMiddleMouseButton TabItemFlags = imgui.TabItemFlagsNoCloseWithMiddleMouseButton
+	// TabItemFlagsNoPushID Don't call PushID(tab->ID)/PopID() on BeginTabItem()/EndTabItem().
+	TabItemFlagsNoPushID TabItemFlags = imgui.TabItemFlagsNoPushID
+)
+
+// TabBarFlags represents imgui.TabBarFlags.
+type TabBarFlags int
+
+// tab bar flags list.
+const (
+	// TabBarFlagsNone default = 0.
+	TabBarFlagsNone TabBarFlags = imgui.TabBarFlagsNone
+	// TabBarFlagsReorderable Allow manually dragging tabs to re-order them + New tabs are appended at the end of list.
+	TabBarFlagsReorderable TabBarFlags = imgui.TabBarFlagsReorderable
+	// TabBarFlagsAutoSelectNewTabs Automatically select new tabs when they appear.
+	TabBarFlagsAutoSelectNewTabs TabBarFlags = imgui.TabBarFlagsAutoSelectNewTabs
+	// TabBarFlagsTabListPopupButton Disable buttons to open the tab list popup.
+	TabBarFlagsTabListPopupButton TabBarFlags = imgui.TabBarFlagsTabListPopupButton
+	// TabBarFlagsNoCloseWithMiddleMouseButton Disable behavior of closing tabs (that are submitted with p_open != NULL)
+	// with middle mouse button. You can still repro this behavior on user's side with if
+	// (IsItemHovered() && IsMouseClicked(2)) *p_open = false.
+	TabBarFlagsNoCloseWithMiddleMouseButton TabBarFlags = imgui.TabBarFlagsNoCloseWithMiddleMouseButton
+	// TabBarFlagsNoTabListScrollingButtons Disable scrolling buttons (apply when fitting policy is
+	// TabBarFlagsFittingPolicyScroll).
+	TabBarFlagsNoTabListScrollingButtons TabBarFlags = imgui.TabBarFlagsNoTabListScrollingButtons
+	// TabBarFlagsNoTooltip Disable tooltips when hovering a tab.
+	TabBarFlagsNoTooltip TabBarFlags = imgui.TabBarFlagsNoTooltip
+	// TabBarFlagsFittingPolicyResizeDown Resize tabs when they don't fit.
+	TabBarFlagsFittingPolicyResizeDown TabBarFlags = imgui.TabBarFlagsFittingPolicyResizeDown
+	// TabBarFlagsFittingPolicyScroll Add scroll buttons when tabs don't fit.
+	TabBarFlagsFittingPolicyScroll TabBarFlags = imgui.TabBarFlagsFittingPolicyScroll
+	// TabBarFlagsFittingPolicyMask combines
+	// TabBarFlagsFittingPolicyResizeDown and TabBarFlagsFittingPolicyScroll.
+	TabBarFlagsFittingPolicyMask TabBarFlags = imgui.TabBarFlagsFittingPolicyMask
+	// TabBarFlagsFittingPolicyDefault alias for TabBarFlagsFittingPolicyResizeDown.
+	TabBarFlagsFittingPolicyDefault TabBarFlags = imgui.TabBarFlagsFittingPolicyDefault
+)
+
+// TreeNodeFlags represents tree node widget flags.
+type TreeNodeFlags int
+
+// tree node flags list.
+const (
+	// TreeNodeFlagsNone default = 0.
+	TreeNodeFlagsNone TreeNodeFlags = imgui.TreeNodeFlagsNone
+	// TreeNodeFlagsSelected draws as selected.
+	TreeNodeFlagsSelected TreeNodeFlags = imgui.TreeNodeFlagsSelected
+	// TreeNodeFlagsFramed draws full colored frame (e.g. for CollapsingHeader).
+	TreeNodeFlagsFramed TreeNodeFlags = imgui.TreeNodeFlagsFramed
+	// TreeNodeFlagsAllowItemOverlap hit testing to allow subsequent widgets to overlap this one.
+	TreeNodeFlagsAllowItemOverlap TreeNodeFlags = imgui.TreeNodeFlagsAllowItemOverlap
+	// TreeNodeFlagsNoTreePushOnOpen doesn't do a TreePush() when open
+	// (e.g. for CollapsingHeader) = no extra indent nor pushing on ID stack.
+	TreeNodeFlagsNoTreePushOnOpen TreeNodeFlags = imgui.TreeNodeFlagsNoTreePushOnOpen
+	// TreeNodeFlagsNoAutoOpenOnLog doesn't automatically and temporarily open node when Logging is active
+	// (by default logging will automatically open tree nodes).
+	TreeNodeFlagsNoAutoOpenOnLog TreeNodeFlags = imgui.TreeNodeFlagsNoAutoOpenOnLog
+	// TreeNodeFlagsDefaultOpen defaults node to be open.
+	TreeNodeFlagsDefaultOpen TreeNodeFlags = imgui.TreeNodeFlagsDefaultOpen
+	// TreeNodeFlagsOpenOnDoubleClick needs double-click to open node.
+	TreeNodeFlagsOpenOnDoubleClick TreeNodeFlags = imgui.TreeNodeFlagsOpenOnDoubleClick
+	// TreeNodeFlagsOpenOnArrow opens only when clicking on the arrow part.
+	// If TreeNodeFlagsOpenOnDoubleClick is also set, single-click arrow or double-click all box to open.
+	TreeNodeFlagsOpenOnArrow TreeNodeFlags = imgui.TreeNodeFlagsOpenOnArrow
+	// TreeNodeFlagsLeaf allows no collapsing, no arrow (use as a convenience for leaf nodes).
+	TreeNodeFlagsLeaf TreeNodeFlags = imgui.TreeNodeFlagsLeaf
+	// TreeNodeFlagsBullet displays a bullet instead of an arrow.
+	TreeNodeFlagsBullet TreeNodeFlags = imgui.TreeNodeFlagsBullet
+	// TreeNodeFlagsFramePadding uses FramePadding (even for an unframed text node) to
+	// vertically align text baseline to regular widget height. Equivalent to calling AlignTextToFramePadding().
+	TreeNodeFlagsFramePadding TreeNodeFlags = imgui.TreeNodeFlagsFramePadding
+	// TreeNodeFlagsSpanAvailWidth extends hit box to the right-most edge, even if not framed.
+	// This is not the default in order to allow adding other items on the same line.
+	// In the future we may refactor the hit system to be front-to-back, allowing natural overlaps
+	// and then this can become the default.
+	TreeNodeFlagsSpanAvailWidth TreeNodeFlags = imgui.TreeNodeFlagsSpanAvailWidth
+	// TreeNodeFlagsSpanFullWidth extends hit box to the left-most and right-most edges (bypass the indented area).
+	TreeNodeFlagsSpanFullWidth TreeNodeFlags = imgui.TreeNodeFlagsSpanFullWidth
+	// TreeNodeFlagsNavLeftJumpsBackHere (WIP) Nav: left direction may move to this TreeNode() from any of its child
+	// (items submitted between TreeNode and TreePop).
+	TreeNodeFlagsNavLeftJumpsBackHere TreeNodeFlags = imgui.TreeNodeFlagsNavLeftJumpsBackHere
+	// TreeNodeFlagsCollapsingHeader combines TreeNodeFlagsFramed and TreeNodeFlagsNoAutoOpenOnLog.
+	TreeNodeFlagsCollapsingHeader TreeNodeFlags = imgui.TreeNodeFlagsCollapsingHeader
+)
+
+// FocusedFlags represents imgui.FocusedFlags.
+type FocusedFlags int
+
+// focused flags list.
+const (
+	FocusedFlagsNone             = imgui.FocusedFlagsNone
+	FocusedFlagsChildWindows     = imgui.FocusedFlagsChildWindows     // Return true if any children of the window is focused
+	FocusedFlagsRootWindow       = imgui.FocusedFlagsRootWindow       // Test from root window (top most parent of the current hierarchy)
+	FocusedFlagsAnyWindow        = imgui.FocusedFlagsAnyWindow        // Return true if any window is focused. Important: If you are trying to tell how to dispatch your low-level inputs do NOT use this. Use 'io.WantCaptureMouse' instead! Please read the FAQ!
+	FocusedFlagsNoPopupHierarchy = imgui.FocusedFlagsNoPopupHierarchy // Do not consider popup hierarchy (do not treat popup emitter as parent of popup) (when used with ChildWindows or RootWindow)
+	// FocusedFlagsDockHierarchy               = 1 << 4   // Consider docking hierarchy (treat dockspace host as parent of docked window) (when used with ChildWindows or RootWindow).
+	FocusedFlagsRootAndChildWindows = imgui.FocusedFlagsRootAndChildWindows
+)
+
+// HoveredFlags represents a hovered flags.
+type HoveredFlags int
+
+// hovered flags list.
+const (
+	// HoveredFlagsNone Return true if directly over the item/window, not obstructed by another window,
+	// not obstructed by an active popup or modal blocking inputs under them.
+	HoveredFlagsNone HoveredFlags = imgui.HoveredFlagsNone
+	// HoveredFlagsChildWindows IsWindowHovered() only: Return true if any children of the window is hovered.
+	HoveredFlagsChildWindows HoveredFlags = imgui.HoveredFlagsChildWindows
+	// HoveredFlagsRootWindow IsWindowHovered() only: Test from root window (top most parent of the current hierarchy).
+	HoveredFlagsRootWindow HoveredFlags = imgui.HoveredFlagsRootWindow
+	// HoveredFlagsAnyWindow IsWindowHovered() only: Return true if any window is hovered.
+	HoveredFlagsAnyWindow HoveredFlags = imgui.HoveredFlagsAnyWindow
+	// HoveredFlagsAllowWhenBlockedByPopup Return true even if a popup window is normally blocking access to this item/window.
+	HoveredFlagsAllowWhenBlockedByPopup HoveredFlags = imgui.HoveredFlagsAllowWhenBlockedByPopup
+	// HoveredFlagsAllowWhenBlockedByActiveItem Return true even if an active item is blocking access to this item/window.
+	// Useful for Drag and Drop patterns.
+	HoveredFlagsAllowWhenBlockedByActiveItem HoveredFlags = imgui.HoveredFlagsAllowWhenBlockedByActiveItem
+	// HoveredFlagsAllowWhenOverlapped Return true even if the position is overlapped by another window.
+	HoveredFlagsAllowWhenOverlapped HoveredFlags = imgui.HoveredFlagsAllowWhenOverlapped
+	// HoveredFlagsAllowWhenDisabled Return true even if the item is disabled.
+	HoveredFlagsAllowWhenDisabled HoveredFlags = imgui.HoveredFlagsAllowWhenDisabled
+)
+
+// ColorEditFlags for ColorEdit3V(), etc.
+type ColorEditFlags int
+
+// list of color edit flags.
+const (
+	// ColorEditFlagsNone default = 0.
+	ColorEditFlagsNone ColorEditFlags = imgui.ColorEditFlagsNone
+	// ColorEditFlagsNoAlpha ignores Alpha component (read 3 components from the input pointer).
+	ColorEditFlagsNoAlpha ColorEditFlags = imgui.ColorEditFlagsNoAlpha
+	// ColorEditFlagsNoPicker disables picker when clicking on colored square.
+	ColorEditFlagsNoPicker ColorEditFlags = imgui.ColorEditFlagsNoPicker
+	// ColorEditFlagsNoOptions disables toggling options menu when right-clicking on inputs/small preview.
+	ColorEditFlagsNoOptions ColorEditFlags = imgui.ColorEditFlagsNoOptions
+	// ColorEditFlagsNoSmallPreview disables colored square preview next to the inputs. (e.g. to show only the inputs).
+	ColorEditFlagsNoSmallPreview ColorEditFlags = imgui.ColorEditFlagsNoSmallPreview
+	// ColorEditFlagsNoInputs disables inputs sliders/text widgets (e.g. to show only the small preview colored square).
+	ColorEditFlagsNoInputs ColorEditFlags = imgui.ColorEditFlagsNoInputs
+	// ColorEditFlagsNoTooltip disables tooltip when hovering the preview.
+	ColorEditFlagsNoTooltip ColorEditFlags = imgui.ColorEditFlagsNoTooltip
+	// ColorEditFlagsNoLabel disables display of inline text label (the label is still forwarded to the tooltip and picker).
+	ColorEditFlagsNoLabel ColorEditFlags = imgui.ColorEditFlagsNoLabel
+	// ColorEditFlagsNoDragDrop disables drag and drop target. ColorButton: disable drag and drop source.
+	ColorEditFlagsNoDragDrop ColorEditFlags = imgui.ColorEditFlagsNoDragDrop
+
+	// User Options (right-click on widget to change some of them). You can set application defaults using SetColorEditOptions().
+	// The idea is that you probably don't want to override them in most of your calls, let the user choose and/or call SetColorEditOptions()
+	// during startup.
+
+	// ColorEditFlagsAlphaBar shows vertical alpha bar/gradient in picker.
+	ColorEditFlagsAlphaBar ColorEditFlags = imgui.ColorEditFlagsAlphaBar
+	// ColorEditFlagsAlphaPreview displays preview as a transparent color over a checkerboard, instead of opaque.
+	ColorEditFlagsAlphaPreview ColorEditFlags = imgui.ColorEditFlagsAlphaPreview
+	// ColorEditFlagsAlphaPreviewHalf displays half opaque / half checkerboard, instead of opaque.
+	ColorEditFlagsAlphaPreviewHalf ColorEditFlags = imgui.ColorEditFlagsAlphaPreviewHalf
+	// ColorEditFlagsHDR = (WIP) surrently only disable 0.0f..1.0f limits in RGBA edition (note: you probably want to use
+	// ImGuiColorEditFlags_Float flag as well).
+	ColorEditFlagsHDR ColorEditFlags = imgui.ColorEditFlagsHDR
+	// ColorEditFlagsRGB sets the format as RGB.
+	ColorEditFlagsRGB ColorEditFlags = imgui.ColorEditFlagsRGB
+	// ColorEditFlagsHSV sets the format as HSV.
+	ColorEditFlagsHSV ColorEditFlags = imgui.ColorEditFlagsHSV
+	// ColorEditFlagsHEX sets the format as HEX.
+	ColorEditFlagsHEX ColorEditFlags = imgui.ColorEditFlagsHEX
+	// ColorEditFlagsUint8 _display_ values formatted as 0..255.
+	ColorEditFlagsUint8 ColorEditFlags = imgui.ColorEditFlagsUint8
+	// ColorEditFlagsFloat _display_ values formatted as 0.0f..1.0f floats instead of 0..255 integers. No round-trip of value via integers.
+	ColorEditFlagsFloat ColorEditFlags = imgui.ColorEditFlagsFloat
+)
+
+// TableFlags represents table flags.
+type TableFlags int
+
+// Table flags enum:.
+const (
+	TableFlagsNone                       TableFlags = TableFlags(imgui.TableFlags_None)
+	TableFlagsResizable                  TableFlags = TableFlags(imgui.TableFlags_Resizable)
+	TableFlagsReorderable                TableFlags = TableFlags(imgui.TableFlags_Reorderable)
+	TableFlagsHideable                   TableFlags = TableFlags(imgui.TableFlags_Hideable)
+	TableFlagsSortable                   TableFlags = TableFlags(imgui.TableFlags_Sortable)
+	TableFlagsNoSavedSettings            TableFlags = TableFlags(imgui.TableFlags_NoSavedSettings)
+	TableFlagsContextMenuInBody          TableFlags = TableFlags(imgui.TableFlags_ContextMenuInBody)
+	TableFlagsRowBg                      TableFlags = TableFlags(imgui.TableFlags_RowBg)
+	TableFlagsBordersInnerH              TableFlags = TableFlags(imgui.TableFlags_BordersInnerH)
+	TableFlagsBordersOuterH              TableFlags = TableFlags(imgui.TableFlags_BordersOuterH)
+	TableFlagsBordersInnerV              TableFlags = TableFlags(imgui.TableFlags_BordersInnerV)
+	TableFlagsBordersOuterV              TableFlags = TableFlags(imgui.TableFlags_BordersOuterV)
+	TableFlagsBordersH                   TableFlags = TableFlags(imgui.TableFlags_BordersH)
+	TableFlagsBordersV                   TableFlags = TableFlags(imgui.TableFlags_BordersV)
+	TableFlagsBordersInner               TableFlags = TableFlags(imgui.TableFlags_BordersInner)
+	TableFlagsBordersOuter               TableFlags = TableFlags(imgui.TableFlags_BordersOuter)
+	TableFlagsBorders                    TableFlags = TableFlags(imgui.TableFlags_Borders)
+	TableFlagsNoBordersInBody            TableFlags = TableFlags(imgui.TableFlags_NoBordersInBody)
+	TableFlagsNoBordersInBodyUntilResize TableFlags = TableFlags(imgui.TableFlags_NoBordersInBodyUntilResizeTableFlags)
+	TableFlagsSizingFixedFit             TableFlags = TableFlags(imgui.TableFlags_SizingFixedFit)
+	TableFlagsSizingFixedSame            TableFlags = TableFlags(imgui.TableFlags_SizingFixedSame)
+	TableFlagsSizingStretchProp          TableFlags = TableFlags(imgui.TableFlags_SizingStretchProp)
+	TableFlagsSizingStretchSame          TableFlags = TableFlags(imgui.TableFlags_SizingStretchSame)
+	TableFlagsNoHostExtendX              TableFlags = TableFlags(imgui.TableFlags_NoHostExtendX)
+	TableFlagsNoHostExtendY              TableFlags = TableFlags(imgui.TableFlags_NoHostExtendY)
+	TableFlagsNoKeepColumnsVisible       TableFlags = TableFlags(imgui.TableFlags_NoKeepColumnsVisible)
+	TableFlagsPreciseWidths              TableFlags = TableFlags(imgui.TableFlags_PreciseWidths)
+	TableFlagsNoClip                     TableFlags = TableFlags(imgui.TableFlags_NoClip)
+	TableFlagsPadOuterX                  TableFlags = TableFlags(imgui.TableFlags_PadOuterX)
+	TableFlagsNoPadOuterX                TableFlags = TableFlags(imgui.TableFlags_NoPadOuterX)
+	TableFlagsNoPadInnerX                TableFlags = TableFlags(imgui.TableFlags_NoPadInnerX)
+	TableFlagsScrollX                    TableFlags = TableFlags(imgui.TableFlags_ScrollX)
+	TableFlagsScrollY                    TableFlags = TableFlags(imgui.TableFlags_ScrollY)
+	TableFlagsSortMulti                  TableFlags = TableFlags(imgui.TableFlags_SortMulti)
+	TableFlagsSortTristate               TableFlags = TableFlags(imgui.TableFlags_SortTristate)
+	TableFlagsSizingMask                 TableFlags = TableFlags(imgui.TableFlags_SizingMask_)
+)
+
+// TableRowFlags represents table row flags.
+type TableRowFlags int
+
+// table row flags:.
+const (
+	TableRowFlagsNone TableRowFlags = TableRowFlags(imgui.TableRowFlags_None)
+	// Identify header row (set default background color + width of its contents accounted different for auto column width).
+	TableRowFlagsHeaders TableRowFlags = TableRowFlags(imgui.TableRowFlags_Headers)
+)
+
+// TableColumnFlags represents a flags for table column (see (*TableColumnWidget).Flags()).
+type TableColumnFlags int
+
+// table column flags list.
+const (
+	// Input configuration flags.
+	TableColumnFlagsNone                 TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_None)
+	TableColumnFlagsDefaultHide          TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_DefaultHide)
+	TableColumnFlagsDefaultSort          TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_DefaultSort)
+	TableColumnFlagsWidthStretch         TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_WidthStretch)
+	TableColumnFlagsWidthFixed           TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_WidthFixed)
+	TableColumnFlagsNoResize             TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_NoResize)
+	TableColumnFlagsNoReorder            TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_NoReorder)
+	TableColumnFlagsNoHide               TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_NoHide)
+	TableColumnFlagsNoClip               TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_NoClip)
+	TableColumnFlagsNoSort               TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_NoSort)
+	TableColumnFlagsNoSortAscending      TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_NoSortAscending)
+	TableColumnFlagsNoSortDescending     TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_NoSortDescending)
+	TableColumnFlagsNoHeaderWidth        TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_NoHeaderWidth)
+	TableColumnFlagsPreferSortAscending  TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_PreferSortAscending)
+	TableColumnFlagsPreferSortDescending TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_PreferSortDescending)
+	TableColumnFlagsIndentEnable         TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_IndentEnable)
+	TableColumnFlagsIndentDisable        TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_IndentDisable)
+
+	// Output status flags read-only via TableGetColumnFlags().
+	TableColumnFlagsIsEnabled TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_IsEnabled)
+	TableColumnFlagsIsVisible TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_IsVisible)
+	TableColumnFlagsIsSorted  TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_IsSorted)
+	TableColumnFlagsIsHovered TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_IsHovered)
+
+	// [Internal] Combinations and masks.
+	TableColumnFlagsWidthMask      TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_WidthMask_)
+	TableColumnFlagsIndentMask     TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_IndentMask_)
+	TableColumnFlagsStatusMask     TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_StatusMask_)
+	TableColumnFlagsNoDirectResize TableColumnFlags = TableColumnFlags(imgui.TableColumnFlags_NoDirectResize_)
+)
+
+// SliderFlags represents imgui.SliderFlags
+// TODO: Hard-reffer to these constants.
+type SliderFlags int
+
+// slider flags.
+const (
+	SliderFlagsNone SliderFlags = 0
+	// Clamp value to min/max bounds when input manually with CTRL+Click. By default CTRL+Click allows going out of bounds.
+	SliderFlagsAlwaysClamp SliderFlags = 1 << 4
+	// Make the widget logarithmic (linear otherwise). Consider using ImGuiSliderFlagsNoRoundToFormat with this if using
+	// a format-string with small amount of digits.
+	SliderFlagsLogarithmic SliderFlags = 1 << 5
+	// Disable rounding underlying value to match precision of the display format string (e.g. %.3f values are rounded to those 3 digits).
+	SliderFlagsNoRoundToFormat SliderFlags = 1 << 6
+	// Disable CTRL+Click or Enter key allowing to input text directly into the widget.
+	SliderFlagsNoInput SliderFlags = 1 << 7
+	// [Internal] We treat using those bits as being potentially a 'float power' argument from the previous API that has got miscast
+	// to this enum, and will trigger an assert if needed.
+	SliderFlagsInvalidMask SliderFlags = 0x7000000F
+)
+
+// PlotFlags represents imgui.ImPlotFlags.
+type PlotFlags int
+
+// plot flags.
+const (
+	PlotFlagsNone        = PlotFlags(imgui.ImPlotFlags_None)
+	PlotFlagsNoTitle     = PlotFlags(imgui.ImPlotFlags_NoTitle)
+	PlotFlagsNoLegend    = PlotFlags(imgui.ImPlotFlags_NoLegend)
+	PlotFlagsNoMenus     = PlotFlags(imgui.ImPlotFlags_NoMenus)
+	PlotFlagsNoBoxSelect = PlotFlags(imgui.ImPlotFlags_NoBoxSelect)
+	PlotFlagsNoMousePos  = PlotFlags(imgui.ImPlotFlags_NoMousePos)
+	PlotFlagsNoHighlight = PlotFlags(imgui.ImPlotFlags_NoHighlight)
+	PlotFlagsNoChild     = PlotFlags(imgui.ImPlotFlags_NoChild)
+	PlotFlagsEqual       = PlotFlags(imgui.ImPlotFlags_Equal)
+	PlotFlagsYAxis2      = PlotFlags(imgui.ImPlotFlags_YAxis2)
+	PlotFlagsYAxis3      = PlotFlags(imgui.ImPlotFlags_YAxis3)
+	PlotFlagsQuery       = PlotFlags(imgui.ImPlotFlags_Query)
+	PlotFlagsCrosshairs  = PlotFlags(imgui.ImPlotFlags_Crosshairs)
+	PlotFlagsAntiAliased = PlotFlags(imgui.ImPlotFlags_AntiAliased)
+	PlotFlagsCanvasOnly  = PlotFlags(imgui.ImPlotFlags_CanvasOnly)
+)
+
+// PlotAxisFlags represents imgui.ImPlotAxisFlags.
+type PlotAxisFlags int
+
+// plot axis flags.
+const (
+	PlotAxisFlagsNone          PlotAxisFlags = PlotAxisFlags(imgui.ImPlotAxisFlags_None)
+	PlotAxisFlagsNoLabel       PlotAxisFlags = PlotAxisFlags(imgui.ImPlotAxisFlags_NoLabel)
+	PlotAxisFlagsNoGridLines   PlotAxisFlags = PlotAxisFlags(imgui.ImPlotAxisFlags_NoGridLines)
+	PlotAxisFlagsNoTickMarks   PlotAxisFlags = PlotAxisFlags(imgui.ImPlotAxisFlags_NoTickMarks)
+	PlotAxisFlagsNoTickLabels  PlotAxisFlags = PlotAxisFlags(imgui.ImPlotAxisFlags_NoTickLabels)
+	PlotAxisFlagsForeground    PlotAxisFlags = PlotAxisFlags(imgui.ImPlotAxisFlags_Foreground)
+	PlotAxisFlagsLogScale      PlotAxisFlags = PlotAxisFlags(imgui.ImPlotAxisFlags_LogScale)
+	PlotAxisFlagsTime          PlotAxisFlags = PlotAxisFlags(imgui.ImPlotAxisFlags_Time)
+	PlotAxisFlagsInvert        PlotAxisFlags = PlotAxisFlags(imgui.ImPlotAxisFlags_Invert)
+	PlotAxisFlagsNoInitialFit  PlotAxisFlags = PlotAxisFlags(imgui.ImPlotAxisFlags_NoInitialFit)
+	PlotAxisFlagsAutoFit       PlotAxisFlags = PlotAxisFlags(imgui.ImPlotAxisFlags_AutoFit)
+	PlotAxisFlagsRangeFit      PlotAxisFlags = PlotAxisFlags(imgui.ImPlotAxisFlags_RangeFit)
+	PlotAxisFlagsLockMin       PlotAxisFlags = PlotAxisFlags(imgui.ImPlotAxisFlags_LockMin)
+	PlotAxisFlagsLockMax       PlotAxisFlags = PlotAxisFlags(imgui.ImPlotAxisFlags_LockMax)
+	PlotAxisFlagsLock          PlotAxisFlags = PlotAxisFlags(imgui.ImPlotAxisFlags_Lock)
+	PlotAxisFlagsNoDecorations PlotAxisFlags = PlotAxisFlags(imgui.ImPlotAxisFlags_NoDecorations)
+)

+ 304 - 0
vendor/github.com/AllenDang/giu/FontAtlasProsessor.go

@@ -0,0 +1,304 @@
+package giu
+
+import (
+	"fmt"
+	"log"
+	"runtime"
+	"strings"
+	"sync"
+
+	"github.com/AllenDang/go-findfont"
+	"github.com/AllenDang/imgui-go"
+)
+
+var (
+	shouldRebuildFontAtlas bool
+	defaultFontSize        float32  = 14
+	stringMap              sync.Map // key is rune, value indicates whether it's a new rune.
+	defaultFonts           []FontInfo
+	extraFonts             []FontInfo
+	extraFontMap           map[string]*imgui.Font
+)
+
+const (
+	preRegisterString = " \"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
+	windows           = "windows"
+)
+
+// FontInfo represents a giu implementation of imgui font.
+type FontInfo struct {
+	fontName string
+	fontPath string
+	fontByte []byte
+	size     float32
+}
+
+func (f *FontInfo) String() string {
+	return fmt.Sprintf("%s:%.2f", f.fontName, f.size)
+}
+
+func (f *FontInfo) SetSize(size float32) *FontInfo {
+	result := *f
+	result.size = size
+
+	for _, i := range extraFonts {
+		if i.String() == result.String() {
+			return &result
+		}
+	}
+
+	extraFonts = append(extraFonts, result)
+	shouldRebuildFontAtlas = true
+
+	return &result
+}
+
+func initFontAtlasProcessor() {
+	extraFontMap = make(map[string]*imgui.Font)
+
+	// Pre register numbers
+	tStr(preRegisterString)
+
+	// Pre-register fonts
+	os := runtime.GOOS
+	switch os {
+	case "darwin":
+		// English font
+		registerDefaultFont("Menlo", defaultFontSize)
+		// Chinese font
+		registerDefaultFont("STHeiti", defaultFontSize-1)
+		// Jananese font
+		registerDefaultFont("ヒラギノ角ゴシック W0", defaultFontSize+3)
+		// Korean font
+		registerDefaultFont("AppleSDGothicNeo", defaultFontSize+2)
+	case windows:
+		// English font
+		registerDefaultFont("Calibri", defaultFontSize+2)
+		// Chinese font
+		registerDefaultFont("MSYH", defaultFontSize+2)
+		// Japanese font
+		registerDefaultFont("MSGOTHIC", defaultFontSize+2)
+		// Korean font
+		registerDefaultFont("MALGUNSL", defaultFontSize+2)
+	case "linux":
+		// English fonts
+		registerDefaultFonts([]FontInfo{
+			{
+				fontName: "FreeSans.ttf",
+				size:     defaultFontSize + 1,
+			},
+			{
+				fontName: "FiraCode-Medium",
+				size:     defaultFontSize + 1,
+			},
+			{
+				fontName: "sans",
+				size:     defaultFontSize + 1,
+			},
+		})
+	}
+}
+
+// SetDefaultFontSize sets the default font size. Invoke this before MasterWindow.NewMasterWindow(..).
+func SetDefaultFontSize(size float32) {
+	defaultFontSize = size
+}
+
+// SetDefaultFont changes default font.
+func SetDefaultFont(fontName string, size float32) {
+	fontPath, err := findfont.Find(fontName)
+	if err != nil {
+		log.Fatalf("Cannot find font %s", fontName)
+		return
+	}
+
+	fontInfo := FontInfo{fontName: fontName, fontPath: fontPath, size: size}
+	defaultFonts = append([]FontInfo{fontInfo}, defaultFonts...)
+}
+
+// SetDefaultFontFromBytes changes default font by bytes of the font file.
+func SetDefaultFontFromBytes(fontBytes []byte, size float32) {
+	defaultFonts = append([]FontInfo{
+		{
+			fontByte: fontBytes,
+			size:     size,
+		},
+	}, defaultFonts...)
+}
+
+func GetDefaultFonts() []FontInfo {
+	return defaultFonts
+}
+
+// AddFont adds font by name, if the font is found, return *FontInfo, otherwise return nil.
+// To use added font, use giu.Style().SetFont(...).
+func AddFont(fontName string, size float32) *FontInfo {
+	fontPath, err := findfont.Find(fontName)
+	if err != nil {
+		fmt.Printf("[Warning]Cannot find font %s at system, related text will not be rendered.\n", fontName)
+		return nil
+	}
+
+	fi := FontInfo{
+		fontName: fontName,
+		fontPath: fontPath,
+		size:     size,
+	}
+
+	extraFonts = append(extraFonts, fi)
+
+	return &fi
+}
+
+// AddFontFromBytes does similar to AddFont, but using data from memory.
+func AddFontFromBytes(fontName string, fontBytes []byte, size float32) *FontInfo {
+	fi := FontInfo{
+		fontName: fontName,
+		fontByte: fontBytes,
+		size:     size,
+	}
+
+	extraFonts = append(extraFonts, fi)
+
+	return &fi
+}
+
+func registerDefaultFont(fontName string, size float32) {
+	fontPath, err := findfont.Find(fontName)
+	if err != nil {
+		return
+	}
+
+	fontInfo := FontInfo{fontName: fontName, fontPath: fontPath, size: size}
+	defaultFonts = append(defaultFonts, fontInfo)
+}
+
+func registerDefaultFonts(fontInfos []FontInfo) {
+	var firstFoundFont *FontInfo
+	for _, fi := range fontInfos {
+		fontPath, err := findfont.Find(fi.fontName)
+		if err == nil {
+			firstFoundFont = &FontInfo{fontName: fi.fontName, fontPath: fontPath, size: fi.size}
+			break
+		}
+	}
+
+	if firstFoundFont != nil {
+		defaultFonts = append(defaultFonts, *firstFoundFont)
+	}
+}
+
+// Register string to font atlas builder.
+// Note only register strings that will be displayed on the UI.
+func tStr(str string) string {
+	for _, s := range str {
+		if _, ok := stringMap.Load(s); !ok {
+			stringMap.Store(s, false)
+			shouldRebuildFontAtlas = true
+		}
+	}
+
+	return str
+}
+
+// Register string pointer to font atlas builder.
+// Note only register strings that will be displayed on the UI.
+func tStrPtr(str *string) *string {
+	tStr(*str)
+	return str
+}
+
+func tStrSlice(str []string) []string {
+	for _, s := range str {
+		tStr(s)
+	}
+
+	return str
+}
+
+// Rebuild font atlas when necessary.
+func rebuildFontAtlas() {
+	if !shouldRebuildFontAtlas {
+		return
+	}
+
+	fonts := Context.IO().Fonts()
+	fonts.Clear()
+
+	var sb strings.Builder
+
+	stringMap.Range(func(k, v any) bool {
+		stringMap.Store(k, true)
+		if ks, ok := k.(rune); ok {
+			sb.WriteRune(ks)
+		}
+
+		return true
+	})
+
+	ranges := imgui.NewGlyphRanges()
+	builder := imgui.NewFontGlyphRangesBuilder()
+
+	// Because we pre-regestered numbers, so default string map's length should greater then 11.
+	if sb.Len() > len(preRegisterString) {
+		builder.AddText(sb.String())
+	} else {
+		builder.AddRanges(fonts.GlyphRangesDefault())
+	}
+
+	builder.BuildRanges(ranges)
+
+	if len(defaultFonts) > 0 {
+		fontConfig := imgui.NewFontConfig()
+		fontConfig.SetOversampleH(2)
+		fontConfig.SetOversampleV(2)
+		fontConfig.SetRasterizerMultiply(1.5)
+
+		for i, fontInfo := range defaultFonts {
+			if i > 0 {
+				fontConfig.SetMergeMode(true)
+			}
+
+			// Scale font size with DPI scale factor
+			if runtime.GOOS == windows {
+				fontInfo.size *= Context.GetPlatform().GetContentScale()
+			}
+
+			if len(fontInfo.fontByte) == 0 {
+				fonts.AddFontFromFileTTFV(fontInfo.fontPath, fontInfo.size, fontConfig, ranges.Data())
+			} else {
+				fonts.AddFontFromMemoryTTFV(fontInfo.fontByte, fontInfo.size, fontConfig, ranges.Data())
+			}
+		}
+
+		// Fall back if no font is added
+		if fonts.GetFontCount() == 0 {
+			fonts.AddFontDefault()
+		}
+	} else {
+		fonts.AddFontDefault()
+	}
+
+	// Add extra fonts
+	for _, fontInfo := range extraFonts {
+		// Scale font size with DPI scale factor
+		if runtime.GOOS == windows {
+			fontInfo.size *= Context.GetPlatform().GetContentScale()
+		}
+
+		// Store imgui.Font for PushFont
+		var f imgui.Font
+		if len(fontInfo.fontByte) == 0 {
+			f = fonts.AddFontFromFileTTFV(fontInfo.fontPath, fontInfo.size, imgui.DefaultFontConfig, ranges.Data())
+		} else {
+			f = fonts.AddFontFromMemoryTTFV(fontInfo.fontByte, fontInfo.size, imgui.DefaultFontConfig, ranges.Data())
+		}
+
+		extraFontMap[fontInfo.String()] = &f
+	}
+
+	fontTextureImg := fonts.TextureDataRGBA32()
+	Context.renderer.SetFontTexture(fontTextureImg)
+
+	shouldRebuildFontAtlas = false
+}

+ 379 - 0
vendor/github.com/AllenDang/giu/ImageWidgets.go

@@ -0,0 +1,379 @@
+package giu
+
+import (
+	ctx "context"
+	"fmt"
+	"image"
+	"image/color"
+	"net/http"
+	"time"
+
+	"github.com/AllenDang/imgui-go"
+)
+
+var _ Widget = &ImageWidget{}
+
+// ImageWidget adds an image.
+// NOTE: ImageWidget is going to be deprecated. ImageWithRGBAWidget
+// should be used instead, however, because it is a native
+// imgui's solution it is still there.
+type ImageWidget struct {
+	texture                *Texture
+	width                  float32
+	height                 float32
+	uv0, uv1               image.Point
+	tintColor, borderColor color.Color
+	onClick                func()
+}
+
+// Image adds an image from giu.Texture.
+func Image(texture *Texture) *ImageWidget {
+	return &ImageWidget{
+		texture:     texture,
+		width:       100,
+		height:      100,
+		uv0:         image.Point{X: 0, Y: 0},
+		uv1:         image.Point{X: 1, Y: 1},
+		tintColor:   color.RGBA{255, 255, 255, 255},
+		borderColor: color.RGBA{0, 0, 0, 0},
+	}
+}
+
+// Uv allows to specify uv parameters.
+func (i *ImageWidget) Uv(uv0, uv1 image.Point) *ImageWidget {
+	i.uv0, i.uv1 = uv0, uv1
+	return i
+}
+
+// TintColor sets image's tint color.
+func (i *ImageWidget) TintColor(tintColor color.Color) *ImageWidget {
+	i.tintColor = tintColor
+	return i
+}
+
+// BorderCol sets color of the border.
+func (i *ImageWidget) BorderCol(borderColor color.Color) *ImageWidget {
+	i.borderColor = borderColor
+	return i
+}
+
+// OnClick adds on-click-callback.
+func (i *ImageWidget) OnClick(cb func()) *ImageWidget {
+	i.onClick = cb
+	return i
+}
+
+// Size sets image size.
+func (i *ImageWidget) Size(width, height float32) *ImageWidget {
+	// Size image with DPI scaling
+	factor := Context.GetPlatform().GetContentScale()
+	i.width, i.height = width*factor, height*factor
+	return i
+}
+
+// Build implements Widget interface.
+func (i *ImageWidget) Build() {
+	size := imgui.Vec2{X: i.width, Y: i.height}
+	rect := imgui.ContentRegionAvail()
+	if size.X == -1 {
+		size.X = rect.X
+	}
+	if size.Y == -1 {
+		size.Y = rect.Y
+	}
+
+	if i.texture == nil || i.texture.id == 0 {
+		Dummy(size.X, size.Y).Build()
+		return
+	}
+
+	// trick: detect click event
+	if i.onClick != nil && IsMouseClicked(MouseButtonLeft) {
+		cursorPos := GetCursorScreenPos()
+		mousePos := GetMousePos()
+		mousePos.Add(cursorPos)
+		if cursorPos.X <= mousePos.X && cursorPos.Y <= mousePos.Y &&
+			cursorPos.X+int(i.width) >= mousePos.X && cursorPos.Y+int(i.height) >= mousePos.Y {
+			i.onClick()
+		}
+	}
+
+	imgui.ImageV(i.texture.id, size, ToVec2(i.uv0), ToVec2(i.uv1), ToVec4Color(i.tintColor), ToVec4Color(i.borderColor))
+}
+
+type imageState struct {
+	loading bool
+	failure bool
+	cancel  ctx.CancelFunc
+	texture *Texture
+}
+
+// Dispose cleans imageState (implements Disposable interface).
+func (is *imageState) Dispose() {
+	is.texture = nil
+	// Cancel ongoing image downloaidng
+	if is.loading && is.cancel != nil {
+		is.cancel()
+	}
+}
+
+var _ Widget = &ImageWithRgbaWidget{}
+
+// ImageWithRgbaWidget wrapps ImageWidget.
+// It is more useful because it doesn't make you to care about
+// imgui textures. You can just pass golang-native image.Image and
+// display it in giu.
+type ImageWithRgbaWidget struct {
+	id   string
+	rgba image.Image
+	img  *ImageWidget
+}
+
+// ImageWithRgba creates ImageWithRgbaWidget.
+func ImageWithRgba(rgba image.Image) *ImageWithRgbaWidget {
+	return &ImageWithRgbaWidget{
+		id:   GenAutoID("ImageWithRgba"),
+		rgba: rgba,
+		img:  Image(nil),
+	}
+}
+
+// Size sets image's size.
+func (i *ImageWithRgbaWidget) Size(width, height float32) *ImageWithRgbaWidget {
+	i.img.Size(width, height)
+	return i
+}
+
+// OnClick sets click callback.
+func (i *ImageWithRgbaWidget) OnClick(cb func()) *ImageWithRgbaWidget {
+	i.img.OnClick(cb)
+	return i
+}
+
+// Build implements Widget interface.
+func (i *ImageWithRgbaWidget) Build() {
+	if i.rgba != nil {
+		var imgState *imageState
+		if state := Context.GetState(i.id); state == nil {
+			imgState = &imageState{}
+			Context.SetState(i.id, imgState)
+
+			NewTextureFromRgba(i.rgba, func(tex *Texture) {
+				imgState.texture = tex
+			})
+		} else {
+			var isOk bool
+			imgState, isOk = state.(*imageState)
+			Assert(isOk, "ImageWithRgbaWidget", "Build", "unexpected type of widget's state recovered")
+		}
+
+		i.img.texture = imgState.texture
+	}
+
+	i.img.Build()
+}
+
+var _ Widget = &ImageWithFileWidget{}
+
+// ImageWithFileWidget allows to display an image directly
+// from .png file.
+// NOTE: Be aware that project using this solution may not be portable
+// because files are not included in executable binaries!
+// You may want to use "embed" package and ImageWithRgba instead.
+type ImageWithFileWidget struct {
+	id      string
+	imgPath string
+	img     *ImageWidget
+}
+
+// ImageWithFile constructs a new ImageWithFileWidget.
+func ImageWithFile(imgPath string) *ImageWithFileWidget {
+	return &ImageWithFileWidget{
+		id:      fmt.Sprintf("ImageWithFile_%s", imgPath),
+		imgPath: imgPath,
+		img:     Image(nil),
+	}
+}
+
+// Size sets image's size.
+func (i *ImageWithFileWidget) Size(width, height float32) *ImageWithFileWidget {
+	i.img.Size(width, height)
+	return i
+}
+
+// OnClick sets click callback.
+func (i *ImageWithFileWidget) OnClick(cb func()) *ImageWithFileWidget {
+	i.img.OnClick(cb)
+	return i
+}
+
+// Build implements Widget interface.
+func (i *ImageWithFileWidget) Build() {
+	imgState := &imageState{}
+	if state := Context.GetState(i.id); state == nil {
+		// Prevent multiple invocation to LoadImage.
+		Context.SetState(i.id, imgState)
+
+		img, err := LoadImage(i.imgPath)
+		if err == nil {
+			NewTextureFromRgba(img, func(tex *Texture) {
+				imgState.texture = tex
+			})
+		}
+	} else {
+		var isOk bool
+		imgState, isOk = state.(*imageState)
+		Assert(isOk, "ImageWithFileWidget", "Build", "wrong type of widget's state got")
+	}
+
+	i.img.texture = imgState.texture
+	i.img.Build()
+}
+
+var _ Widget = &ImageWithURLWidget{}
+
+// ImageWithURLWidget allows to display an image using
+// an URL as image source.
+type ImageWithURLWidget struct {
+	id              string
+	imgURL          string
+	downloadTimeout time.Duration
+	whenLoading     Layout
+	whenFailure     Layout
+	onReady         func()
+	onFailure       func(error)
+	img             *ImageWidget
+}
+
+// ImageWithURL creates ImageWithURLWidget.
+func ImageWithURL(url string) *ImageWithURLWidget {
+	return &ImageWithURLWidget{
+		id:              fmt.Sprintf("ImageWithURL_%s", url),
+		imgURL:          url,
+		downloadTimeout: 10 * time.Second,
+		whenLoading:     Layout{Dummy(100, 100)},
+		whenFailure:     Layout{Dummy(100, 100)},
+		img:             Image(nil),
+	}
+}
+
+// OnReady sets event trigger when image is downloaded and ready to display.
+func (i *ImageWithURLWidget) OnReady(onReady func()) *ImageWithURLWidget {
+	i.onReady = onReady
+	return i
+}
+
+// OnFailure sets event trigger when image failed to download/load.
+func (i *ImageWithURLWidget) OnFailure(onFailure func(error)) *ImageWithURLWidget {
+	i.onFailure = onFailure
+	return i
+}
+
+// OnClick sets click callback.
+func (i *ImageWithURLWidget) OnClick(cb func()) *ImageWithURLWidget {
+	i.img.OnClick(cb)
+	return i
+}
+
+// Timeout sets download timeout.
+func (i *ImageWithURLWidget) Timeout(downloadTimeout time.Duration) *ImageWithURLWidget {
+	i.downloadTimeout = downloadTimeout
+	return i
+}
+
+// Size sets image's size.
+func (i *ImageWithURLWidget) Size(width, height float32) *ImageWithURLWidget {
+	i.img.Size(width, height)
+	return i
+}
+
+// LayoutForLoading allows to set layout rendered while loading an image.
+func (i *ImageWithURLWidget) LayoutForLoading(widgets ...Widget) *ImageWithURLWidget {
+	i.whenLoading = Layout(widgets)
+	return i
+}
+
+// LayoutForFailure allows to specify layout when image failed to download.
+func (i *ImageWithURLWidget) LayoutForFailure(widgets ...Widget) *ImageWithURLWidget {
+	i.whenFailure = Layout(widgets)
+	return i
+}
+
+// Build implements Widget interface.
+func (i *ImageWithURLWidget) Build() {
+	imgState := &imageState{}
+
+	if state := Context.GetState(i.id); state == nil {
+		Context.SetState(i.id, imgState)
+
+		// Prevent multiple invocation to download image.
+		downloadContext, cancalFunc := ctx.WithCancel(ctx.Background())
+		Context.SetState(i.id, &imageState{loading: true, cancel: cancalFunc})
+
+		errorFn := func(err error) {
+			Context.SetState(i.id, &imageState{failure: true})
+
+			// Trigger onFailure event
+			if i.onFailure != nil {
+				i.onFailure(err)
+			}
+		}
+
+		go func() {
+			// Load image from url
+			client := &http.Client{Timeout: i.downloadTimeout}
+			req, err := http.NewRequestWithContext(downloadContext, "GET", i.imgURL, http.NoBody)
+			if err != nil {
+				errorFn(err)
+				return
+			}
+
+			resp, err := client.Do(req)
+			if err != nil {
+				errorFn(err)
+				return
+			}
+
+			defer func() {
+				if closeErr := resp.Body.Close(); closeErr != nil {
+					errorFn(closeErr)
+				}
+			}()
+
+			img, _, err := image.Decode(resp.Body)
+			if err != nil {
+				errorFn(err)
+				return
+			}
+
+			rgba := ImageToRgba(img)
+
+			NewTextureFromRgba(rgba, func(tex *Texture) {
+				Context.SetState(i.id, &imageState{
+					loading: false,
+					failure: false,
+					texture: tex,
+				})
+			})
+
+			// Trigger onReady event
+			if i.onReady != nil {
+				i.onReady()
+			}
+		}()
+	} else {
+		var isOk bool
+		imgState, isOk = state.(*imageState)
+		Assert(isOk, "ImageWithURLWidget", "Build", "wrong type of widget's state recovered.")
+	}
+
+	switch {
+	case imgState.failure:
+		i.whenFailure.Build()
+	case imgState.loading:
+		i.whenLoading.Build()
+	default:
+		i.img.texture = imgState.texture
+		i.img.Build()
+	}
+}

+ 104 - 0
vendor/github.com/AllenDang/giu/InputHandler.go

@@ -0,0 +1,104 @@
+package giu
+
+// input menager is used to register a keyboard shortcuts in an app.
+
+// Shortcut represents a keyboard shortcut.
+type Shortcut struct {
+	Key      Key
+	Modifier Modifier
+	Callback func()
+	IsGlobal ShortcutType
+}
+
+// WindowShortcut represents a window-level shortcut
+// could be used as an argument to (*Window).RegisterKeyboardShortcuts.
+type WindowShortcut struct {
+	Key      Key
+	Modifier Modifier
+	Callback func()
+}
+
+// ShortcutType represens a type of shortcut (global or local).
+type ShortcutType bool
+
+const (
+	// GlobalShortcut is registered for all the app.
+	GlobalShortcut ShortcutType = true
+
+	// LocalShortcut is registered for current window only.
+	LocalShortcut ShortcutType = false
+)
+
+// InputHandler is an interface which needs to be implemented
+// by user-definied input handlers.
+type InputHandler interface {
+	// RegisterKeyboardShortcuts adds a specified shortcuts into input handler
+	RegisterKeyboardShortcuts(...Shortcut)
+	// UnregisterKeyboardShortcuts removes iwndow shourtcuts from input handler
+	UnregisterWindowShortcuts()
+	// Handle handles a shortcut
+	Handle(Key, Modifier)
+}
+
+// --- Default implementation of giu input manager ---
+
+var _ InputHandler = &inputHandler{}
+
+func newInputHandler() *inputHandler {
+	return &inputHandler{
+		shortcuts: make(map[keyCombo]*callbacks),
+	}
+}
+
+type inputHandler struct {
+	shortcuts map[keyCombo]*callbacks
+}
+
+func (i *inputHandler) RegisterKeyboardShortcuts(s ...Shortcut) {
+	for _, shortcut := range s {
+		combo := keyCombo{shortcut.Key, shortcut.Modifier}
+
+		cb, isRegistered := i.shortcuts[combo]
+		if !isRegistered {
+			cb = &callbacks{}
+		}
+
+		if shortcut.IsGlobal {
+			cb.global = shortcut.Callback
+		} else {
+			cb.window = shortcut.Callback
+		}
+
+		i.shortcuts[combo] = cb
+	}
+}
+
+func (i *inputHandler) UnregisterWindowShortcuts() {
+	for _, s := range i.shortcuts {
+		s.window = nil
+	}
+}
+
+func (i *inputHandler) Handle(key Key, mod Modifier) {
+	for combo, cb := range i.shortcuts {
+		if combo.key != key || combo.modifier != mod {
+			continue
+		}
+
+		if cb.window != nil {
+			cb.window()
+		} else if cb.global != nil {
+			cb.global()
+		}
+	}
+}
+
+type keyCombo struct {
+	key      Key
+	modifier Modifier
+}
+
+type callbacks struct {
+	global func()
+	window func()
+}

+ 148 - 0
vendor/github.com/AllenDang/giu/Keycode.go

@@ -0,0 +1,148 @@
+package giu
+
+import "github.com/go-gl/glfw/v3.3/glfw"
+
+// Key represents a glfw key.
+type Key glfw.Key
+
+// These key codes are inspired by the USB HID Usage Tables v1.12 (p. 53-60),
+// but re-arranged to map to 7-bit ASCII for printable keys (function keys are
+// put in the 256+ range).
+const (
+	KeyUnknown      Key = Key(glfw.KeyUnknown)
+	KeySpace        Key = Key(glfw.KeySpace)
+	KeyApostrophe   Key = Key(glfw.KeyApostrophe)
+	KeyComma        Key = Key(glfw.KeyComma)
+	KeyMinus        Key = Key(glfw.KeyMinus)
+	KeyPeriod       Key = Key(glfw.KeyPeriod)
+	KeySlash        Key = Key(glfw.KeySlash)
+	Key0            Key = Key(glfw.Key0)
+	Key1            Key = Key(glfw.Key1)
+	Key2            Key = Key(glfw.Key2)
+	Key3            Key = Key(glfw.Key3)
+	Key4            Key = Key(glfw.Key4)
+	Key5            Key = Key(glfw.Key5)
+	Key6            Key = Key(glfw.Key6)
+	Key7            Key = Key(glfw.Key7)
+	Key8            Key = Key(glfw.Key8)
+	Key9            Key = Key(glfw.Key9)
+	KeySemicolon    Key = Key(glfw.KeySemicolon)
+	KeyEqual        Key = Key(glfw.KeyEqual)
+	KeyA            Key = Key(glfw.KeyA)
+	KeyB            Key = Key(glfw.KeyB)
+	KeyC            Key = Key(glfw.KeyC)
+	KeyD            Key = Key(glfw.KeyD)
+	KeyE            Key = Key(glfw.KeyE)
+	KeyF            Key = Key(glfw.KeyF)
+	KeyG            Key = Key(glfw.KeyG)
+	KeyH            Key = Key(glfw.KeyH)
+	KeyI            Key = Key(glfw.KeyI)
+	KeyJ            Key = Key(glfw.KeyJ)
+	KeyK            Key = Key(glfw.KeyK)
+	KeyL            Key = Key(glfw.KeyL)
+	KeyM            Key = Key(glfw.KeyM)
+	KeyN            Key = Key(glfw.KeyN)
+	KeyO            Key = Key(glfw.KeyO)
+	KeyP            Key = Key(glfw.KeyP)
+	KeyQ            Key = Key(glfw.KeyQ)
+	KeyR            Key = Key(glfw.KeyR)
+	KeyS            Key = Key(glfw.KeyS)
+	KeyT            Key = Key(glfw.KeyT)
+	KeyU            Key = Key(glfw.KeyU)
+	KeyV            Key = Key(glfw.KeyV)
+	KeyW            Key = Key(glfw.KeyW)
+	KeyX            Key = Key(glfw.KeyX)
+	KeyY            Key = Key(glfw.KeyY)
+	KeyZ            Key = Key(glfw.KeyZ)
+	KeyLeftBracket  Key = Key(glfw.KeyLeftBracket)
+	KeyBackslash    Key = Key(glfw.KeyBackslash)
+	KeyRightBracket Key = Key(glfw.KeyRightBracket)
+	KeyGraveAccent  Key = Key(glfw.KeyGraveAccent)
+	KeyWorld1       Key = Key(glfw.KeyWorld1)
+	KeyWorld2       Key = Key(glfw.KeyWorld2)
+	KeyEscape       Key = Key(glfw.KeyEscape)
+	KeyEnter        Key = Key(glfw.KeyEnter)
+	KeyTab          Key = Key(glfw.KeyTab)
+	KeyBackspace    Key = Key(glfw.KeyBackspace)
+	KeyInsert       Key = Key(glfw.KeyInsert)
+	KeyDelete       Key = Key(glfw.KeyDelete)
+	KeyRight        Key = Key(glfw.KeyRight)
+	KeyLeft         Key = Key(glfw.KeyLeft)
+	KeyDown         Key = Key(glfw.KeyDown)
+	KeyUp           Key = Key(glfw.KeyUp)
+	KeyPageUp       Key = Key(glfw.KeyPageUp)
+	KeyPageDown     Key = Key(glfw.KeyPageDown)
+	KeyHome         Key = Key(glfw.KeyHome)
+	KeyEnd          Key = Key(glfw.KeyEnd)
+	KeyCapsLock     Key = Key(glfw.KeyCapsLock)
+	KeyScrollLock   Key = Key(glfw.KeyScrollLock)
+	KeyNumLock      Key = Key(glfw.KeyNumLock)
+	KeyPrintScreen  Key = Key(glfw.KeyPrintScreen)
+	KeyPause        Key = Key(glfw.KeyPause)
+	KeyF1           Key = Key(glfw.KeyF1)
+	KeyF2           Key = Key(glfw.KeyF2)
+	KeyF3           Key = Key(glfw.KeyF3)
+	KeyF4           Key = Key(glfw.KeyF4)
+	KeyF5           Key = Key(glfw.KeyF5)
+	KeyF6           Key = Key(glfw.KeyF6)
+	KeyF7           Key = Key(glfw.KeyF7)
+	KeyF8           Key = Key(glfw.KeyF8)
+	KeyF9           Key = Key(glfw.KeyF9)
+	KeyF10          Key = Key(glfw.KeyF10)
+	KeyF11          Key = Key(glfw.KeyF11)
+	KeyF12          Key = Key(glfw.KeyF12)
+	KeyF13          Key = Key(glfw.KeyF13)
+	KeyF14          Key = Key(glfw.KeyF14)
+	KeyF15          Key = Key(glfw.KeyF15)
+	KeyF16          Key = Key(glfw.KeyF16)
+	KeyF17          Key = Key(glfw.KeyF17)
+	KeyF18          Key = Key(glfw.KeyF18)
+	KeyF19          Key = Key(glfw.KeyF19)
+	KeyF20          Key = Key(glfw.KeyF20)
+	KeyF21          Key = Key(glfw.KeyF21)
+	KeyF22          Key = Key(glfw.KeyF22)
+	KeyF23          Key = Key(glfw.KeyF23)
+	KeyF24          Key = Key(glfw.KeyF24)
+	KeyF25          Key = Key(glfw.KeyF25)
+	KeyKP0          Key = Key(glfw.KeyKP0)
+	KeyKP1          Key = Key(glfw.KeyKP1)
+	KeyKP2          Key = Key(glfw.KeyKP2)
+	KeyKP3          Key = Key(glfw.KeyKP3)
+	KeyKP4          Key = Key(glfw.KeyKP4)
+	KeyKP5          Key = Key(glfw.KeyKP5)
+	KeyKP6          Key = Key(glfw.KeyKP6)
+	KeyKP7          Key = Key(glfw.KeyKP7)
+	KeyKP8          Key = Key(glfw.KeyKP8)
+	KeyKP9          Key = Key(glfw.KeyKP9)
+	KeyKPDecimal    Key = Key(glfw.KeyKPDecimal)
+	KeyKPDivide     Key = Key(glfw.KeyKPDivide)
+	KeyKPMultiply   Key = Key(glfw.KeyKPMultiply)
+	KeyKPSubtract   Key = Key(glfw.KeyKPSubtract)
+	KeyKPAdd        Key = Key(glfw.KeyKPAdd)
+	KeyKPEnter      Key = Key(glfw.KeyKPEnter)
+	KeyKPEqual      Key = Key(glfw.KeyKPEqual)
+	KeyLeftShift    Key = Key(glfw.KeyLeftShift)
+	KeyLeftControl  Key = Key(glfw.KeyLeftControl)
+	KeyLeftAlt      Key = Key(glfw.KeyLeftAlt)
+	KeyLeftSuper    Key = Key(glfw.KeyLeftSuper)
+	KeyRightShift   Key = Key(glfw.KeyRightShift)
+	KeyRightControl Key = Key(glfw.KeyRightControl)
+	KeyRightAlt     Key = Key(glfw.KeyRightAlt)
+	KeyRightSuper   Key = Key(glfw.KeyRightSuper)
+	KeyMenu         Key = Key(glfw.KeyMenu)
+	KeyLast         Key = Key(glfw.KeyLast)
+)
+
+// Modifier represents glfw.Modifier.
+type Modifier glfw.ModifierKey
+
+// modifier keys.
+const (
+	ModNone     Modifier = iota
+	ModControl  Modifier = Modifier(glfw.ModControl)
+	ModAlt      Modifier = Modifier(glfw.ModAlt)
+	ModSuper    Modifier = Modifier(glfw.ModSuper)
+	ModShift    Modifier = Modifier(glfw.ModShift)
+	ModCapsLock Modifier = Modifier(glfw.ModCapsLock)
+	ModNumLock  Modifier = Modifier(glfw.ModNumLock)
+)

+ 1 - 1
vendor/github.com/zserge/lorca/LICENSE → vendor/github.com/AllenDang/giu/LICENSE

@@ -1,6 +1,6 @@
 MIT License
 
-Copyright (c) 2018 Serge Zaitsev
+Copyright (c) 2020 Allen Dang
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal

+ 50 - 0
vendor/github.com/AllenDang/giu/Layout.go

@@ -0,0 +1,50 @@
+package giu
+
+const (
+	// Auto is used to widget.Size to indicate height or width to occupy available spaces.
+	Auto float32 = -1
+)
+
+// Widget is a base unit of giu rendering system.
+// each widget just needs to implement Build method which is called,
+// when widget needs to be rendered.
+type Widget interface {
+	Build()
+}
+
+var (
+	_ Widget    = Layout{}
+	_ Splitable = Layout{}
+)
+
+// Layout is a set of widgets. It implements Widget interface so
+// Layout can be used as a widget.
+type Layout []Widget
+
+// Build implements Widget interface.
+func (l Layout) Build() {
+	for _, w := range l {
+		if w != nil {
+			w.Build()
+		}
+	}
+}
+
+// Splitable is implemented by widgets, which can be split (ranged)
+// Layout implements Splitable.
+type Splitable interface {
+	Range(func(w Widget))
+}
+
+// Range ranges ofer the Layout, calling rangeFunc
+// on each loop iteration.
+func (l Layout) Range(rangeFunc func(Widget)) {
+	for _, w := range l {
+		if splitable, canRange := w.(Splitable); canRange {
+			splitable.Range(rangeFunc)
+			continue
+		}
+
+		rangeFunc(w)
+	}
+}

+ 47 - 0
vendor/github.com/AllenDang/giu/ListClipper.go

@@ -0,0 +1,47 @@
+package giu
+
+import (
+	"github.com/AllenDang/imgui-go"
+)
+
+var _ Widget = &ListClipperWrapper{}
+
+// ListClipperWrapper is a ImGuiListClipper implementation.
+// it can be used to diplay a large, vertical list of items and
+// avoid rendering them.
+type ListClipperWrapper struct {
+	layout Layout
+}
+
+// ListClipper creates list clipper.
+func ListClipper() *ListClipperWrapper {
+	return &ListClipperWrapper{}
+}
+
+// Layout sets layout for list clipper.
+func (l *ListClipperWrapper) Layout(layout ...Widget) *ListClipperWrapper {
+	l.layout = layout
+	return l
+}
+
+// Build implements widget interface.
+func (l *ListClipperWrapper) Build() {
+	// read all the layout widgets and (eventually) split nested layouts
+	var layout Layout
+	l.layout.Range(func(w Widget) {
+		layout = append(layout, w)
+	})
+
+	clipper := imgui.NewListClipper()
+	defer clipper.Delete()
+
+	clipper.Begin(len(layout))
+
+	for clipper.Step() {
+		for i := clipper.DisplayStart(); i < clipper.DisplayEnd(); i++ {
+			layout[i].Build()
+		}
+	}
+
+	clipper.End()
+}

+ 131 - 0
vendor/github.com/AllenDang/giu/Markdown.go

@@ -0,0 +1,131 @@
+package giu
+
+import (
+	"image"
+	"image/color"
+	"net/http"
+	"strings"
+	"time"
+
+	"github.com/AllenDang/imgui-go"
+	"github.com/faiface/mainthread"
+)
+
+// MarkdownWidget implements DearImGui markdown extension
+// https://github.com/juliettef/imgui_markdown
+// It is like LabelWidget but with md formatting.
+type MarkdownWidget struct {
+	md      *string
+	linkCb  func(url string)
+	headers []imgui.MarkdownHeaderData
+}
+
+// Markdown creates new markdown widget.
+func Markdown(md *string) *MarkdownWidget {
+	return &MarkdownWidget{
+		md:     md,
+		linkCb: OpenURL,
+	}
+}
+
+// OnLink sets another than default link callback.
+func (m *MarkdownWidget) OnLink(cb func(url string)) *MarkdownWidget {
+	m.linkCb = cb
+	return m
+}
+
+// Header sets header formatting
+// NOTE: level (counting from 0!) is header level. (for instance, header `# H1` will have level 0).
+func (m *MarkdownWidget) Header(level int, font *FontInfo, separator bool) *MarkdownWidget {
+	// ensure if header data are at least as long as level
+	if m.headers == nil {
+		m.headers = make([]imgui.MarkdownHeaderData, level)
+	}
+
+	if level <= len(m.headers) {
+		m.headers = append(m.headers, make([]imgui.MarkdownHeaderData, len(m.headers)-level+1)...)
+	}
+
+	if font != nil {
+		if f, ok := extraFontMap[font.String()]; ok {
+			m.headers[level].Font = *f
+		}
+	}
+
+	m.headers[level].HasSeparator = separator
+
+	return m
+}
+
+// Build implements Widget interface.
+func (m *MarkdownWidget) Build() {
+	imgui.Markdown(tStrPtr(m.md), m.linkCb, loadImage, m.headers)
+}
+
+func loadImage(path string) imgui.MarkdownImageData {
+	var img *image.RGBA
+	var err error
+
+	switch {
+	case strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://"):
+		// Load image from url
+		client := &http.Client{Timeout: 5 * time.Second}
+		resp, respErr := client.Get(path)
+		if respErr != nil {
+			return imgui.MarkdownImageData{}
+		}
+
+		defer func() {
+			closeErr := resp.Body.Close()
+			Assert((closeErr == nil), "MarkdownWidget", "loadImage", "Could not close http request!")
+		}()
+
+		rgba, _, imgErr := image.Decode(resp.Body)
+		if imgErr != nil {
+			return imgui.MarkdownImageData{}
+		}
+
+		img = ImageToRgba(rgba)
+	default:
+		img, err = LoadImage(path)
+		if err != nil {
+			return imgui.MarkdownImageData{}
+		}
+	}
+
+	size := img.Bounds()
+
+	// nolint:gocritic // TODO/BUG: figure out, why it doesn't work as expected and consider
+	// if current workaround is save
+	/*
+		tex := &Texture{}
+		NewTextureFromRgba(img, func(t *Texture) {
+			fmt.Println("creating texture")
+			tex.id = t.id
+		})
+	*/
+
+	var id imgui.TextureID
+	mainthread.Call(func() {
+		var err error
+		id, err = Context.renderer.LoadImage(img)
+		if err != nil {
+			return
+		}
+	})
+
+	return imgui.MarkdownImageData{
+		TextureID: &id,
+		Scale:     true,
+		Size: imgui.Vec2{
+			X: float32(size.Dx()),
+			Y: float32(size.Dy()),
+		},
+		UseLinkCallback: true,
+		// default values
+		Uv0:         ToVec2(image.Point{0, 0}),
+		Uv1:         ToVec2(image.Point{1, 1}),
+		TintColor:   ToVec4Color(color.RGBA{255, 255, 255, 255}),
+		BorderColor: ToVec4Color(color.RGBA{0, 0, 0, 0}),
+	}
+}

+ 399 - 0
vendor/github.com/AllenDang/giu/MasterWindow.go

@@ -0,0 +1,399 @@
+package giu
+
+import (
+	"image"
+	"image/color"
+	"runtime"
+	"time"
+
+	"github.com/AllenDang/imgui-go"
+	"github.com/faiface/mainthread"
+	"github.com/go-gl/glfw/v3.3/glfw"
+	"gopkg.in/eapache/queue.v1"
+)
+
+// MasterWindowFlags wrapps imgui.GLFWWindowFlags.
+type MasterWindowFlags imgui.GLFWWindowFlags
+
+// master window flags.
+const (
+	// Specifies the window will be fixed size.
+	MasterWindowFlagsNotResizable MasterWindowFlags = MasterWindowFlags(imgui.GLFWWindowFlagsNotResizable)
+	// Specifies whether the window is maximized.
+	MasterWindowFlagsMaximized MasterWindowFlags = MasterWindowFlags(imgui.GLFWWindowFlagsMaximized)
+	// Specifies whether the window will be always-on-top.
+	MasterWindowFlagsFloating MasterWindowFlags = MasterWindowFlags(imgui.GLFWWindowFlagsFloating)
+	// Specifies whether the window will be frameless.
+	MasterWindowFlagsFrameless MasterWindowFlags = MasterWindowFlags(imgui.GLFWWindowFlagsFrameless)
+	// Specifies whether the window will be transparent.
+	MasterWindowFlagsTransparent MasterWindowFlags = MasterWindowFlags(imgui.GLFWWindowFlagsTransparent)
+)
+
+// DontCare could be used as an argument to (*MasterWindow).SetSizeLimits.
+var DontCare int = imgui.GlfwDontCare
+
+// MasterWindow represents a glfw master window
+// It is a base for a windows (see Window.go).
+type MasterWindow struct {
+	width      int
+	height     int
+	clearColor [4]float32
+	title      string
+	platform   imgui.Platform
+	renderer   imgui.Renderer
+	context    *imgui.Context
+	io         *imgui.IO
+	updateFunc func()
+}
+
+// NewMasterWindow creates a new master window and initializes GLFW.
+// it should be called in main function. For more details and use cases,
+// see examples/helloworld/.
+func NewMasterWindow(title string, width, height int, flags MasterWindowFlags) *MasterWindow {
+	initFontAtlasProcessor()
+
+	context := imgui.CreateContext(nil)
+	imgui.ImPlotCreateContext()
+	imgui.ImNodesCreateContext()
+
+	io := imgui.CurrentIO()
+
+	io.SetConfigFlags(imgui.ConfigFlagEnablePowerSavingMode | imgui.BackendFlagsRendererHasVtxOffset)
+
+	// Disable imgui.ini
+	io.SetIniFilename("")
+
+	p, err := imgui.NewGLFW(io, title, width, height, imgui.GLFWWindowFlags(flags))
+	if err != nil {
+		panic(err)
+	}
+
+	// Assign platform to contex
+	Context.platform = p
+
+	r, err := imgui.NewOpenGL3(io, 1.0)
+	if err != nil {
+		panic(err)
+	}
+
+	// Create context
+	Context.renderer = r
+
+	// Create font
+	if len(defaultFonts) == 0 {
+		io.Fonts().AddFontDefault()
+		fontAtlas := io.Fonts().TextureDataRGBA32()
+		r.SetFontTexture(fontAtlas)
+	} else {
+		shouldRebuildFontAtlas = true
+		rebuildFontAtlas()
+	}
+
+	// init texture loading queue
+	Context.textureLoadingQueue = queue.New()
+
+	mw := &MasterWindow{
+		clearColor: [4]float32{0, 0, 0, 1},
+		width:      width,
+		height:     height,
+		title:      title,
+		io:         &io,
+		context:    context,
+		platform:   p,
+		renderer:   r,
+	}
+
+	mw.SetInputHandler(newInputHandler())
+
+	p.SetSizeChangeCallback(mw.sizeChange)
+
+	mw.setTheme()
+
+	return mw
+}
+
+func (w *MasterWindow) setTheme() {
+	style := imgui.CurrentStyle()
+
+	// Scale DPI in windows
+	if runtime.GOOS == "windows" {
+		style.ScaleAllSizes(Context.GetPlatform().GetContentScale())
+	}
+
+	imgui.PushStyleVarFloat(imgui.StyleVarWindowRounding, 2)
+	imgui.PushStyleVarFloat(imgui.StyleVarFrameRounding, 4)
+	imgui.PushStyleVarFloat(imgui.StyleVarGrabRounding, 4)
+	imgui.PushStyleVarFloat(imgui.StyleVarFrameBorderSize, 1)
+
+	style.SetColor(imgui.StyleColorText, imgui.Vec4{X: 0.95, Y: 0.96, Z: 0.98, W: 1.00})
+	style.SetColor(imgui.StyleColorTextDisabled, imgui.Vec4{X: 0.36, Y: 0.42, Z: 0.47, W: 1.00})
+	style.SetColor(imgui.StyleColorWindowBg, imgui.Vec4{X: 0.11, Y: 0.15, Z: 0.17, W: 1.00})
+	style.SetColor(imgui.StyleColorChildBg, imgui.Vec4{X: 0.15, Y: 0.18, Z: 0.22, W: 1.00})
+	style.SetColor(imgui.StyleColorPopupBg, imgui.Vec4{X: 0.08, Y: 0.08, Z: 0.08, W: 0.94})
+	style.SetColor(imgui.StyleColorBorder, imgui.Vec4{X: 0.08, Y: 0.10, Z: 0.12, W: 1.00})
+	style.SetColor(imgui.StyleColorBorderShadow, imgui.Vec4{X: 0.00, Y: 0.00, Z: 0.00, W: 0.00})
+	style.SetColor(imgui.StyleColorFrameBg, imgui.Vec4{X: 0.20, Y: 0.25, Z: 0.29, W: 1.00})
+	style.SetColor(imgui.StyleColorFrameBgHovered, imgui.Vec4{X: 0.12, Y: 0.20, Z: 0.28, W: 1.00})
+	style.SetColor(imgui.StyleColorFrameBgActive, imgui.Vec4{X: 0.09, Y: 0.12, Z: 0.14, W: 1.00})
+	style.SetColor(imgui.StyleColorTitleBg, imgui.Vec4{X: 0.09, Y: 0.12, Z: 0.14, W: 0.65})
+	style.SetColor(imgui.StyleColorTitleBgActive, imgui.Vec4{X: 0.08, Y: 0.10, Z: 0.12, W: 1.00})
+	style.SetColor(imgui.StyleColorTitleBgCollapsed, imgui.Vec4{X: 0.00, Y: 0.00, Z: 0.00, W: 0.51})
+	style.SetColor(imgui.StyleColorMenuBarBg, imgui.Vec4{X: 0.15, Y: 0.18, Z: 0.22, W: 1.00})
+	style.SetColor(imgui.StyleColorScrollbarBg, imgui.Vec4{X: 0.02, Y: 0.02, Z: 0.02, W: 0.39})
+	style.SetColor(imgui.StyleColorScrollbarGrab, imgui.Vec4{X: 0.20, Y: 0.25, Z: 0.29, W: 1.00})
+	style.SetColor(imgui.StyleColorScrollbarGrabHovered, imgui.Vec4{X: 0.18, Y: 0.22, Z: 0.25, W: 1.00})
+	style.SetColor(imgui.StyleColorScrollbarGrabActive, imgui.Vec4{X: 0.09, Y: 0.21, Z: 0.31, W: 1.00})
+	style.SetColor(imgui.StyleColorCheckMark, imgui.Vec4{X: 0.28, Y: 0.56, Z: 1.00, W: 1.00})
+	style.SetColor(imgui.StyleColorSliderGrab, imgui.Vec4{X: 0.28, Y: 0.56, Z: 1.00, W: 1.00})
+	style.SetColor(imgui.StyleColorSliderGrabActive, imgui.Vec4{X: 0.37, Y: 0.61, Z: 1.00, W: 1.00})
+	style.SetColor(imgui.StyleColorButton, imgui.Vec4{X: 0.20, Y: 0.25, Z: 0.29, W: 1.00})
+	style.SetColor(imgui.StyleColorButtonHovered, imgui.Vec4{X: 0.28, Y: 0.56, Z: 1.00, W: 1.00})
+	style.SetColor(imgui.StyleColorButtonActive, imgui.Vec4{X: 0.06, Y: 0.53, Z: 0.98, W: 1.00})
+	style.SetColor(imgui.StyleColorHeader, imgui.Vec4{X: 0.20, Y: 0.25, Z: 0.29, W: 0.55})
+	style.SetColor(imgui.StyleColorHeaderHovered, imgui.Vec4{X: 0.26, Y: 0.59, Z: 0.98, W: 0.80})
+	style.SetColor(imgui.StyleColorHeaderActive, imgui.Vec4{X: 0.26, Y: 0.59, Z: 0.98, W: 1.00})
+	style.SetColor(imgui.StyleColorSeparator, imgui.Vec4{X: 0.20, Y: 0.25, Z: 0.29, W: 1.00})
+	style.SetColor(imgui.StyleColorSeparatorHovered, imgui.Vec4{X: 0.10, Y: 0.40, Z: 0.75, W: 0.78})
+	style.SetColor(imgui.StyleColorSeparatorActive, imgui.Vec4{X: 0.10, Y: 0.40, Z: 0.75, W: 1.00})
+	style.SetColor(imgui.StyleColorResizeGrip, imgui.Vec4{X: 0.26, Y: 0.59, Z: 0.98, W: 0.25})
+	style.SetColor(imgui.StyleColorResizeGripHovered, imgui.Vec4{X: 0.26, Y: 0.59, Z: 0.98, W: 0.67})
+	style.SetColor(imgui.StyleColorResizeGripActive, imgui.Vec4{X: 0.26, Y: 0.59, Z: 0.98, W: 0.95})
+	style.SetColor(imgui.StyleColorTab, imgui.Vec4{X: 0.11, Y: 0.15, Z: 0.17, W: 1.00})
+	style.SetColor(imgui.StyleColorTabHovered, imgui.Vec4{X: 0.26, Y: 0.59, Z: 0.98, W: 0.80})
+	style.SetColor(imgui.StyleColorTabActive, imgui.Vec4{X: 0.20, Y: 0.25, Z: 0.29, W: 1.00})
+	style.SetColor(imgui.StyleColorTabUnfocused, imgui.Vec4{X: 0.11, Y: 0.15, Z: 0.17, W: 1.00})
+	style.SetColor(imgui.StyleColorTabUnfocusedActive, imgui.Vec4{X: 0.11, Y: 0.15, Z: 0.17, W: 1.00})
+	style.SetColor(imgui.StyleColorPlotLines, imgui.Vec4{X: 0.61, Y: 0.61, Z: 0.61, W: 1.00})
+	style.SetColor(imgui.StyleColorPlotLinesHovered, imgui.Vec4{X: 1.00, Y: 0.43, Z: 0.35, W: 1.00})
+	style.SetColor(imgui.StyleColorPlotHistogram, imgui.Vec4{X: 0.90, Y: 0.70, Z: 0.00, W: 1.00})
+	style.SetColor(imgui.StyleColorPlotHistogramHovered, imgui.Vec4{X: 1.00, Y: 0.60, Z: 0.00, W: 1.00})
+	style.SetColor(imgui.StyleColorTextSelectedBg, imgui.Vec4{X: 0.26, Y: 0.59, Z: 0.98, W: 0.35})
+	style.SetColor(imgui.StyleColorDragDropTarget, imgui.Vec4{X: 1.00, Y: 1.00, Z: 0.00, W: 0.90})
+	style.SetColor(imgui.StyleColorNavHighlight, imgui.Vec4{X: 0.26, Y: 0.59, Z: 0.98, W: 1.00})
+	style.SetColor(imgui.StyleColorNavWindowingHighlight, imgui.Vec4{X: 1.00, Y: 1.00, Z: 1.00, W: 0.70})
+	style.SetColor(imgui.StyleColorTableHeaderBg, imgui.Vec4{X: 0.12, Y: 0.20, Z: 0.28, W: 1.00})
+	style.SetColor(imgui.StyleColorTableBorderStrong, imgui.Vec4{X: 0.20, Y: 0.25, Z: 0.29, W: 1.00})
+	style.SetColor(imgui.StyleColorTableBorderLight, imgui.Vec4{X: 0.20, Y: 0.25, Z: 0.29, W: 0.70})
+}
+
+// SetBgColor sets background color of master window.
+func (w *MasterWindow) SetBgColor(bgColor color.Color) {
+	const mask = 0xffff
+
+	r, g, b, a := bgColor.RGBA()
+	w.clearColor = [4]float32{
+		float32(r) / mask,
+		float32(g) / mask,
+		float32(b) / mask,
+		float32(a) / mask,
+	}
+}
+
+func (w *MasterWindow) sizeChange(width, height int) {
+	w.render()
+}
+
+func (w *MasterWindow) render() {
+	if !w.platform.IsVisible() || w.platform.IsMinimized() {
+		return
+	}
+
+	Context.invalidAllState()
+	defer Context.cleanState()
+
+	rebuildFontAtlas()
+
+	p := w.platform
+	r := w.renderer
+
+	p.NewFrame()
+	r.PreRender(w.clearColor)
+
+	imgui.NewFrame()
+	w.updateFunc()
+	imgui.Render()
+
+	r.Render(p.DisplaySize(), p.FramebufferSize(), imgui.RenderedDrawData())
+	p.PostRender()
+}
+
+// Run the main loop to create new frame, process events and call update ui func.
+func (w *MasterWindow) run() {
+	p := w.platform
+
+	ticker := time.NewTicker(time.Second / time.Duration(p.GetTPS()))
+	shouldQuit := false
+	for !shouldQuit {
+		mainthread.Call(func() {
+			// process texture load requests
+			if Context.textureLoadingQueue != nil && Context.textureLoadingQueue.Length() > 0 {
+				for Context.textureLoadingQueue.Length() > 0 {
+					request, ok := Context.textureLoadingQueue.Remove().(textureLoadRequest)
+					Assert(ok, "MasterWindow", "Run", "processing texture requests: wrong type of texture request")
+					NewTextureFromRgba(request.img, request.cb)
+				}
+			}
+
+			p.ProcessEvents()
+			w.render()
+
+			shouldQuit = p.ShouldStop()
+		})
+
+		<-ticker.C
+	}
+}
+
+// GetSize return size of master window.
+func (w *MasterWindow) GetSize() (width, height int) {
+	if w.platform != nil {
+		if glfwPlatform, ok := w.platform.(*imgui.GLFW); ok {
+			return glfwPlatform.GetWindow().GetSize()
+		}
+	}
+
+	return w.width, w.height
+}
+
+// GetPos return position of master window.
+func (w *MasterWindow) GetPos() (x, y int) {
+	if w.platform != nil {
+		if glfwPlatform, ok := w.platform.(*imgui.GLFW); ok {
+			x, y = glfwPlatform.GetWindow().GetPos()
+		}
+	}
+
+	return
+}
+
+// SetPos sets position of master window.
+func (w *MasterWindow) SetPos(x, y int) {
+	if w.platform != nil {
+		if glfwPlatform, ok := w.platform.(*imgui.GLFW); ok {
+			glfwPlatform.GetWindow().SetPos(x, y)
+		}
+	}
+}
+
+// SetSize sets size of master window.
+func (w *MasterWindow) SetSize(x, y int) {
+	if w.platform != nil {
+		if glfwPlatform, ok := w.platform.(*imgui.GLFW); ok {
+			mainthread.CallNonBlock(func() {
+				glfwPlatform.GetWindow().SetSize(x, y)
+			})
+		}
+	}
+}
+
+// SetCloseCallback sets the close callback of the window, which is called when
+// the user attempts to close the window, for example by clicking the close
+// widget in the title bar.
+//
+// The close flag is set before this callback is called, but you can modify it at
+// any time with returned value of callback function.
+//
+// Mac OS X: Selecting Quit from the application menu will trigger the close
+// callback for all windows.
+func (w *MasterWindow) SetCloseCallback(cb func() bool) {
+	w.platform.SetCloseCallback(cb)
+}
+
+// SetDropCallback sets callback when file was droppend into the window.
+func (w *MasterWindow) SetDropCallback(cb func([]string)) {
+	w.platform.SetDropCallback(cb)
+}
+
+// Run runs the main loop.
+// loopFunc will be used to construct the ui.
+// Run should be called at the end of main function, after setting
+// up the master window.
+func (w *MasterWindow) Run(loopFunc func()) {
+	mainthread.Run(func() {
+		Context.isRunning = true
+		w.updateFunc = loopFunc
+
+		Context.isAlive = true
+
+		w.run()
+
+		Context.isAlive = false
+
+		mainthread.Call(func() {
+			w.renderer.Dispose()
+			w.platform.Dispose()
+
+			imgui.ImNodesDestroyContext()
+			imgui.ImPlotDestroyContext()
+			w.context.Destroy()
+		})
+
+		Context.isRunning = false
+	})
+}
+
+// RegisterKeyboardShortcuts registers a global - master window - keyboard shortcuts.
+func (w *MasterWindow) RegisterKeyboardShortcuts(s ...WindowShortcut) *MasterWindow {
+	for _, shortcut := range s {
+		Context.InputHandler.RegisterKeyboardShortcuts(Shortcut{
+			Key:      shortcut.Key,
+			Modifier: shortcut.Modifier,
+			Callback: shortcut.Callback,
+			IsGlobal: GlobalShortcut,
+		})
+	}
+
+	return w
+}
+
+// SetIcon sets the icon of the specified window. If passed an array of candidate images,
+// those of or closest to the sizes desired by the system are selected. If no images are
+// specified, the window reverts to its default icon.
+//
+// The image is ideally provided in the form of *image.NRGBA.
+// The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight
+// bits per channel with the red channel first. They are arranged canonically
+// as packed sequential rows, starting from the top-left corner. If the image
+// type is not *image.NRGBA, it will be converted to it.
+//
+// The desired image sizes varies depending on platform and system settings. The selected
+// images will be rescaled as needed. Good sizes include 16x16, 32x32 and 48x48.
+func (w *MasterWindow) SetIcon(icons []image.Image) {
+	w.platform.SetIcon(icons)
+}
+
+// SetSizeLimits sets the size limits of the client area of the specified window.
+// If the window is full screen or not resizable, this function does nothing.
+//
+// The size limits are applied immediately and may cause the window to be resized.
+// To specify only a minimum size or only a maximum one, set the other pair to giu.DontCare.
+// To disable size limits for a window, set them all to giu.DontCare.
+func (w *MasterWindow) SetSizeLimits(minw, minh, maxw, maxh int) {
+	w.platform.SetSizeLimits(minw, minh, maxw, maxh)
+}
+
+// SetTitle updates master window's title.
+func (w *MasterWindow) SetTitle(title string) {
+	w.platform.SetTitle(title)
+}
+
+// Close will savely close the master window.
+func (w *MasterWindow) Close() {
+	w.SetShouldClose(true)
+}
+
+// SetShouldClose sets whether master window should be closed.
+func (w *MasterWindow) SetShouldClose(v bool) {
+	w.platform.SetShouldStop(v)
+}
+
+// SetInputHandler allows to change default input handler.
+// see InputHandler.go.
+func (w *MasterWindow) SetInputHandler(handler InputHandler) {
+	Context.InputHandler = handler
+	w.platform.SetInputCallback(func(key glfw.Key, modifier glfw.ModifierKey, action glfw.Action) {
+		if action == glfw.Press {
+			handler.Handle(Key(key), Modifier(modifier))
+		}
+	})
+}

+ 60 - 0
vendor/github.com/AllenDang/giu/MemoryEditor.go

@@ -0,0 +1,60 @@
+package giu
+
+import (
+	"github.com/AllenDang/imgui-go"
+)
+
+type memoryEditorState struct {
+	editor imgui.MemoryEditor
+}
+
+// Dispose implements Disposable interface.
+func (s *memoryEditorState) Dispose() {
+	// noop
+}
+
+// MemoryEditorWidget - Mini memory editor for Dear ImGui
+// (to embed in your game/tools)
+//
+// Right-click anywhere to access the Options menu!
+// You can adjust the keyboard repeat delay/rate in ImGuiIO.
+// The code assume a mono-space font for simplicity!
+// If you don't use the default font, use ImGui::PushFont()/PopFont() to switch to a mono-space font before calling this.
+type MemoryEditorWidget struct {
+	id       string
+	contents []byte
+}
+
+// MemoryEditor creates nwe memory editor widget.
+func MemoryEditor() *MemoryEditorWidget {
+	return &MemoryEditorWidget{
+		id: GenAutoID("memoryEditor"),
+	}
+}
+
+// Contents sets editor's conents.
+func (me *MemoryEditorWidget) Contents(contents []byte) *MemoryEditorWidget {
+	me.contents = contents
+	return me
+}
+
+// Build implements widget inetrface.
+func (me *MemoryEditorWidget) Build() {
+	me.getState().editor.DrawContents(me.contents)
+}
+
+func (me *MemoryEditorWidget) getState() (state *memoryEditorState) {
+	if s := Context.GetState(me.id); s == nil {
+		state = &memoryEditorState{
+			editor: imgui.NewMemoryEditor(),
+		}
+
+		Context.SetState(me.id, state)
+	} else {
+		var ok bool
+		state, ok = s.(*memoryEditorState)
+		Assert(ok, "MemoryEditorWidget", "getState", "incorrect state type recovered.")
+	}
+
+	return state
+}

+ 179 - 0
vendor/github.com/AllenDang/giu/Msgbox.go

@@ -0,0 +1,179 @@
+package giu
+
+import "fmt"
+
+// DialogResult represents dialog result
+// dialog resullt is bool. if OK/Yes it is true, else (Cancel/No) - false.
+type DialogResult bool
+
+// dialog results.
+const (
+	DialogResultOK     DialogResult = true
+	DialogResultCancel DialogResult = false
+
+	DialogResultYes = DialogResultOK
+	DialogResultNo  = DialogResultCancel
+)
+
+// MsgboxButtons determines which buttons are in the dialog.
+type MsgboxButtons uint8
+
+// button sets.
+const (
+	// Yes-No question.
+	MsgboxButtonsYesNo MsgboxButtons = 1 << iota
+	// Ok / Cancel dialog.
+	MsgboxButtonsOkCancel
+	// info.
+	MsgboxButtonsOk
+)
+
+// DialogResultCallback is a callback for dialogs.
+type DialogResultCallback func(DialogResult)
+
+var _ Disposable = &msgboxState{}
+
+type msgboxState struct {
+	title          string
+	content        string
+	resultCallback DialogResultCallback
+	buttons        MsgboxButtons
+	open           bool
+}
+
+// Dispose implements disposable interface.
+func (ms *msgboxState) Dispose() {
+	// Nothing to do here.
+}
+
+func msgboxInvokeCallback(result DialogResult, callback DialogResultCallback) {
+	CloseCurrentPopup()
+	if callback != nil {
+		callback(result)
+	}
+}
+
+func buildMsgboxButtons(buttons MsgboxButtons, callback DialogResultCallback) Layout {
+	switch buttons {
+	case MsgboxButtonsOk:
+		return Layout{
+			Button(" Ok ").OnClick(func() {
+				msgboxInvokeCallback(DialogResultOK, callback)
+			}),
+		}
+	case MsgboxButtonsOkCancel:
+		return Layout{
+			Row(
+				Button("  Ok  ").OnClick(func() {
+					msgboxInvokeCallback(DialogResultOK, callback)
+				}),
+				Button("Cancel").OnClick(func() {
+					msgboxInvokeCallback(DialogResultCancel, callback)
+				}),
+			),
+		}
+	case MsgboxButtonsYesNo:
+		return Layout{
+			Row(
+				Button(" Yes ").OnClick(func() {
+					msgboxInvokeCallback(DialogResultYes, callback)
+				}),
+				Button("  No  ").OnClick(func() {
+					msgboxInvokeCallback(DialogResultNo, callback)
+				}),
+			),
+		}
+	default:
+		return Layout{
+			Button("  Ok  ").OnClick(func() {
+				msgboxInvokeCallback(DialogResultOK, callback)
+			}),
+		}
+	}
+}
+
+const msgboxID string = "###Msgbox"
+
+// PrepareMsgbox should be invoked in function in the same layout level where you call g.Msgbox.
+// BUG: calling this more than 1 time per frame causes unexpected
+// merging msgboxes layouts (see https://github.com/AllenDang/giu/issues/290)
+func PrepareMsgbox() Layout {
+	return Layout{
+		Custom(func() {
+			var state *msgboxState
+
+			// Register state.
+			stateRaw := Context.GetState(msgboxID)
+
+			if stateRaw == nil {
+				state = &msgboxState{title: "Info", content: "Content", buttons: MsgboxButtonsOk, resultCallback: nil, open: false}
+				Context.SetState(msgboxID, state)
+			} else {
+				var isOk bool
+				state, isOk = stateRaw.(*msgboxState)
+				Assert(isOk, "MsgboxWidget", "PrepareMsgbox", "got state of unexpected type")
+			}
+
+			if state.open {
+				OpenPopup(msgboxID)
+				state.open = false
+			}
+			SetNextWindowSize(300, 0)
+			PopupModal(fmt.Sprintf("%s%s", state.title, msgboxID)).Layout(
+				Custom(func() {
+					// Ensure the state is valid.
+					Context.GetState(msgboxID)
+				}),
+				Label(state.content).Wrapped(true),
+				buildMsgboxButtons(state.buttons, state.resultCallback),
+			).Build()
+		}),
+	}
+}
+
+// MsgboxWidget represents message dialog.
+type MsgboxWidget struct{}
+
+func (m *MsgboxWidget) getState() *msgboxState {
+	stateRaw := Context.GetState(msgboxID)
+	if stateRaw == nil {
+		panic("Msgbox is not prepared. Invoke giu.PrepareMsgbox in the end of the layout.")
+	}
+
+	result, isOk := stateRaw.(*msgboxState)
+	Assert(isOk, "MsgboxWidget", "getState", "unexpected type of widget's state recovered")
+
+	return result
+}
+
+// Msgbox opens message box.
+// call it whenever you want to open popup with
+// question / info.
+func Msgbox(title, content string) *MsgboxWidget {
+	result := &MsgboxWidget{}
+
+	state := result.getState()
+	state.title = title
+	state.content = content
+
+	state.buttons = MsgboxButtonsOk
+	state.resultCallback = nil
+
+	state.open = true
+
+	return result
+}
+
+// Buttons sets which buttons should be possible.
+func (m *MsgboxWidget) Buttons(buttons MsgboxButtons) *MsgboxWidget {
+	s := m.getState()
+	s.buttons = buttons
+	return m
+}
+
+// ResultCallback sets result callback.
+func (m *MsgboxWidget) ResultCallback(cb DialogResultCallback) *MsgboxWidget {
+	s := m.getState()
+	s.resultCallback = cb
+	return m
+}

+ 467 - 0
vendor/github.com/AllenDang/giu/Plot.go

@@ -0,0 +1,467 @@
+package giu
+
+import (
+	"image"
+
+	"github.com/AllenDang/imgui-go"
+)
+
+// PlotWidget is implemented by all the particular plots, which can be used
+// in (*PlotCanvasWidget).Plots.
+type PlotWidget interface {
+	Plot()
+}
+
+// ImPlotYAxis represents y axis settings.
+type ImPlotYAxis int
+
+// ImPlotYAxis enum:.
+const (
+	ImPlotYAxisLeft          ImPlotYAxis = 0 // left (default)
+	ImPlotYAxisFirstOnRight  ImPlotYAxis = 1 // first on right side
+	ImPlotYAxisSecondOnRight ImPlotYAxis = 2 // second on right side
+)
+
+// PlotTicker represents axis ticks.
+type PlotTicker struct {
+	Position float64
+	Label    string
+}
+
+// PlotCanvasWidget represents a giu plot widget.
+type PlotCanvasWidget struct {
+	title                            string
+	xLabel                           string
+	yLabel                           string
+	width                            int
+	height                           int
+	flags                            PlotFlags
+	xFlags, yFlags, y2Flags, y3Flags PlotAxisFlags
+	y2Label                          string
+	y3Label                          string
+	xMin, xMax, yMin, yMax           float64
+	axisLimitCondition               ExecCondition
+	xTicksValue, yTicksValue         []float64
+	xTicksLabel, yTicksLabel         []string
+	xTicksShowDefault                bool
+	yTicksShowDefault                bool
+	yTicksYAxis                      ImPlotYAxis
+	plots                            []PlotWidget
+}
+
+// Plot adds creates a new plot widget.
+func Plot(title string) *PlotCanvasWidget {
+	return &PlotCanvasWidget{
+		title:              title,
+		xLabel:             "",
+		yLabel:             "",
+		width:              -1,
+		height:             0,
+		flags:              PlotFlagsNone,
+		xFlags:             PlotAxisFlagsNone,
+		yFlags:             PlotAxisFlagsNone,
+		y2Flags:            PlotAxisFlagsNoGridLines,
+		y3Flags:            PlotAxisFlagsNoGridLines,
+		y2Label:            "",
+		y3Label:            "",
+		xMin:               0,
+		xMax:               10,
+		yMin:               0,
+		yMax:               10,
+		xTicksShowDefault:  true,
+		yTicksShowDefault:  true,
+		yTicksYAxis:        0,
+		axisLimitCondition: ConditionOnce,
+	}
+}
+
+// AxisLimits sets X and Y axis limits.
+func (p *PlotCanvasWidget) AxisLimits(xmin, xmax, ymin, ymax float64, cond ExecCondition) *PlotCanvasWidget {
+	p.xMin = xmin
+	p.xMax = xmax
+	p.yMin = ymin
+	p.yMax = ymax
+	p.axisLimitCondition = cond
+
+	return p
+}
+
+// XTicks sets x axis ticks.
+func (p *PlotCanvasWidget) XTicks(ticks []PlotTicker, showDefault bool) *PlotCanvasWidget {
+	length := len(ticks)
+	if length == 0 {
+		return p
+	}
+
+	values := make([]float64, length)
+	labels := make([]string, length)
+
+	for i, t := range ticks {
+		values[i] = t.Position
+		labels[i] = t.Label
+	}
+
+	p.xTicksValue = values
+	p.xTicksLabel = labels
+	p.xTicksShowDefault = showDefault
+	return p
+}
+
+// YTicks sets y axis ticks.
+func (p *PlotCanvasWidget) YTicks(ticks []PlotTicker, showDefault bool, yAxis ImPlotYAxis) *PlotCanvasWidget {
+	length := len(ticks)
+	if length == 0 {
+		return p
+	}
+
+	values := make([]float64, length)
+	labels := make([]string, length)
+
+	for i, t := range ticks {
+		values[i] = t.Position
+		labels[i] = t.Label
+	}
+
+	p.yTicksValue = values
+	p.yTicksLabel = labels
+	p.yTicksShowDefault = showDefault
+	p.yTicksYAxis = yAxis
+	return p
+}
+
+// Flags sets plot canvas flags.
+func (p *PlotCanvasWidget) Flags(flags PlotFlags) *PlotCanvasWidget {
+	p.flags = flags
+	return p
+}
+
+// XAxeFlags sets x axis fags.
+func (p *PlotCanvasWidget) XAxeFlags(flags PlotAxisFlags) *PlotCanvasWidget {
+	p.xFlags = flags
+	return p
+}
+
+// YAxeFlags sets y axis flags.
+func (p *PlotCanvasWidget) YAxeFlags(yFlags, y2Flags, y3Flags PlotAxisFlags) *PlotCanvasWidget {
+	p.yFlags = yFlags
+	p.y2Flags = y2Flags
+	p.y3Flags = y3Flags
+	return p
+}
+
+// Plots adds plots to plot canvas.
+func (p *PlotCanvasWidget) Plots(plots ...PlotWidget) *PlotCanvasWidget {
+	p.plots = plots
+	return p
+}
+
+// Size set canvas size.
+func (p *PlotCanvasWidget) Size(width, height int) *PlotCanvasWidget {
+	p.width = width
+	p.height = height
+	return p
+}
+
+// Build implements Widget interface.
+func (p *PlotCanvasWidget) Build() {
+	if len(p.plots) > 0 {
+		imgui.ImPlotSetNextPlotLimits(p.xMin, p.xMax, p.yMin, p.yMax, imgui.Condition(p.axisLimitCondition))
+
+		if len(p.xTicksValue) > 0 {
+			imgui.ImPlotSetNextPlotTicksX(p.xTicksValue, p.xTicksLabel, p.xTicksShowDefault)
+		}
+
+		if len(p.yTicksValue) > 0 {
+			imgui.ImPlotSetNextPlotTicksY(p.yTicksValue, p.yTicksLabel, p.yTicksShowDefault, int(p.yTicksYAxis))
+		}
+
+		if imgui.ImPlotBegin(
+			tStr(p.title), tStr(p.xLabel),
+			tStr(p.yLabel), ToVec2(image.Pt(p.width, p.height)),
+			imgui.ImPlotFlags(p.flags), imgui.ImPlotAxisFlags(p.xFlags),
+			imgui.ImPlotAxisFlags(p.yFlags), imgui.ImPlotAxisFlags(p.y2Flags),
+			imgui.ImPlotAxisFlags(p.y3Flags), tStr(p.y2Label), tStr(p.y3Label),
+		) {
+			for _, plot := range p.plots {
+				plot.Plot()
+			}
+			imgui.ImPlotEnd()
+		}
+	}
+}
+
+// PlotBarWidget adds bar plot (column chart) to the canvas.
+type PlotBarWidget struct {
+	title  string
+	data   []float64
+	width  float64
+	shift  float64
+	offset int
+}
+
+// PlotBar adds a plot bar (column chart).
+func PlotBar(title string, data []float64) *PlotBarWidget {
+	return &PlotBarWidget{
+		title:  title,
+		data:   data,
+		width:  0.2,
+		shift:  0,
+		offset: 0,
+	}
+}
+
+// Width sets bar width.
+func (p *PlotBarWidget) Width(width float64) *PlotBarWidget {
+	p.width = width
+	return p
+}
+
+// Shift sets shift of the bar.
+func (p *PlotBarWidget) Shift(shift float64) *PlotBarWidget {
+	p.shift = shift
+	return p
+}
+
+// Offset sets bar's offset.
+func (p *PlotBarWidget) Offset(offset int) *PlotBarWidget {
+	p.offset = offset
+	return p
+}
+
+// Plot implements Plot interface.
+func (p *PlotBarWidget) Plot() {
+	imgui.ImPlotBars(p.title, p.data, p.width, p.shift, p.offset)
+}
+
+// PlotBarHWidget represents a column chart on Y axis.
+type PlotBarHWidget struct {
+	title  string
+	data   []float64
+	height float64
+	shift  float64
+	offset int
+}
+
+// PlotBarH adds plot bars on y axis.
+func PlotBarH(title string, data []float64) *PlotBarHWidget {
+	return &PlotBarHWidget{
+		title:  title,
+		data:   data,
+		height: 0.2,
+		shift:  0,
+		offset: 0,
+	}
+}
+
+// Height sets bar height (in fact bars' width).
+func (p *PlotBarHWidget) Height(height float64) *PlotBarHWidget {
+	p.height = height
+	return p
+}
+
+// Shift sets shift.
+func (p *PlotBarHWidget) Shift(shift float64) *PlotBarHWidget {
+	p.shift = shift
+	return p
+}
+
+// Offset sets offset.
+func (p *PlotBarHWidget) Offset(offset int) *PlotBarHWidget {
+	p.offset = offset
+	return p
+}
+
+// Plot implements plot interface.
+func (p *PlotBarHWidget) Plot() {
+	imgui.ImPlotBarsH(tStr(p.title), p.data, p.height, p.shift, p.offset)
+}
+
+// PlotLineWidget represents a plot line (linear chart).
+type PlotLineWidget struct {
+	title      string
+	values     []float64
+	xScale, x0 float64
+	offset     int
+	yAxis      ImPlotYAxis
+}
+
+// PlotLine adds a new plot line to the canvas.
+func PlotLine(title string, values []float64) *PlotLineWidget {
+	return &PlotLineWidget{
+		title:  title,
+		values: values,
+		xScale: 1,
+		x0:     0,
+		offset: 0,
+	}
+}
+
+// SetPlotYAxis sets yAxis parameters.
+func (p *PlotLineWidget) SetPlotYAxis(yAxis ImPlotYAxis) *PlotLineWidget {
+	p.yAxis = yAxis
+	return p
+}
+
+// XScale sets x-axis-scale.
+func (p *PlotLineWidget) XScale(scale float64) *PlotLineWidget {
+	p.xScale = scale
+	return p
+}
+
+// X0 sets a start position on x axis.
+func (p *PlotLineWidget) X0(x0 float64) *PlotLineWidget {
+	p.x0 = x0
+	return p
+}
+
+// Offset sets chart offset.
+func (p *PlotLineWidget) Offset(offset int) *PlotLineWidget {
+	p.offset = offset
+	return p
+}
+
+// Plot implements Plot interface.
+func (p *PlotLineWidget) Plot() {
+	imgui.ImPlotSetPlotYAxis(imgui.ImPlotYAxis(p.yAxis))
+	imgui.ImPlotLine(tStr(p.title), p.values, p.xScale, p.x0, p.offset)
+}
+
+// PlotLineXYWidget adds XY plot line.
+type PlotLineXYWidget struct {
+	title  string
+	xs, ys []float64
+	offset int
+	yAxis  ImPlotYAxis
+}
+
+// PlotLineXY adds XY plot line to canvas.
+func PlotLineXY(title string, xvalues, yvalues []float64) *PlotLineXYWidget {
+	return &PlotLineXYWidget{
+		title:  title,
+		xs:     xvalues,
+		ys:     yvalues,
+		offset: 0,
+	}
+}
+
+// SetPlotYAxis sets yAxis parameters.
+func (p *PlotLineXYWidget) SetPlotYAxis(yAxis ImPlotYAxis) *PlotLineXYWidget {
+	p.yAxis = yAxis
+	return p
+}
+
+// Offset sets chart's offset.
+func (p *PlotLineXYWidget) Offset(offset int) *PlotLineXYWidget {
+	p.offset = offset
+	return p
+}
+
+// Plot implements Plot interface.
+func (p *PlotLineXYWidget) Plot() {
+	imgui.ImPlotSetPlotYAxis(imgui.ImPlotYAxis(p.yAxis))
+	imgui.ImPlotLineXY(tStr(p.title), p.xs, p.ys, p.offset)
+}
+
+// PlotPieChartWidget represents a pie chart.
+type PlotPieChartWidget struct {
+	labels       []string
+	values       []float64
+	x, y, radius float64
+	normalize    bool
+	labelFormat  string
+	angle0       float64
+}
+
+// PlotPieChart adds pie chart to the canvas.
+func PlotPieChart(labels []string, values []float64, x, y, radius float64) *PlotPieChartWidget {
+	return &PlotPieChartWidget{
+		labels:      labels,
+		values:      values,
+		x:           x,
+		y:           y,
+		radius:      radius,
+		normalize:   false,
+		labelFormat: "%.1f",
+		angle0:      90,
+	}
+}
+
+func (p *PlotPieChartWidget) Normalize(n bool) *PlotPieChartWidget {
+	p.normalize = n
+	return p
+}
+
+// LabelFormat sets format of labels.
+func (p *PlotPieChartWidget) LabelFormat(fmtStr string) *PlotPieChartWidget {
+	p.labelFormat = fmtStr
+	return p
+}
+
+func (p *PlotPieChartWidget) Angle0(a float64) *PlotPieChartWidget {
+	p.angle0 = a
+	return p
+}
+
+func (p *PlotPieChartWidget) Plot() {
+	imgui.ImPlotPieChart(tStrSlice(p.labels), p.values, p.x, p.y, p.radius, p.normalize, p.labelFormat, p.angle0)
+}
+
+type PlotScatterWidget struct {
+	label      string
+	values     []float64
+	xscale, x0 float64
+	offset     int
+}
+
+func PlotScatter(label string, values []float64) *PlotScatterWidget {
+	return &PlotScatterWidget{
+		label:  label,
+		values: values,
+		xscale: 1,
+		x0:     0,
+		offset: 0,
+	}
+}
+
+func (p *PlotScatterWidget) XScale(s float64) *PlotScatterWidget {
+	p.xscale = s
+	return p
+}
+
+func (p *PlotScatterWidget) X0(x float64) *PlotScatterWidget {
+	p.x0 = x
+	return p
+}
+
+func (p *PlotScatterWidget) Offset(offset int) *PlotScatterWidget {
+	p.offset = offset
+	return p
+}
+
+func (p *PlotScatterWidget) Plot() {
+	imgui.ImPlotScatter(tStr(p.label), p.values, p.xscale, p.x0, p.offset)
+}
+
+type PlotScatterXYWidget struct {
+	label  string
+	xs, ys []float64
+	offset int
+}
+
+func PlotScatterXY(label string, xs, ys []float64) *PlotScatterXYWidget {
+	return &PlotScatterXYWidget{
+		label:  label,
+		xs:     xs,
+		ys:     ys,
+		offset: 0,
+	}
+}
+
+func (p *PlotScatterXYWidget) Offset(offset int) *PlotScatterXYWidget {
+	p.offset = offset
+	return p
+}
+
+func (p *PlotScatterXYWidget) Plot() {
+	imgui.ImPlotScatterXY(tStr(p.label), p.xs, p.ys, p.offset)
+}

+ 105 - 0
vendor/github.com/AllenDang/giu/Popups.go

@@ -0,0 +1,105 @@
+package giu
+
+import (
+	"github.com/AllenDang/imgui-go"
+)
+
+// OpenPopup opens a popup with specified id.
+// NOTE: you need to build this popup first (see Pop(Modal)Widget).
+func OpenPopup(name string) {
+	imgui.OpenPopup(name)
+}
+
+// CloseCurrentPopup closes currently opened popup.
+// If no popups opened, no action will be taken.
+func CloseCurrentPopup() {
+	imgui.CloseCurrentPopup()
+}
+
+var _ Widget = &PopupWidget{}
+
+// PopupWidget  is a window which appears next to the mouse cursor.
+// For instance it is used to display color palette in ColorSelectWidget.
+type PopupWidget struct {
+	name   string
+	flags  WindowFlags
+	layout Layout
+}
+
+// Popup creates new popup widget.
+func Popup(name string) *PopupWidget {
+	return &PopupWidget{
+		name:   tStr(name),
+		flags:  0,
+		layout: nil,
+	}
+}
+
+// Flags sets pupup's flags.
+func (p *PopupWidget) Flags(flags WindowFlags) *PopupWidget {
+	p.flags = flags
+	return p
+}
+
+// Layout sets popup's layout.
+func (p *PopupWidget) Layout(widgets ...Widget) *PopupWidget {
+	p.layout = Layout(widgets)
+	return p
+}
+
+// Build implements Widget interface.
+func (p *PopupWidget) Build() {
+	if imgui.BeginPopup(p.name, int(p.flags)) {
+		p.layout.Build()
+		imgui.EndPopup()
+	}
+}
+
+var _ Widget = &PopupModalWidget{}
+
+// PopupModalWidget is a popup window that block every interactions behind it, cannot be closed by
+// user, adds a dimming background, has a title bar.
+type PopupModalWidget struct {
+	name   string
+	open   *bool
+	flags  WindowFlags
+	layout Layout
+}
+
+// PopupModal creates new popup modal widget.
+func PopupModal(name string) *PopupModalWidget {
+	return &PopupModalWidget{
+		name:   tStr(name),
+		open:   nil,
+		flags:  WindowFlagsNoResize,
+		layout: nil,
+	}
+}
+
+// IsOpen allows to control popup's state
+// NOTE: changing opens' value will not result in changing popup's state
+// if OpenPopup(...) wasn't called!
+func (p *PopupModalWidget) IsOpen(open *bool) *PopupModalWidget {
+	p.open = open
+	return p
+}
+
+// Flags allows to specify popup's flags.
+func (p *PopupModalWidget) Flags(flags WindowFlags) *PopupModalWidget {
+	p.flags = flags
+	return p
+}
+
+// Layout sets layout.
+func (p *PopupModalWidget) Layout(widgets ...Widget) *PopupModalWidget {
+	p.layout = Layout(widgets)
+	return p
+}
+
+// Build implements Widget interface.
+func (p *PopupModalWidget) Build() {
+	if imgui.BeginPopupModalV(p.name, p.open, int(p.flags)) {
+		p.layout.Build()
+		imgui.EndPopup()
+	}
+}

+ 107 - 0
vendor/github.com/AllenDang/giu/ProgressIndicator.go

@@ -0,0 +1,107 @@
+package giu
+
+import (
+	"image"
+	"math"
+	"time"
+
+	"github.com/AllenDang/imgui-go"
+)
+
+var _ Disposable = &progressIndicatorState{}
+
+type progressIndicatorState struct {
+	angle float64
+	stop  bool
+}
+
+func (ps *progressIndicatorState) update() {
+	ticker := time.NewTicker(time.Second / 60)
+	for !ps.stop {
+		if ps.angle > 6.2 {
+			ps.angle = 0
+		}
+		ps.angle += 0.1
+
+		Update()
+		<-ticker.C
+	}
+
+	ticker.Stop()
+}
+
+// Dispose implements Disposable interface.
+func (ps *progressIndicatorState) Dispose() {
+	ps.stop = true
+}
+
+// static check to ensure if ProgressIndicatorWidget implements Widget interface.
+var _ Widget = &ProgressIndicatorWidget{}
+
+// ProgressIndicatorWidget represents progress indicator widget
+// see examples/extrawidgets/.
+type ProgressIndicatorWidget struct {
+	internalID string
+	width      float32
+	height     float32
+	radius     float32
+	label      string
+}
+
+// ProgressIndicator creates a new ProgressIndicatorWidget.
+func ProgressIndicator(label string, width, height, radius float32) *ProgressIndicatorWidget {
+	return &ProgressIndicatorWidget{
+		internalID: "###giu-progress-indicator",
+		width:      width,
+		height:     height,
+		radius:     radius,
+		label:      label,
+	}
+}
+
+// Build implements Widget interface.
+func (p *ProgressIndicatorWidget) Build() {
+	// State exists
+	if s := Context.GetState(p.internalID); s == nil {
+		// Register state and start go routine
+		ps := progressIndicatorState{angle: 0.0, stop: false}
+		Context.SetState(p.internalID, &ps)
+		go ps.update()
+	} else {
+		var isOk bool
+		state, isOk := s.(*progressIndicatorState)
+		Assert(isOk, "ProgressIndicatorWidget", "Build", "got unexpected type of widget's sate")
+
+		child := Child().Border(false).Size(p.width, p.height).Layout(Layout{
+			Custom(func() {
+				// Process width and height
+				width, height := GetAvailableRegion()
+
+				canvas := GetCanvas()
+
+				pos := GetCursorScreenPos()
+
+				centerPt := pos.Add(image.Pt(int(width/2), int(height/2)))
+				centerPt2 := image.Pt(
+					int(float64(p.radius)*math.Sin(state.angle)+float64(centerPt.X)),
+					int(float64(p.radius)*math.Cos(state.angle)+float64(centerPt.Y)),
+				)
+
+				color := imgui.CurrentStyle().GetColor(imgui.StyleColorText)
+				rgba := Vec4ToRGBA(color)
+
+				canvas.AddCircle(centerPt, p.radius, rgba, int(p.radius), p.radius/20.0)
+				canvas.AddCircleFilled(centerPt2, p.radius/5, rgba)
+
+				// Draw text
+				if len(p.label) > 0 {
+					labelWidth, _ := CalcTextSize(tStr(p.label))
+					labelPos := centerPt.Add(image.Pt(-1*int(labelWidth/2), int(p.radius+p.radius/5+8)))
+					canvas.AddText(labelPos, rgba, p.label)
+				}
+			}),
+		})
+
+		child.Build()
+	}
+}

+ 219 - 0
vendor/github.com/AllenDang/giu/README.md

@@ -0,0 +1,219 @@
+# giu
+
+[![codecov](https://codecov.io/gh/AllenDang/giu/branch/master/graph/badge.svg)](https://codecov.io/gh/AllenDang/giu)
+[![Join the chat at https://gitter.im/AllenDang-giu/community](https://badges.gitter.im/AllenDang-giu/community.svg)](https://gitter.im/AllenDang-giu/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[![Go Report Card](https://goreportcard.com/badge/github.com/AllenDang/giu)](https://goreportcard.com/report/github.com/AllenDang/giu)
+![Build Status](https://github.com/AllenDang/giu/actions/workflows/build.yml/badge.svg)
+[![Godoc Card](https://camo.githubusercontent.com/fd3cd5d5f44237541b35fcfdcba2fd4466a60c12/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f476f646f632d7265666572656e63652d626c75652e737667)](https://pkg.go.dev/github.com/AllenDang/giu?tab=doc)
+
+A rapid cross-platform GUI framework for Go based on [Dear ImGui](https://github.com/ocornut/imgui) and the great Go binding [imgui-go](https://github.com/inkyblackness/imgui-go).
+
+Any contribution (features, widgets, tutorials, documents, etc...) is appreciated!
+
+## Sponsor
+(This library is available under a free and permissive license, but needs financial support to sustain its continued improvements. In addition to maintenance and stability there are many desirable features yet to be added. If you are using giu, please consider reaching out.)
+
+Businesses: support continued development and maintenance via invoiced technical support, maintenance, sponsoring contracts:
+
+E-mail: allengnr@gmail.com
+
+Individuals: support continued development and maintenance [here](https://patreon.com/AllenDang).
+
+## Supported Platforms
+
+giu is built upon GLFW v3.3, so ideally giu could support all platforms that GLFW v3.3 supports.
+
+- Windows (Windows 10 x64 and Windows 11 x64)
+- macOS (macOS v10.15 and macOS Big Sur)
+- Linux (thanks remeh for testing it)
+- Raspberry Pi 3B (thanks sndvaps for testing it)
+
+## Features
+
+Compared to other Dear ImGui golang bindings, giu has the following features:
+
+- Small executable file size (<3MB after UPX compression for the example/helloworld demo).
+- Live-updating during the resizing of the OS window (implemented on GLFW 3.3 and OpenGL 3.2).
+- Support for displaying various languages without any font setting. Giu will rebuild font atlas incrementally according to texts in UI between frames.
+- Redraws only when user event occurs. Costs only 0.5% CPU usage with 60FPS.
+- Declarative UI (see examples for more details).
+- DPI awareness (auto scaling font and UI to adapt to high DPI monitors).
+- Drop in usage; no need to implement render and platform.
+- OS clipboard support.
+
+![Screenshot](https://github.com/AllenDang/giu/raw/master/examples/imguidemo/screenshot.png)
+![Screenshot1](https://github.com/AllenDang/giu/blob/master/screenshots/SqlPower.png)
+![Screenshot2](https://github.com/AllenDang/giu/blob/master/screenshots/Chart.png)
+
+## Hello world
+
+```go
+package main
+
+import (
+	"fmt"
+
+	g "github.com/AllenDang/giu"
+)
+
+func onClickMe() {
+	fmt.Println("Hello world!")
+}
+
+func onImSoCute() {
+	fmt.Println("Im sooooooo cute!!")
+}
+
+func loop() {
+	g.SingleWindow().Layout(
+		g.Label("Hello world from giu"),
+		g.Row(
+			g.Button("Click Me").OnClick(onClickMe),
+			g.Button("I'm so cute").OnClick(onImSoCute),
+		),
+	)
+}
+
+func main() {
+	wnd := g.NewMasterWindow("Hello world", 400, 200, g.MasterWindowFlagsNotResizable)
+	wnd.Run(loop)
+}
+```
+
+Here is the result:
+
+![Helloworld](https://github.com/AllenDang/giu/raw/master/examples/helloworld/helloworld.png)
+
+## Quick introduction
+
+### What is immediate mode GUI?
+
+Immediate mode GUI system means the UI control doesn't retain its state and value. For example, calling `giu.InputText(&str)` will display a input text box on screen, and the user entered value will be stored in `&str`. Input text box doesn't know anything about it.
+
+And the `loop` method in the _Hello world_ example is in charge of **drawing** all widgets based on the parameters passed into them. This method will be invoked 30 times per second to reflect interactive states (like clicked, hovered, value-changed, etc.). It will be the place you define the UI structure.
+
+### The layout and sizing system
+
+By default, any widget placed inside a container's `Layout` will be placed vertically.
+
+To create a row of widgets (i.e. place widgets one by one horizontally), use the `Row()` method. For example `giu.Row(Label(...), Button(...))` will create a Label next to a Button.
+
+To create a column of widgets (i.e. place widgets one by one vertically) inside a row, use the `Column()` method.
+
+Any widget that has a `Size()` method, can set its size explicitly. Note that you can pass a negative value to `Size()`, which will fill the remaining width/height value. For example, `InputText(...).Size(giu.Auto)` will create an input text box with the longest width that its container has left.
+
+### Containers
+
+#### MasterWindow
+
+A `MasterWindow` means the platform native window implemented by the OS. All subwindows and widgets will be placed inside it.
+
+#### Window
+
+A `Window` is a container with a title bar, and can be collapsed. `SingleWindow` is a special kind of window that will occupy all the available space of `MasterWindow`.
+
+#### Child
+
+A `Child` is like a panel in other GUI frameworks - it can have a background color and border.
+
+### Widgets
+
+Check `examples/widgets` for all kinds of widgets.
+
+## Install
+
+The backend of giu depends on OpenGL 3.3, make sure your environment supports it (as far as I know, some Virtual Machines like VirtualBox doesn't support it).
+
+### MacOS
+
+```sh
+xcode-select --install
+go get github.com/AllenDang/giu
+```
+
+### Windows
+
+1. Install mingw [download here](https://github.com/brechtsanders/winlibs_mingw/releases/latest). Thanks @alchem1ster!
+2. Add the binaries folder of mingw to the path (usually is _\mingw64\bin_).
+3. go get github.com/AllenDang/giu
+
+Or, install [TDM-GCC](https://jmeubank.github.io/tdm-gcc/).
+
+### Linux
+
+First you need to install the required dependencies:
+
+```bash
+sudo apt install libx11-dev libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev libglx-dev libgl1-mesa-dev libxxf86vm-dev
+```
+
+on Red Hat based distributions:
+```bash
+sudo dnf install libX11-devel libXcursor-devel libXrandr-devel libXinerama-devel libXi-devel libGL-devel libXxf86vm-devel
+```
+
+you may also need to install C/C++ compiller (like g++) if it isn't already installed. Follow go compilator prompts.
+
+Then, a simple `go build` will work.
+
+Cross-compiling is a bit more complicated. Let's say that you want to build for arm64. This is what you would need to do:
+
+```bash
+sudo dpkg --add-architecture arm64
+sudo apt update
+sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu \
+    libx11-dev:arm64 libxcursor-dev:arm64 libxrandr-dev:arm64 libxinerama-dev:arm64 libxi-dev:arm64 libglx-dev:arm64 libgl1-mesa-dev:arm64 libxxf86vm-dev:arm64
+GOOS=linux GOARCH=arm64 CGO_ENABLED=1 CC=aarch64-linux-gnu-gcc CXX=aarch64-linux-gnu-g++ HOST=aarch64-linux-gnu go build -v
+```
+
+## Deploying
+
+### Build MacOS version on MacOS.
+
+```sh
+go build -ldflags "-s -w" .
+```
+
+### Build Windows version on Windows.
+
+```sh
+go build -ldflags "-s -w -H=windowsgui -extldflags=-static" .
+```
+
+### Build Windows version on MacOS/Linux.
+
+1. Install mingw-64.
+
+on Mac:
+```sh
+brew install mingw-w64
+```
+
+on Linux:
+
+```sh
+sudo dnf install mingw64-gcc mingw64-gcc-c++ mingw-winpthreads-static
+```
+
+2. Prepare and embed the application icon into the executable and build.
+
+```sh
+cat > YourExeName.rc << EOL
+id ICON "./res/app_win.ico"
+GLFW_ICON ICON "./res/app_win.ico"
+EOL
+
+x86_64-w64-mingw32-windres YourExeName.rc -O coff -o YourExeName.syso
+GOOS=windows GOARCH=amd64 CGO_ENABLED=1 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++ HOST=x86_64-w64-mingw32 go build -ldflags "-s -w -H=windowsgui -extldflags=-static" -p 4 -v -o YourExeName.exe
+
+rm YourExeName.syso
+rm YourExeName.rc
+```
+
+## Documentation
+
+Check [Wiki](https://github.com/AllenDang/giu/wiki)
+
+## Contribution
+
+All kinds of pull requests (document, demo, screenshots, code, etc.) are more than welcome!

+ 226 - 0
vendor/github.com/AllenDang/giu/SliderWidgets.go

@@ -0,0 +1,226 @@
+package giu
+
+import (
+	"fmt"
+
+	"github.com/AllenDang/imgui-go"
+)
+
+var _ Widget = &SliderIntWidget{}
+
+// SliderIntWidget is a slider around int32 values.
+type SliderIntWidget struct {
+	label    string
+	value    *int32
+	min      int32
+	max      int32
+	format   string
+	width    float32
+	onChange func()
+}
+
+// SliderInt constructs new SliderIntWidget.
+func SliderInt(value *int32, min, max int32) *SliderIntWidget {
+	return &SliderIntWidget{
+		label:    GenAutoID("##SliderInt"),
+		value:    value,
+		min:      min,
+		max:      max,
+		format:   "%d",
+		width:    0,
+		onChange: nil,
+	}
+}
+
+// Format sets data format displayed on the slider
+// NOTE: on C side of imgui, it will be processed like:
+// fmt.Sprintf(format, currentValue) so you can do e.g.
+// SLiderInt(...).Format("My age is %d") and %d will be replaced with current value.
+func (s *SliderIntWidget) Format(format string) *SliderIntWidget {
+	s.format = format
+	return s
+}
+
+// Size sets slider's width.
+func (s *SliderIntWidget) Size(width float32) *SliderIntWidget {
+	s.width = width
+	return s
+}
+
+// OnChange sets callback when slider's position gets changed.
+func (s *SliderIntWidget) OnChange(onChange func()) *SliderIntWidget {
+	s.onChange = onChange
+	return s
+}
+
+// Label sets slider label (id).
+func (s *SliderIntWidget) Label(label string) *SliderIntWidget {
+	s.label = tStr(label)
+	return s
+}
+
+// Labelf sets formated label.
+func (s *SliderIntWidget) Labelf(format string, args ...any) *SliderIntWidget {
+	return s.Label(fmt.Sprintf(format, args...))
+}
+
+// Build implements Widget interface.
+func (s *SliderIntWidget) Build() {
+	if s.width != 0 {
+		PushItemWidth(s.width)
+		defer PopItemWidth()
+	}
+
+	if imgui.SliderIntV(tStr(s.label), s.value, s.min, s.max, s.format) && s.onChange != nil {
+		s.onChange()
+	}
+}
+
+var _ Widget = &VSliderIntWidget{}
+
+// VSliderIntWidget stands from Vertical SliderIntWidget.
+type VSliderIntWidget struct {
+	label    string
+	width    float32
+	height   float32
+	value    *int32
+	min      int32
+	max      int32
+	format   string
+	flags    SliderFlags
+	onChange func()
+}
+
+// VSliderInt creates new vslider int.
+func VSliderInt(value *int32, min, max int32) *VSliderIntWidget {
+	return &VSliderIntWidget{
+		label:  GenAutoID("##VSliderInt"),
+		width:  18,
+		height: 60,
+		value:  value,
+		min:    min,
+		max:    max,
+		format: "%d",
+		flags:  SliderFlagsNone,
+	}
+}
+
+// Size sets slider's size.
+func (vs *VSliderIntWidget) Size(width, height float32) *VSliderIntWidget {
+	vs.width, vs.height = width, height
+	return vs
+}
+
+// Flags sets flags.
+func (vs *VSliderIntWidget) Flags(flags SliderFlags) *VSliderIntWidget {
+	vs.flags = flags
+	return vs
+}
+
+// Format sets format (see comment on (*SliderIntWidget).Format).
+func (vs *VSliderIntWidget) Format(format string) *VSliderIntWidget {
+	vs.format = format
+	return vs
+}
+
+// OnChange sets callback called when slider's position gets changed.
+func (vs *VSliderIntWidget) OnChange(onChange func()) *VSliderIntWidget {
+	vs.onChange = onChange
+	return vs
+}
+
+// Label sets slider's label (id).
+func (vs *VSliderIntWidget) Label(label string) *VSliderIntWidget {
+	vs.label = tStr(label)
+	return vs
+}
+
+// Labelf sets formated label.
+func (vs *VSliderIntWidget) Labelf(format string, args ...any) *VSliderIntWidget {
+	return vs.Label(fmt.Sprintf(format, args...))
+}
+
+// Build implements Widget interface.
+func (vs *VSliderIntWidget) Build() {
+	if imgui.VSliderIntV(
+		tStr(vs.label),
+		imgui.Vec2{X: vs.width, Y: vs.height},
+		vs.value,
+		vs.min,
+		vs.max,
+		vs.format,
+		int(vs.flags),
+	) && vs.onChange != nil {
+		vs.onChange()
+	}
+}
+
+var _ Widget = &SliderFloatWidget{}
+
+// SliderFloatWidget does similar to SliderIntWidget but slides around
+// float32 values.
+type SliderFloatWidget struct {
+	label    string
+	value    *float32
+	min      float32
+	max      float32
+	format   string
+	width    float32
+	onChange func()
+}
+
+// SliderFloat creates new slider float widget.
+func SliderFloat(value *float32, min, max float32) *SliderFloatWidget {
+	return &SliderFloatWidget{
+		label:    GenAutoID("##SliderFloat"),
+		value:    value,
+		min:      min,
+		max:      max,
+		format:   "%.3f",
+		width:    0,
+		onChange: nil,
+	}
+}
+
+// Format sets format of text displayed on the slider.
+// default is %.3f.
+func (sf *SliderFloatWidget) Format(format string) *SliderFloatWidget {
+	sf.format = format
+	return sf
+}
+
+// OnChange is callback called when slider's position gets changed.
+func (sf *SliderFloatWidget) OnChange(onChange func()) *SliderFloatWidget {
+	sf.onChange = onChange
+
+	return sf
+}
+
+// Size sets slider's width.
+func (sf *SliderFloatWidget) Size(width float32) *SliderFloatWidget {
+	sf.width = width
+	return sf
+}
+
+// Label sets slider's label (id).
+func (sf *SliderFloatWidget) Label(label string) *SliderFloatWidget {
+	sf.label = tStr(label)
+	return sf
+}
+
+// Labelf sets formated label.
+func (sf *SliderFloatWidget) Labelf(format string, args ...any) *SliderFloatWidget {
+	return sf.Label(fmt.Sprintf(format, args...))
+}
+
+// Build implements Widget interface.
+func (sf *SliderFloatWidget) Build() {
+	if sf.width != 0 {
+		PushItemWidth(sf.width)
+		defer PopItemWidth()
+	}
+
+	if imgui.SliderFloatV(tStr(sf.label), sf.value, sf.min, sf.max, sf.format, 1.0) && sf.onChange != nil {
+		sf.onChange()
+	}
+}

+ 173 - 0
vendor/github.com/AllenDang/giu/SplitLayout.go

@@ -0,0 +1,173 @@
+package giu
+
+import (
+	"image/color"
+
+	"github.com/AllenDang/imgui-go"
+)
+
+// SplitDirection represents a direction (vertical/horizontal) of splitting layout.
+type SplitDirection uint8
+
+const (
+	// DirectionHorizontal is a horizontal line.
+	DirectionHorizontal SplitDirection = 1 << iota
+	// DirectionVertical is a vertical line.
+	DirectionVertical
+)
+
+var _ Disposable = &splitLayoutState{}
+
+type splitLayoutState struct {
+	delta   float32
+	sashPos float32
+}
+
+// Dispose implements disposable interface.
+func (s *splitLayoutState) Dispose() {
+	// noop
+}
+
+// SplitLayoutWidget creates two childs with a line between them.
+// This line can be moved by the user to adjust child sizes.
+type SplitLayoutWidget struct {
+	id                  string
+	direction           SplitDirection
+	layout1             Widget
+	layout2             Widget
+	originItemSpacingX  float32
+	originItemSpacingY  float32
+	originFramePaddingX float32
+	originFramePaddingY float32
+	sashPos             float32
+	border              bool
+}
+
+// SplitLayout creates split layout widget.
+func SplitLayout(direction SplitDirection, sashPos float32, layout1, layout2 Widget) *SplitLayoutWidget {
+	return &SplitLayoutWidget{
+		direction: direction,
+		sashPos:   sashPos,
+		layout1:   layout1,
+		layout2:   layout2,
+		border:    true,
+		id:        GenAutoID("SplitLayout"),
+	}
+}
+
+// Border sets if childs should have borders.
+func (s *SplitLayoutWidget) Border(b bool) *SplitLayoutWidget {
+	s.border = b
+	return s
+}
+
+// ID allows to manually set splitter's id.
+func (s *SplitLayoutWidget) ID(id string) *SplitLayoutWidget {
+	s.id = id
+	return s
+}
+
+// Build implements widget interface.
+func (s *SplitLayoutWidget) Build() {
+	splitLayoutState := s.getState()
+	s.originItemSpacingX, s.originItemSpacingY = GetItemInnerSpacing()
+	s.originFramePaddingX, s.originFramePaddingY = GetFramePadding()
+
+	var layout Layout
+
+	splitLayoutState.sashPos += splitLayoutState.delta
+	if splitLayoutState.sashPos < 1 {
+		splitLayoutState.sashPos = 1
+	}
+
+	switch s.direction {
+	case DirectionHorizontal:
+		availableW, _ := GetAvailableRegion()
+		if splitLayoutState.sashPos >= availableW {
+			splitLayoutState.sashPos = availableW
+		}
+
+		layout = Layout{
+			Row(
+				s.buildChild(splitLayoutState.sashPos, 0, s.layout1),
+				VSplitter(&(splitLayoutState.delta)).Size(s.originItemSpacingX, 0),
+				s.buildChild(Auto, Auto, s.layout2),
+			),
+		}
+	case DirectionVertical:
+		_, availableH := GetAvailableRegion()
+		if splitLayoutState.sashPos >= availableH {
+			splitLayoutState.sashPos = availableH
+		}
+		layout = Layout{
+			Column(
+				s.buildChild(Auto, splitLayoutState.sashPos, s.layout1),
+				HSplitter(&(splitLayoutState.delta)).Size(0, s.originItemSpacingY),
+				s.buildChild(Auto, Auto, s.layout2),
+			),
+		}
+	}
+
+	PushItemSpacing(0, 0)
+	layout.Build()
+	PopStyle()
+}
+
+func (s *SplitLayoutWidget) restoreItemSpacing(layout Widget) Layout {
+	return Layout{
+		Custom(func() {
+			PushItemSpacing(s.originItemSpacingX, s.originItemSpacingY)
+			PushFramePadding(s.originFramePaddingX, s.originFramePaddingY)
+			// Restore Child bg color
+			bgColor := imgui.CurrentStyle().GetColor(imgui.StyleColorChildBg)
+			PushStyleColor(StyleColorChildBg, Vec4ToRGBA(bgColor))
+		}),
+		layout,
+		Custom(func() {
+			PopStyleColor()
+			PopStyleV(2)
+		}),
+	}
+}
+
+// Build Child panel. If layout is a SplitLayout, set the frame padding to zero.
+func (s *SplitLayoutWidget) buildChild(width, height float32, layout Widget) Widget {
+	return Layout{
+		Custom(func() {
+			_, isSplitLayoutWidget := layout.(*SplitLayoutWidget)
+			hasFramePadding := isSplitLayoutWidget || !s.border
+			hasBorder := !isSplitLayoutWidget && s.border
+
+			if hasFramePadding {
+				PushFramePadding(0, 0)
+			}
+
+			PushStyleColor(StyleColorChildBg, color.RGBA{R: 0, G: 0, B: 0, A: 0})
+
+			Child().
+				Border(hasBorder).
+				Size(width, height).
+				Layout(s.restoreItemSpacing(layout)).
+				Build()
+
+			PopStyleColor()
+
+			if hasFramePadding {
+				PopStyle()
+			}
+		}),
+	}
+}
+
+func (s *SplitLayoutWidget) getState() (state *splitLayoutState) {
+	if st := Context.GetState(s.id); st == nil {
+		state = &splitLayoutState{delta: 0.0, sashPos: s.sashPos}
+		Context.SetState(s.id, state)
+	} else {
+		var isOk bool
+		state, isOk = st.(*splitLayoutState)
+		Assert(isOk, "SplitLayoutWidget", "Build", "got unexpected type of widget's state")
+	}
+
+	return state
+}

+ 48 - 0
vendor/github.com/AllenDang/giu/StackWidget.go

@@ -0,0 +1,48 @@
+package giu
+
+import "github.com/AllenDang/imgui-go"
+
+var _ Widget = &StackWidget{}
+
+// StackWidget is used to ensure, that the build methods of all
+// the widgets (layouts field) was called, but only the selected
+// (visible field) layout is rendered (visible) in app.
+type StackWidget struct {
+	visible int32
+	layouts []Widget
+}
+
+// Stack creates a new StackWidget.
+func Stack(visible int32, layouts ...Widget) *StackWidget {
+	return &StackWidget{
+		visible: visible,
+		layouts: layouts,
+	}
+}
+
+// Build implements widget interface.
+func (s *StackWidget) Build() {
+	// save visible cursor position
+	visiblePos := GetCursorScreenPos()
+
+	// build visible layout
+	// NOTE: it is important to build the visiblely showed layout before
+	// building another ones, because the interactive layout widgets
+	// (e.g. buttons) should be rendered on top of `stack`
+	layouts := s.layouts
+
+	if s.visible >= 0 && s.visible < int32(len(s.layouts)) {
+		s.layouts[s.visible].Build()
+		// remove visible layout from layouts list
+		// nolint:gocritic // remove visible widget
+		layouts = append(s.layouts[:s.visible], s.layouts[:s.visible+1]...)
+	}
+
+	// build invisible layouts with 0 alpha
+	imgui.PushStyleVarFloat(imgui.StyleVarAlpha, 0)
+	for _, l := range layouts {
+		SetCursorScreenPos(visiblePos)
+		l.Build()
+	}
+	imgui.PopStyleVar()
+}

+ 479 - 0
vendor/github.com/AllenDang/giu/Style.go

@@ -0,0 +1,479 @@
+package giu
+
+import (
+	"image/color"
+
+	"github.com/AllenDang/imgui-go"
+)
+
+// PushFont sets font to "font"
+// NOTE: PopFont has to be called
+// NOTE: Don't use PushFont. use StyleSetter instead.
+func PushFont(font *FontInfo) bool {
+	if font == nil {
+		return false
+	}
+
+	if f, ok := extraFontMap[font.String()]; ok {
+		imgui.PushFont(*f)
+		return true
+	}
+
+	return false
+}
+
+// PopFont pops the font (should be called after PushFont).
+func PopFont() {
+	imgui.PopFont()
+}
+
+// PushStyleColor wrapps imgui.PushStyleColor
+// NOTE: don't forget to call PopStyleColor()!
+func PushStyleColor(id StyleColorID, col color.Color) {
+	imgui.PushStyleColor(imgui.StyleColorID(id), ToVec4Color(col))
+}
+
+// PushColorText calls PushStyleColor(StyleColorText,...)
+// NOTE: don't forget to call PopStyleColor()!
+func PushColorText(col color.Color) {
+	imgui.PushStyleColor(imgui.StyleColorText, ToVec4Color(col))
+}
+
+// PushColorTextDisabled calls PushStyleColor(StyleColorTextDisabled,...)
+// NOTE: don't forget to call PopStyleColor()!
+func PushColorTextDisabled(col color.Color) {
+	imgui.PushStyleColor(imgui.StyleColorTextDisabled, ToVec4Color(col))
+}
+
+// PushColorWindowBg calls PushStyleColor(StyleColorWindowBg,...)
+// NOTE: don't forget to call PopStyleColor()!
+func PushColorWindowBg(col color.Color) {
+	imgui.PushStyleColor(imgui.StyleColorWindowBg, ToVec4Color(col))
+}
+
+// PushColorFrameBg calls PushStyleColor(StyleColorFrameBg,...)
+// NOTE: don't forget to call PopStyleColor()!
+func PushColorFrameBg(col color.Color) {
+	imgui.PushStyleColor(imgui.StyleColorFrameBg, ToVec4Color(col))
+}
+
+// PushColorButton calls PushStyleColor(StyleColorButton,...)
+// NOTE: don't forget to call PopStyleColor()!
+func PushColorButton(col color.Color) {
+	imgui.PushStyleColor(imgui.StyleColorButton, ToVec4Color(col))
+}
+
+// PushColorButtonHovered calls PushStyleColor(StyleColorButtonHovered,...)
+// NOTE: don't forget to call PopStyleColor()!
+func PushColorButtonHovered(col color.Color) {
+	imgui.PushStyleColor(imgui.StyleColorButtonHovered, ToVec4Color(col))
+}
+
+// PushColorButtonActive calls PushStyleColor(StyleColorButtonActive,...)
+// NOTE: don't forget to call PopStyleColor()!
+func PushColorButtonActive(col color.Color) {
+	imgui.PushStyleColor(imgui.StyleColorButtonActive, ToVec4Color(col))
+}
+
+// PushWindowPadding calls PushStyleVar(StyleWindowPadding,...)
+func PushWindowPadding(width, height float32) {
+	imgui.PushStyleVarVec2(imgui.StyleVarWindowPadding, imgui.Vec2{X: width, Y: height})
+}
+
+// PushFramePadding calls PushStyleVar(StyleFramePadding,...)
+func PushFramePadding(width, height float32) {
+	imgui.PushStyleVarVec2(imgui.StyleVarFramePadding, imgui.Vec2{X: width, Y: height})
+}
+
+// PushItemSpacing calls PushStyleVar(StyleVarItemSpacing,...)
+func PushItemSpacing(width, height float32) {
+	imgui.PushStyleVarVec2(imgui.StyleVarItemSpacing, imgui.Vec2{X: width, Y: height})
+}
+
+// PushButtonTextAlign sets alignment for button text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered.
+func PushButtonTextAlign(width, height float32) {
+	imgui.PushStyleVarVec2(imgui.StyleVarButtonTextAlign, imgui.Vec2{X: width, Y: height})
+}
+
+// PushSelectableTextAlign sets alignment for selectable text. Defaults to (0.0f,0.5f) for left-aligned,vertically centered.
+func PushSelectableTextAlign(width, height float32) {
+	imgui.PushStyleVarVec2(imgui.StyleVarSelectableTextAlign, imgui.Vec2{X: width, Y: height})
+}
+
+// PopStyle should be called to stop applying style.
+// It should be called as much times, as you Called PushStyle...
+// NOTE: If you don't call PopStyle imgui will panic.
+func PopStyle() {
+	imgui.PopStyleVar()
+}
+
+// PopStyleV does similarly to PopStyle, but allows to specify number
+// of styles you're going to pop.
+func PopStyleV(count int) {
+	imgui.PopStyleVarV(count)
+}
+
+// PopStyleColor is used to stop applying colors styles.
+// It should be called after each PushStyleColor... (for each push)
+// If PopStyleColor wasn't called after PushColor... or was called
+// inproperly, imgui will panic.
+func PopStyleColor() {
+	imgui.PopStyleColor()
+}
+
+// PopStyleColorV does similar to PopStyleColor, but allows to specify
+// how much style colors would you like to pop.
+func PopStyleColorV(count int) {
+	imgui.PopStyleColorV(count)
+}
+
+// AlignTextToFramePadding vertically aligns upcoming text baseline to
+// FramePadding.y so that it will align properly to regularly framed
+// items. Call if you have text on a line before a framed item.
+func AlignTextToFramePadding() {
+	imgui.AlignTextToFramePadding()
+}
+
+// PushItemWidth sets following item's widths
+// NOTE: don't forget to call PopItemWidth! If you don't do so, imgui
+// will panic.
+func PushItemWidth(width float32) {
+	imgui.PushItemWidth(width)
+}
+
+// PopItemWidth should be called to stop applying PushItemWidth effect
+// If it isn't called imgui will panic.
+func PopItemWidth() {
+	imgui.PopItemWidth()
+}
+
+// PushTextWrapPos adds the position, where the text should be frapped.
+// use PushTextWrapPos, render text. If text reaches frame end,
+// rendering will be continued at the start pos in line below.
+// NOTE: Don't forget to call PopWrapTextPos
+// NOTE: it is done automatically in LabelWidget (see (*LabelWIdget).Wrapped()).
+func PushTextWrapPos() {
+	imgui.PushTextWrapPos()
+}
+
+// PopTextWrapPos should be caled as many times as PushTextWrapPos
+// on each frame.
+func PopTextWrapPos() {
+	imgui.PopTextWrapPos()
+}
+
+// MouseCursorType represents a type (layout) of mouse cursor.
+type MouseCursorType int
+
+// cursor types.
+const (
+	// MouseCursorNone no mouse cursor.
+	MouseCursorNone MouseCursorType = -1
+	// MouseCursorArrow standard arrow mouse cursor.
+	MouseCursorArrow MouseCursorType = 0
+	// MouseCursorTextInput when hovering over InputText, etc.
+	MouseCursorTextInput MouseCursorType = 1
+	// MouseCursorResizeAll (Unused by imgui functions).
+	MouseCursorResizeAll MouseCursorType = 2
+	// MouseCursorResizeNS when hovering over an horizontal border.
+	MouseCursorResizeNS MouseCursorType = 3
+	// MouseCursorResizeEW when hovering over a vertical border or a column.
+	MouseCursorResizeEW MouseCursorType = 4
+	// MouseCursorResizeNESW when hovering over the bottom-left corner of a window.
+	MouseCursorResizeNESW MouseCursorType = 5
+	// MouseCursorResizeNWSE when hovering over the bottom-right corner of a window.
+	MouseCursorResizeNWSE MouseCursorType = 6
+	// MouseCursorHand (Unused by imgui functions. Use for e.g. hyperlinks).
+	MouseCursorHand  MouseCursorType = 7
+	MouseCursorCount MouseCursorType = 8
+)
+
+// SetMouseCursor sets mouse cursor layout.
+func SetMouseCursor(cursor MouseCursorType) {
+	imgui.SetMouseCursor(int(cursor))
+}
+
+// GetWindowPadding returns window padding.
+func GetWindowPadding() (x, y float32) {
+	vec2 := imgui.CurrentStyle().WindowPadding()
+	return vec2.X, vec2.Y
+}
+
+// GetItemSpacing returns current item spacing.
+func GetItemSpacing() (w, h float32) {
+	vec2 := imgui.CurrentStyle().ItemSpacing()
+	return vec2.X, vec2.Y
+}
+
+// GetItemInnerSpacing returns current item inner spacing.
+func GetItemInnerSpacing() (w, h float32) {
+	vec2 := imgui.CurrentStyle().ItemInnerSpacing()
+	return vec2.X, vec2.Y
+}
+
+// GetFramePadding returns current frame padding.
+func GetFramePadding() (x, y float32) {
+	vec2 := imgui.CurrentStyle().FramePadding()
+	return vec2.X, vec2.Y
+}
+
+// StyleColorID identifies a color in the UI style.
+type StyleColorID imgui.StyleColorID
+
+// StyleColor identifier.
+const (
+	StyleColorText                  StyleColorID = StyleColorID(imgui.StyleColorText)
+	StyleColorTextDisabled          StyleColorID = StyleColorID(imgui.StyleColorTextDisabled)
+	StyleColorWindowBg              StyleColorID = StyleColorID(imgui.StyleColorWindowBg)
+	StyleColorChildBg               StyleColorID = StyleColorID(imgui.StyleColorChildBg)
+	StyleColorPopupBg               StyleColorID = StyleColorID(imgui.StyleColorPopupBg)
+	StyleColorBorder                StyleColorID = StyleColorID(imgui.StyleColorBorder)
+	StyleColorBorderShadow          StyleColorID = StyleColorID(imgui.StyleColorBorderShadow)
+	StyleColorFrameBg               StyleColorID = StyleColorID(imgui.StyleColorFrameBg)
+	StyleColorFrameBgHovered        StyleColorID = StyleColorID(imgui.StyleColorFrameBgHovered)
+	StyleColorFrameBgActive         StyleColorID = StyleColorID(imgui.StyleColorFrameBgActive)
+	StyleColorTitleBg               StyleColorID = StyleColorID(imgui.StyleColorTitleBg)
+	StyleColorTitleBgActive         StyleColorID = StyleColorID(imgui.StyleColorTitleBgActive)
+	StyleColorTitleBgCollapsed      StyleColorID = StyleColorID(imgui.StyleColorTitleBgCollapsed)
+	StyleColorMenuBarBg             StyleColorID = StyleColorID(imgui.StyleColorMenuBarBg)
+	StyleColorScrollbarBg           StyleColorID = StyleColorID(imgui.StyleColorScrollbarBg)
+	StyleColorScrollbarGrab         StyleColorID = StyleColorID(imgui.StyleColorScrollbarGrab)
+	StyleColorScrollbarGrabHovered  StyleColorID = StyleColorID(imgui.StyleColorScrollbarGrabHovered)
+	StyleColorScrollbarGrabActive   StyleColorID = StyleColorID(imgui.StyleColorScrollbarGrabActive)
+	StyleColorCheckMark             StyleColorID = StyleColorID(imgui.StyleColorCheckMark)
+	StyleColorSliderGrab            StyleColorID = StyleColorID(imgui.StyleColorSliderGrab)
+	StyleColorSliderGrabActive      StyleColorID = StyleColorID(imgui.StyleColorSliderGrabActive)
+	StyleColorButton                StyleColorID = StyleColorID(imgui.StyleColorButton)
+	StyleColorButtonHovered         StyleColorID = StyleColorID(imgui.StyleColorButtonHovered)
+	StyleColorButtonActive          StyleColorID = StyleColorID(imgui.StyleColorButtonActive)
+	StyleColorHeader                StyleColorID = StyleColorID(imgui.StyleColorHeader)
+	StyleColorHeaderHovered         StyleColorID = StyleColorID(imgui.StyleColorHeaderHovered)
+	StyleColorHeaderActive          StyleColorID = StyleColorID(imgui.StyleColorHeaderActive)
+	StyleColorSeparator             StyleColorID = StyleColorID(imgui.StyleColorSeparator)
+	StyleColorSeparatorHovered      StyleColorID = StyleColorID(imgui.StyleColorSeparatorHovered)
+	StyleColorSeparatorActive       StyleColorID = StyleColorID(imgui.StyleColorSeparatorActive)
+	StyleColorResizeGrip            StyleColorID = StyleColorID(imgui.StyleColorResizeGrip)
+	StyleColorResizeGripHovered     StyleColorID = StyleColorID(imgui.StyleColorResizeGripHovered)
+	StyleColorResizeGripActive      StyleColorID = StyleColorID(imgui.StyleColorResizeGripActive)
+	StyleColorTab                   StyleColorID = StyleColorID(imgui.StyleColorTab)
+	StyleColorTabHovered            StyleColorID = StyleColorID(imgui.StyleColorTabHovered)
+	StyleColorTabActive             StyleColorID = StyleColorID(imgui.StyleColorTabActive)
+	StyleColorTabUnfocused          StyleColorID = StyleColorID(imgui.StyleColorTabUnfocused)
+	StyleColorTabUnfocusedActive    StyleColorID = StyleColorID(imgui.StyleColorTabUnfocusedActive)
+	StyleColorPlotLines             StyleColorID = StyleColorID(imgui.StyleColorPlotLines)
+	StyleColorPlotLinesHovered      StyleColorID = StyleColorID(imgui.StyleColorPlotLinesHovered)
+	StyleColorProgressBarActive     StyleColorID = StyleColorPlotLinesHovered
+	StyleColorPlotHistogram         StyleColorID = StyleColorID(imgui.StyleColorPlotHistogram)
+	StyleColorPlotHistogramHovered  StyleColorID = StyleColorID(imgui.StyleColorPlotHistogramHovered)
+	StyleColorTableHeaderBg         StyleColorID = StyleColorID(imgui.StyleColorTableHeaderBg)
+	StyleColorTableBorderStrong     StyleColorID = StyleColorID(imgui.StyleColorTableBorderStrong)
+	StyleColorTableBorderLight      StyleColorID = StyleColorID(imgui.StyleColorTableBorderLight)
+	StyleColorTableRowBg            StyleColorID = StyleColorID(imgui.StyleColorTableRowBg)
+	StyleColorTableRowBgAlt         StyleColorID = StyleColorID(imgui.StyleColorTableRowBgAlt)
+	StyleColorTextSelectedBg        StyleColorID = StyleColorID(imgui.StyleColorTextSelectedBg)
+	StyleColorDragDropTarget        StyleColorID = StyleColorID(imgui.StyleColorDragDropTarget)
+	StyleColorNavHighlight          StyleColorID = StyleColorID(imgui.StyleColorNavHighlight)
+	StyleColorNavWindowingHighlight StyleColorID = StyleColorID(imgui.StyleColorNavWindowingHighlight)
+	StyleColorNavWindowingDimBg     StyleColorID = StyleColorID(imgui.StyleColorNavWindowingDimBg)
+	StyleColorModalWindowDimBg      StyleColorID = StyleColorID(imgui.StyleColorModalWindowDimBg)
+)
+
+// StyleVarID identifies a style variable in the UI style.
+type StyleVarID imgui.StyleVarID
+
+// Style IDs.
+const (
+	// StyleVarAlpha is a float.
+	StyleVarAlpha StyleVarID = StyleVarID(imgui.StyleVarAlpha)
+	// float     DisabledAlpha.
+	StyleVarDisabledAlpha StyleVarID = StyleVarID(imgui.StyleVarDisabledAlpha)
+	// StyleVarWindowPadding is a Vec2.
+	StyleVarWindowPadding StyleVarID = StyleVarID(imgui.StyleVarWindowPadding)
+	// StyleVarWindowRounding is a float.
+	StyleVarWindowRounding StyleVarID = StyleVarID(imgui.StyleVarWindowRounding)
+	// StyleVarWindowBorderSize is a float.
+	StyleVarWindowBorderSize StyleVarID = StyleVarID(imgui.StyleVarWindowBorderSize)
+	// StyleVarWindowMinSize is a Vec2.
+	StyleVarWindowMinSize StyleVarID = StyleVarID(imgui.StyleVarWindowMinSize)
+	// StyleVarWindowTitleAlign is a Vec2.
+	StyleVarWindowTitleAlign StyleVarID = StyleVarID(imgui.StyleVarWindowTitleAlign)
+	// StyleVarChildRounding is a float.
+	StyleVarChildRounding StyleVarID = StyleVarID(imgui.StyleVarChildRounding)
+	// StyleVarChildBorderSize is a float.
+	StyleVarChildBorderSize StyleVarID = StyleVarID(imgui.StyleVarChildBorderSize)
+	// StyleVarPopupRounding is a float.
+	StyleVarPopupRounding StyleVarID = StyleVarID(imgui.StyleVarPopupRounding)
+	// StyleVarPopupBorderSize is a float.
+	StyleVarPopupBorderSize StyleVarID = StyleVarID(imgui.StyleVarPopupBorderSize)
+	// StyleVarFramePadding is a Vec2.
+	StyleVarFramePadding StyleVarID = StyleVarID(imgui.StyleVarFramePadding)
+	// StyleVarFrameRounding is a float.
+	StyleVarFrameRounding StyleVarID = StyleVarID(imgui.StyleVarFrameRounding)
+	// StyleVarFrameBorderSize is a float.
+	StyleVarFrameBorderSize StyleVarID = StyleVarID(imgui.StyleVarFrameBorderSize)
+	// StyleVarItemSpacing is a Vec2.
+	StyleVarItemSpacing StyleVarID = StyleVarID(imgui.StyleVarItemSpacing)
+	// StyleVarItemInnerSpacing is a Vec2.
+	StyleVarItemInnerSpacing StyleVarID = StyleVarID(imgui.StyleVarItemInnerSpacing)
+	// StyleVarIndentSpacing is a float.
+	StyleVarIndentSpacing StyleVarID = StyleVarID(imgui.StyleVarIndentSpacing)
+	// StyleVarScrollbarSize is a float.
+	StyleVarScrollbarSize StyleVarID = StyleVarID(imgui.StyleVarScrollbarSize)
+	// StyleVarScrollbarRounding is a float.
+	StyleVarScrollbarRounding StyleVarID = StyleVarID(imgui.StyleVarScrollbarRounding)
+	// StyleVarGrabMinSize is a float.
+	StyleVarGrabMinSize StyleVarID = StyleVarID(imgui.StyleVarGrabMinSize)
+	// StyleVarGrabRounding is a float.
+	StyleVarGrabRounding StyleVarID = StyleVarID(imgui.StyleVarGrabRounding)
+	// StyleVarTabRounding is a float.
+	StyleVarTabRounding StyleVarID = StyleVarID(imgui.StyleVarTabRounding)
+	// StyleVarButtonTextAlign is a Vec2.
+	StyleVarButtonTextAlign StyleVarID = StyleVarID(imgui.StyleVarButtonTextAlign)
+	// StyleVarSelectableTextAlign is a Vec2.
+	StyleVarSelectableTextAlign StyleVarID = StyleVarID(imgui.StyleVarSelectableTextAlign)
+)
+
+// IsVec2 returns true if the style var id should be processed as imgui.Vec2
+// if not, it is interpreted as float32.
+func (s StyleVarID) IsVec2() bool {
+	lookup := map[StyleVarID]bool{
+		// StyleVarWindowPadding is a Vec2.
+		StyleVarWindowPadding:    true,
+		StyleVarWindowMinSize:    true,
+		StyleVarWindowTitleAlign: true,
+		StyleVarFramePadding:     true,
+		StyleVarItemSpacing:      true,
+		// StyleVarItemInnerSpacing is a Vec2.
+		StyleVarItemInnerSpacing:    true,
+		StyleVarButtonTextAlign:     true,
+		StyleVarSelectableTextAlign: true,
+	}
+
+	result, ok := lookup[s]
+
+	return result && ok
+}
+
+var _ Widget = &StyleSetter{}
+
+// StyleSetter is a user-friendly way to manage imgui styles.
+type StyleSetter struct {
+	colors   map[StyleColorID]color.Color
+	styles   map[StyleVarID]any
+	font     *FontInfo
+	disabled bool
+	layout   Layout
+}
+
+// Style initializes a style setter (see examples/setstyle).
+func Style() *StyleSetter {
+	var ss StyleSetter
+	ss.colors = make(map[StyleColorID]color.Color)
+	ss.styles = make(map[StyleVarID]any)
+
+	return &ss
+}
+
+// SetColor sets colorID's color.
+func (ss *StyleSetter) SetColor(colorID StyleColorID, col color.Color) *StyleSetter {
+	ss.colors[colorID] = col
+	return ss
+}
+
+// SetStyle sets styleVarID to width and height.
+func (ss *StyleSetter) SetStyle(varID StyleVarID, width, height float32) *StyleSetter {
+	ss.styles[varID] = imgui.Vec2{X: width, Y: height}
+	return ss
+}
+
+// SetStyleFloat sets styleVarID to float value.
+// NOTE: for float typed values see above in comments over
+// StyleVarID's comments.
+func (ss *StyleSetter) SetStyleFloat(varID StyleVarID, value float32) *StyleSetter {
+	ss.styles[varID] = value
+	return ss
+}
+
+// SetFont sets font.
+func (ss *StyleSetter) SetFont(font *FontInfo) *StyleSetter {
+	ss.font = font
+	return ss
+}
+
+// SetFontSize sets size of the font.
+// NOTE: Be aware, that StyleSetter needs to add a new font to font atlas for
+// each font's size.
+func (ss *StyleSetter) SetFontSize(size float32) *StyleSetter {
+	var font FontInfo
+	if ss.font != nil {
+		font = *ss.font
+	} else {
+		font = defaultFonts[0]
+	}
+
+	ss.font = font.SetSize(size)
+
+	return ss
+}
+
+// SetDisabled sets if items are disabled.
+func (ss *StyleSetter) SetDisabled(d bool) *StyleSetter {
+	ss.disabled = d
+	return ss
+}
+
+// To allows to specify a layout, StyleSetter should apply style for.
+func (ss *StyleSetter) To(widgets ...Widget) *StyleSetter {
+	ss.layout = widgets
+	return ss
+}
+
+// Build implements Widget.
+func (ss *StyleSetter) Build() {
+	if ss.layout == nil || len(ss.layout) == 0 {
+		return
+	}
+
+	for k, v := range ss.colors {
+		imgui.PushStyleColor(imgui.StyleColorID(k), ToVec4Color(v))
+	}
+
+	for k, v := range ss.styles {
+		if k.IsVec2() {
+			var value imgui.Vec2
+			switch typed := v.(type) {
+			case imgui.Vec2:
+				value = typed
+			case float32:
+				value = imgui.Vec2{X: typed, Y: typed}
+			}
+
+			imgui.PushStyleVarVec2(imgui.StyleVarID(k), value)
+		} else {
+			var value float32
+			switch typed := v.(type) {
+			case float32:
+				value = typed
+			case imgui.Vec2:
+				value = typed.X
+			}
+
+			imgui.PushStyleVarFloat(imgui.StyleVarID(k), value)
+		}
+	}
+
+	if ss.font != nil {
+		if PushFont(ss.font) {
+			defer PopFont()
+		}
+	}
+
+	imgui.BeginDisabled(ss.disabled)
+
+	ss.layout.Build()
+
+	imgui.EndDisabled()
+
+	imgui.PopStyleColorV(len(ss.colors))
+	imgui.PopStyleVarV(len(ss.styles))
+}

+ 212 - 0
vendor/github.com/AllenDang/giu/TableWidgets.go

@@ -0,0 +1,212 @@
+package giu
+
+import (
+	"image/color"
+
+	"github.com/AllenDang/imgui-go"
+)
+
+type TableRowWidget struct {
+	flags        TableRowFlags
+	minRowHeight float64
+	layout       Layout
+	bgColor      color.Color
+}
+
+func TableRow(widgets ...Widget) *TableRowWidget {
+	return &TableRowWidget{
+		flags:        0,
+		minRowHeight: 0,
+		layout:       widgets,
+		bgColor:      nil,
+	}
+}
+
+func (r *TableRowWidget) BgColor(c color.Color) *TableRowWidget {
+	r.bgColor = c
+	return r
+}
+
+func (r *TableRowWidget) Flags(flags TableRowFlags) *TableRowWidget {
+	r.flags = flags
+	return r
+}
+
+func (r *TableRowWidget) MinHeight(height float64) *TableRowWidget {
+	r.minRowHeight = height
+	return r
+}
+
+// BuildTableRow executes table row build steps.
+func (r *TableRowWidget) BuildTableRow() {
+	imgui.TableNextRow(imgui.TableRowFlags(r.flags), r.minRowHeight)
+
+	for _, w := range r.layout {
+		switch w.(type) {
+		case *TooltipWidget,
+			*ContextMenuWidget, *PopupModalWidget:
+			// noop
+		default:
+			imgui.TableNextColumn()
+		}
+
+		w.Build()
+	}
+
+	if r.bgColor != nil {
+		imgui.TableSetBgColor(imgui.TableBgTarget_RowBg0, uint32(imgui.GetColorU32(ToVec4Color(r.bgColor))), -1)
+	}
+}
+
+type TableColumnWidget struct {
+	label              string
+	flags              TableColumnFlags
+	innerWidthOrWeight float32
+	userID             uint32
+}
+
+func TableColumn(label string) *TableColumnWidget {
+	return &TableColumnWidget{
+		label:              tStr(label),
+		flags:              0,
+		innerWidthOrWeight: 0,
+		userID:             0,
+	}
+}
+
+func (c *TableColumnWidget) Flags(flags TableColumnFlags) *TableColumnWidget {
+	c.flags = flags
+	return c
+}
+
+func (c *TableColumnWidget) InnerWidthOrWeight(w float32) *TableColumnWidget {
+	c.innerWidthOrWeight = w
+	return c
+}
+
+func (c *TableColumnWidget) UserID(id uint32) *TableColumnWidget {
+	c.userID = id
+	return c
+}
+
+// BuildTableColumn executes table column build steps.
+func (c *TableColumnWidget) BuildTableColumn() {
+	imgui.TableSetupColumn(c.label, imgui.TableColumnFlags(c.flags), c.innerWidthOrWeight, c.userID)
+}
+
+var _ Widget = &TableWidget{}
+
+type TableWidget struct {
+	id           string
+	flags        TableFlags
+	size         imgui.Vec2
+	innerWidth   float64
+	rows         []*TableRowWidget
+	columns      []*TableColumnWidget
+	fastMode     bool
+	freezeRow    int
+	freezeColumn int
+}
+
+func Table() *TableWidget {
+	return &TableWidget{
+		id:           GenAutoID("Table"),
+		flags:        TableFlagsResizable | TableFlagsBorders | TableFlagsScrollY,
+		rows:         nil,
+		columns:      nil,
+		fastMode:     false,
+		freezeRow:    -1,
+		freezeColumn: -1,
+	}
+}
+
+// ID sets the internal id of table widget.
+func (t *TableWidget) ID(id string) *TableWidget {
+	t.id = id
+	return t
+}
+
+// FastMode Displays visible rows only to boost performance.
+func (t *TableWidget) FastMode(b bool) *TableWidget {
+	t.fastMode = b
+	return t
+}
+
+// Freeze columns/rows so they stay visible when scrolled.
+func (t *TableWidget) Freeze(col, row int) *TableWidget {
+	t.freezeColumn = col
+	t.freezeRow = row
+	return t
+}
+
+func (t *TableWidget) Columns(cols ...*TableColumnWidget) *TableWidget {
+	t.columns = cols
+	return t
+}
+
+func (t *TableWidget) Rows(rows ...*TableRowWidget) *TableWidget {
+	t.rows = rows
+	return t
+}
+
+func (t *TableWidget) Size(width, height float32) *TableWidget {
+	t.size = imgui.Vec2{X: width, Y: height}
+	return t
+}
+
+func (t *TableWidget) InnerWidth(width float64) *TableWidget {
+	t.innerWidth = width
+	return t
+}
+
+func (t *TableWidget) Flags(flags TableFlags) *TableWidget {
+	t.flags = flags
+	return t
+}
+
+// Build implements Widget interface.
+func (t *TableWidget) Build() {
+	if len(t.rows) == 0 {
+		return
+	}
+
+	colCount := len(t.columns)
+	if colCount == 0 {
+		colCount = len(t.rows[0].layout)
+	}
+
+	if imgui.BeginTable(t.id, colCount, imgui.TableFlags(t.flags), t.size, t.innerWidth) {
+		if t.freezeColumn >= 0 && t.freezeRow >= 0 {
+			imgui.TableSetupScrollFreeze(t.freezeColumn, t.freezeRow)
+		}
+
+		if len(t.columns) > 0 {
+			for _, col := range t.columns {
+				col.BuildTableColumn()
+			}
+			imgui.TableHeadersRow()
+		}
+
+		if t.fastMode {
+			clipper := imgui.NewListClipper()
+			defer clipper.Delete()
+
+			clipper.Begin(len(t.rows))
+
+			for clipper.Step() {
+				for i := clipper.DisplayStart(); i < clipper.DisplayEnd(); i++ {
+					row := t.rows[i]
+					row.BuildTableRow()
+				}
+			}
+
+			clipper.End()
+		} else {
+			for _, row := range t.rows {
+				row.BuildTableRow()
+			}
+		}
+
+		imgui.EndTable()
+	}
+}

+ 456 - 0
vendor/github.com/AllenDang/giu/TextWidgets.go

@@ -0,0 +1,456 @@
+package giu
+
+import (
+	"fmt"
+	"math"
+
+	"github.com/AllenDang/imgui-go"
+	"github.com/sahilm/fuzzy"
+)
+
+var _ Widget = &InputTextMultilineWidget{}
+
+// InputTextMultilineWidget is a large (multiline) text input
+// see examples/widgets/.
+type InputTextMultilineWidget struct {
+	label         string
+	text          *string
+	width, height float32
+	flags         InputTextFlags
+	cb            imgui.InputTextCallback
+	onChange      func()
+}
+
+// InputTextMultiline creates InputTextMultilineWidget.
+func InputTextMultiline(text *string) *InputTextMultilineWidget {
+	return &InputTextMultilineWidget{
+		text:     text,
+		width:    0,
+		height:   0,
+		flags:    0,
+		cb:       nil,
+		onChange: nil,
+		label:    GenAutoID("##InputTextMultiline"),
+	}
+}
+
+// Label sets input field label.
+func (i *InputTextMultilineWidget) Label(label string) *InputTextMultilineWidget {
+	i.label = label
+	return i
+}
+
+// Labelf is formatting version of Label.
+func (i *InputTextMultilineWidget) Labelf(format string, args ...any) *InputTextMultilineWidget {
+	return i.Label(fmt.Sprintf(format, args...))
+}
+
+// Flags sets InputTextFlags (see Flags.go).
+func (i *InputTextMultilineWidget) Flags(flags InputTextFlags) *InputTextMultilineWidget {
+	i.flags = flags
+	return i
+}
+
+// Callback sets imgui.InputTextCallback.
+func (i *InputTextMultilineWidget) Callback(cb imgui.InputTextCallback) *InputTextMultilineWidget {
+	i.cb = cb
+	return i
+}
+
+// OnChange set callback called when user action taken on input text field (when text was changed).
+func (i *InputTextMultilineWidget) OnChange(onChange func()) *InputTextMultilineWidget {
+	i.onChange = onChange
+	return i
+}
+
+// Size sets input field size.
+func (i *InputTextMultilineWidget) Size(width, height float32) *InputTextMultilineWidget {
+	i.width, i.height = width, height
+	return i
+}
+
+// Build implements Widget interface.
+func (i *InputTextMultilineWidget) Build() {
+	if imgui.InputTextMultilineV(
+		tStr(i.label),
+		tStrPtr(i.text),
+		imgui.Vec2{
+			X: i.width,
+			Y: i.height,
+		},
+		int(i.flags), i.cb,
+	) && i.onChange != nil {
+		i.onChange()
+	}
+}
+
+var _ Widget = &BulletWidget{}
+
+// BulletWidget adds a small, white dot (bullet).
+// useful in enumerations.
+type BulletWidget struct{}
+
+// Bullet creates a bullet widget.
+func Bullet() *BulletWidget {
+	return &BulletWidget{}
+}
+
+// Build implements Widget interface.
+func (b *BulletWidget) Build() {
+	imgui.Bullet()
+}
+
+var _ Widget = &BulletTextWidget{}
+
+// BulletTextWidget does similar to BulletWidget, but allows
+// to add a text after a bullet. Very useful to create lists.
+type BulletTextWidget struct {
+	text string
+}
+
+// BulletText creates bulletTextWidget.
+func BulletText(text string) *BulletTextWidget {
+	return &BulletTextWidget{
+		text: tStr(text),
+	}
+}
+
+// BulletTextf is a formatting version of BulletText.
+func BulletTextf(format string, args ...any) *BulletTextWidget {
+	return BulletText(fmt.Sprintf(format, args...))
+}
+
+// Build implements Widget interface.
+func (bt *BulletTextWidget) Build() {
+	imgui.BulletText(bt.text)
+}
+
+var _ Disposable = &inputTextState{}
+
+type inputTextState struct {
+	autoCompleteCandidates fuzzy.Matches
+}
+
+// Dispose implements disposable interface.
+func (s *inputTextState) Dispose() {
+	s.autoCompleteCandidates = nil
+}
+
+var _ Widget = &InputTextWidget{}
+
+// InputTextWidget is a single-line text iinput.
+type InputTextWidget struct {
+	label      string
+	hint       string
+	value      *string
+	width      float32
+	candidates []string
+	flags      InputTextFlags
+	cb         imgui.InputTextCallback
+	onChange   func()
+}
+
+// InputText creates new input text widget.
+func InputText(value *string) *InputTextWidget {
+	return &InputTextWidget{
+		label:    GenAutoID("##InputText"),
+		hint:     "",
+		value:    value,
+		width:    0,
+		flags:    0,
+		cb:       nil,
+		onChange: nil,
+	}
+}
+
+// Label adds label (alternatively you can use it to set widget's id).
+func (i *InputTextWidget) Label(label string) *InputTextWidget {
+	i.label = tStr(label)
+	return i
+}
+
+// Labelf adds formatted label.
+func (i *InputTextWidget) Labelf(format string, args ...any) *InputTextWidget {
+	return i.Label(fmt.Sprintf(format, args...))
+}
+
+// AutoComplete enables auto complete popup by using fuzzy search of current value against candidates
+// Press enter to confirm the first candidate.
+func (i *InputTextWidget) AutoComplete(candidates []string) *InputTextWidget {
+	i.candidates = candidates
+	return i
+}
+
+// Hint sets hint text.
+func (i *InputTextWidget) Hint(hint string) *InputTextWidget {
+	i.hint = tStr(hint)
+	return i
+}
+
+// Size sets field's width.
+func (i *InputTextWidget) Size(width float32) *InputTextWidget {
+	i.width = width
+	return i
+}
+
+// Flags sets flags.
+func (i *InputTextWidget) Flags(flags InputTextFlags) *InputTextWidget {
+	i.flags = flags
+	return i
+}
+
+// Callback sets input text callback.
+func (i *InputTextWidget) Callback(cb imgui.InputTextCallback) *InputTextWidget {
+	i.cb = cb
+	return i
+}
+
+// OnChange sets callback when text was changed.
+func (i *InputTextWidget) OnChange(onChange func()) *InputTextWidget {
+	i.onChange = onChange
+	return i
+}
+
+// Build implements Widget interface.
+func (i *InputTextWidget) Build() {
+	// Get state
+	var state *inputTextState
+	if s := Context.GetState(i.label); s == nil {
+		state = &inputTextState{}
+		Context.SetState(i.label, state)
+	} else {
+		var isOk bool
+		state, isOk = s.(*inputTextState)
+		Assert(isOk, "InputTextWidget", "Build", "wrong state type recovered.")
+	}
+
+	if i.width != 0 {
+		PushItemWidth(i.width)
+		defer PopItemWidth()
+	}
+
+	isChanged := imgui.InputTextWithHint(i.label, i.hint, tStrPtr(i.value), int(i.flags), i.cb)
+
+	if isChanged && i.onChange != nil {
+		i.onChange()
+	}
+
+	if isChanged {
+		// Enable auto complete
+		if len(i.candidates) > 0 {
+			matches := fuzzy.Find(*i.value, i.candidates)
+			if matches.Len() > 0 {
+				size := int(math.Min(5, float64(matches.Len())))
+				matches = matches[:size]
+
+				state.autoCompleteCandidates = matches
+			}
+		}
+	}
+
+	// Draw autocomplete list
+	if len(state.autoCompleteCandidates) > 0 {
+		labels := make(Layout, len(state.autoCompleteCandidates))
+		for i, m := range state.autoCompleteCandidates {
+			labels[i] = Label(m.Str)
+		}
+
+		SetNextWindowPos(imgui.GetItemRectMin().X, imgui.GetItemRectMax().Y)
+		imgui.BeginTooltip()
+		labels.Build()
+		imgui.EndTooltip()
+
+		// Press enter will replace value string with first match candidate
+		if IsKeyPressed(KeyEnter) {
+			*i.value = state.autoCompleteCandidates[0].Str
+			state.autoCompleteCandidates = nil
+		}
+	}
+}
+
+var _ Widget = &InputIntWidget{}
+
+// InputIntWidget is an input text field acceptiong intager values only.
+type InputIntWidget struct {
+	label    string
+	value    *int32
+	width    float32
+	flags    InputTextFlags
+	onChange func()
+}
+
+// InputInt creates input int widget
+// NOTE: value is int32, so its size is up to 10^32-1.
+// to process greater values, you need to use InputTextWidget
+// with InputTextFlagsCharsDecimal and strconv.ParseInt in OnChange callback.
+func InputInt(value *int32) *InputIntWidget {
+	return &InputIntWidget{
+		label:    GenAutoID("##InputInt"),
+		value:    value,
+		width:    0,
+		flags:    0,
+		onChange: nil,
+	}
+}
+
+// Label sets label (id).
+func (i *InputIntWidget) Label(label string) *InputIntWidget {
+	i.label = tStr(label)
+	return i
+}
+
+// Labelf sets formatted label.
+func (i *InputIntWidget) Labelf(format string, args ...any) *InputIntWidget {
+	return i.Label(fmt.Sprintf(format, args...))
+}
+
+// Size sets input's width.
+func (i *InputIntWidget) Size(width float32) *InputIntWidget {
+	i.width = width
+	return i
+}
+
+// Flags sets flags.
+func (i *InputIntWidget) Flags(flags InputTextFlags) *InputIntWidget {
+	i.flags = flags
+	return i
+}
+
+// OnChange adds on change callback.
+func (i *InputIntWidget) OnChange(onChange func()) *InputIntWidget {
+	i.onChange = onChange
+	return i
+}
+
+// Build implements Widget interface.
+func (i *InputIntWidget) Build() {
+	if i.width != 0 {
+		PushItemWidth(i.width)
+		defer PopItemWidth()
+	}
+
+	if imgui.InputIntV(i.label, i.value, 0, 100, int(i.flags)) && i.onChange != nil {
+		i.onChange()
+	}
+}
+
+var _ Widget = &InputFloatWidget{}
+
+// InputFloatWidget does similar to InputIntWIdget, but accepts float numbers.
+type InputFloatWidget struct {
+	label    string
+	value    *float32
+	width    float32
+	flags    InputTextFlags
+	format   string
+	onChange func()
+}
+
+// InputFloat constructs InputFloatWidget.
+func InputFloat(value *float32) *InputFloatWidget {
+	return &InputFloatWidget{
+		label:    GenAutoID("##InputFloatWidget"),
+		width:    0,
+		value:    value,
+		format:   "%.3f",
+		flags:    0,
+		onChange: nil,
+	}
+}
+
+// Label sets label of input field.
+func (i *InputFloatWidget) Label(label string) *InputFloatWidget {
+	i.label = tStr(label)
+	return i
+}
+
+// Labelf sets formatted label.
+func (i *InputFloatWidget) Labelf(format string, args ...any) *InputFloatWidget {
+	return i.Label(fmt.Sprintf(format, args...))
+}
+
+// Size sets input field's width.
+func (i *InputFloatWidget) Size(width float32) *InputFloatWidget {
+	i.width = width
+	return i
+}
+
+// Flags sets flags.
+func (i *InputFloatWidget) Flags(flags InputTextFlags) *InputFloatWidget {
+	i.flags = flags
+	return i
+}
+
+// Format sets data format (e.g. %.3f).
+func (i *InputFloatWidget) Format(format string) *InputFloatWidget {
+	i.format = format
+	return i
+}
+
+// OnChange sets callback called when text is changed.
+func (i *InputFloatWidget) OnChange(onChange func()) *InputFloatWidget {
+	i.onChange = onChange
+	return i
+}
+
+// Build implements Widget interface.
+func (i *InputFloatWidget) Build() {
+	if i.width != 0 {
+		PushItemWidth(i.width)
+		defer PopItemWidth()
+	}
+
+	if imgui.InputFloatV(i.label, i.value, 0, 0, i.format, int(i.flags)) && i.onChange != nil {
+		i.onChange()
+	}
+}
+
+var _ Widget = &LabelWidget{}
+
+// LabelWidget is a plain text label.
+type LabelWidget struct {
+	label    string
+	fontInfo *FontInfo
+	wrapped  bool
+}
+
+// Label constructs label widget.
+func Label(label string) *LabelWidget {
+	return &LabelWidget{
+		label:   tStr(label),
+		wrapped: false,
+	}
+}
+
+// Labelf allows to add formatted label.
+func Labelf(format string, args ...any) *LabelWidget {
+	return Label(fmt.Sprintf(format, args...))
+}
+
+// Wrapped determinates if label is frapped.
+func (l *LabelWidget) Wrapped(wrapped bool) *LabelWidget {
+	l.wrapped = wrapped
+	return l
+}
+
+// Font sets specific font (does like Style().SetFont).
+func (l *LabelWidget) Font(font *FontInfo) *LabelWidget {
+	l.fontInfo = font
+	return l
+}
+
+// Build implements Widget interface.
+func (l *LabelWidget) Build() {
+	if l.wrapped {
+		PushTextWrapPos()
+		defer PopTextWrapPos()
+	}
+
+	if l.fontInfo != nil {
+		if PushFont(l.fontInfo) {
+			defer PopFont()
+		}
+	}
+
+	imgui.Text(l.label)
+}

+ 78 - 0
vendor/github.com/AllenDang/giu/Texture.go

@@ -0,0 +1,78 @@
+package giu
+
+import (
+	"fmt"
+	"image"
+	"runtime"
+
+	"github.com/AllenDang/imgui-go"
+	"github.com/faiface/mainthread"
+)
+
+// Texture represents imgui.TextureID.
+// It is base unit of images in imgui.
+type Texture struct {
+	id imgui.TextureID
+}
+
+type textureLoadRequest struct {
+	img image.Image
+	cb  func(*Texture)
+}
+
+type loadImageResult struct {
+	id  imgui.TextureID
+	err error
+}
+
+// EnqueueNewTextureFromRgba adds loading texture request to loading queue
+// it allows us to run this method in main loop
+// NOTE: remember to call it after NewMasterWindow!
+func EnqueueNewTextureFromRgba(rgba image.Image, loadCb func(t *Texture)) {
+	Assert((Context.textureLoadingQueue != nil), "", "EnqueueNewTextureFromRgba", "you need to call EnqueueNewTextureFromRgba after giu.NewMasterWindow call!")
+	Context.textureLoadingQueue.Add(textureLoadRequest{rgba, loadCb})
+}
+
+// NewTextureFromRgba creates a new texture from image.Image and, when it is done, calls loadCallback(loadedTexture).
+func NewTextureFromRgba(rgba image.Image, loadCallback func(*Texture)) {
+	Assert(Context.isRunning, "", "NewTextureFromRgba", "cannot load texture befor (*MasterWindow).Run call!")
+	loadTexture(rgba, loadCallback)
+}
+
+func loadTexture(rgba image.Image, loadCallback func(*Texture)) {
+	go func() {
+		Update()
+		result := mainthread.CallVal(func() any {
+			texID, err := Context.renderer.LoadImage(ImageToRgba(rgba))
+			return &loadImageResult{id: texID, err: err}
+		})
+
+		tid, ok := result.(*loadImageResult)
+		switch {
+		case !ok:
+			panic("giu: NewTextureFromRgba: unexpected error occurred")
+		case tid.err != nil:
+			panic(fmt.Sprintf("giu: NewTextureFromRgba: error loading texture: %v", tid.err))
+		}
+
+		texture := Texture{id: tid.id}
+
+		// Set finalizer
+		runtime.SetFinalizer(&texture, (*Texture).release)
+
+		// execute callback
+		loadCallback(&texture)
+	}()
+}
+
+// ToTexture converts imgui.TextureID to Texture.
+func ToTexture(textureID imgui.TextureID) *Texture {
+	return &Texture{id: textureID}
+}
+
+func (t *Texture) release() {
+	Update()
+	mainthread.Call(func() {
+		Context.renderer.ReleaseImage(t.id)
+	})
+}

+ 11 - 0
vendor/github.com/AllenDang/giu/TextureFilters.go

@@ -0,0 +1,11 @@
+package giu
+
+// Texture filtering types.
+const (
+	TextureFilterNearest = iota
+	TextureFilterLinear
+	TextureFilterNearestMipmapNearest
+	TextureFilterLinearMipmapNearest
+	TextureFilterNearestMipmapLinear
+	TextureFilterLinearMipmapLinear
+)

+ 216 - 0
vendor/github.com/AllenDang/giu/Utils.go

@@ -0,0 +1,216 @@
+package giu
+
+import (
+	"fmt"
+	"image"
+	"image/color"
+	"image/draw"
+	"image/png"
+	"log"
+	"os"
+	"path/filepath"
+
+	"github.com/AllenDang/imgui-go"
+	"github.com/pkg/browser"
+)
+
+// LoadImage loads image from file and returns *image.RGBA.
+func LoadImage(imgPath string) (*image.RGBA, error) {
+	imgFile, err := os.Open(filepath.Clean(imgPath))
+	if err != nil {
+		return nil, fmt.Errorf("LoadImage: error opening image file %s: %w", imgPath, err)
+	}
+
+	defer func() {
+		// nolint:govet // we want to reuse this err variable here
+		if err := imgFile.Close(); err != nil {
+			panic(fmt.Sprintf("error closing image file: %s", imgPath))
+		}
+	}()
+
+	img, err := png.Decode(imgFile)
+	if err != nil {
+		return nil, fmt.Errorf("LoadImage: error decoding png image: %w", err)
+	}
+
+	return ImageToRgba(img), nil
+}
+
+// ImageToRgba converts image.Image to *image.RGBA.
+func ImageToRgba(img image.Image) *image.RGBA {
+	switch trueImg := img.(type) {
+	case *image.RGBA:
+		return trueImg
+	default:
+		rgba := image.NewRGBA(trueImg.Bounds())
+		draw.Draw(rgba, trueImg.Bounds(), trueImg, image.Pt(0, 0), draw.Src)
+		return rgba
+	}
+}
+
+// ToVec4Color converts rgba color to imgui.Vec4.
+func ToVec4Color(col color.Color) imgui.Vec4 {
+	const mask = 0xffff
+
+	r, g, b, a := col.RGBA()
+	return imgui.Vec4{
+		X: float32(r) / mask,
+		Y: float32(g) / mask,
+		Z: float32(b) / mask,
+		W: float32(a) / mask,
+	}
+}
+
+// ToVec2 converts image.Point to imgui.Vec2.
+func ToVec2(pt image.Point) imgui.Vec2 {
+	return imgui.Vec2{
+		X: float32(pt.X),
+		Y: float32(pt.Y),
+	}
+}
+
+// Vec4ToRGBA converts imgui's Vec4 to golang rgba color.
+func Vec4ToRGBA(vec4 imgui.Vec4) color.RGBA {
+	return color.RGBA{
+		R: uint8(vec4.X * 255),
+		G: uint8(vec4.Y * 255),
+		B: uint8(vec4.Z * 255),
+		A: uint8(vec4.W * 255),
+	}
+}
+
+// Update updates giu app
+// it is done by default after each frame.
+// However because frames stops rendering, when no user
+// action is done, it may be necessary to
+// Update ui manually at some point.
+func Update() {
+	if Context.isAlive {
+		Context.platform.Update()
+	}
+}
+
+// GetCursorScreenPos returns imgui drawing cursor on the screen.
+func GetCursorScreenPos() image.Point {
+	pos := imgui.CursorScreenPos()
+	return image.Pt(int(pos.X), int(pos.Y))
+}
+
+// SetCursorScreenPos sets imgui drawing cursor on the screen.
+func SetCursorScreenPos(pos image.Point) {
+	imgui.SetCursorScreenPos(imgui.Vec2{X: float32(pos.X), Y: float32(pos.Y)})
+}
+
+// GetCursorPos gets imgui drawing cursor inside of current window.
+func GetCursorPos() image.Point {
+	pos := imgui.CursorPos()
+	return image.Pt(int(pos.X), int(pos.Y))
+}
+
+// SetCursorPos sets imgui drawing cursor inside of current window.
+func SetCursorPos(pos image.Point) {
+	imgui.SetCursorPos(imgui.Vec2{X: float32(pos.X), Y: float32(pos.Y)})
+}
+
+// GetMousePos returns mouse position.
+func GetMousePos() image.Point {
+	pos := imgui.MousePos()
+	return image.Pt(int(pos.X), int(pos.Y))
+}
+
+// GetAvailableRegion returns region available for rendering.
+// it is always WindowSize-WindowPadding*2.
+func GetAvailableRegion() (width, height float32) {
+	region := imgui.ContentRegionAvail()
+	return region.X, region.Y
+}
+
+// CalcTextSize calls CalcTextSizeV(text, false, -1).
+func CalcTextSize(text string) (width, height float32) {
+	return CalcTextSizeV(text, false, -1)
+}
+
+// CalcTextSizeV calculates text dimensions.
+func CalcTextSizeV(text string, hideAfterDoubleHash bool, wrapWidth float32) (w, h float32) {
+	size := imgui.CalcTextSize(text, hideAfterDoubleHash, wrapWidth)
+	return size.X, size.Y
+}
+
+// SetNextWindowSize sets size of the next window.
+func SetNextWindowSize(width, height float32) {
+	imgui.SetNextWindowSize(imgui.Vec2{X: width, Y: height})
+}
+
+// ExecCondition represents imgui.Condition.
+type ExecCondition imgui.Condition
+
+// imgui conditions.
+const (
+	ConditionAlways       ExecCondition = ExecCondition(imgui.ConditionAlways)
+	ConditionOnce         ExecCondition = ExecCondition(imgui.ConditionOnce)
+	ConditionFirstUseEver ExecCondition = ExecCondition(imgui.ConditionFirstUseEver)
+	ConditionAppearing    ExecCondition = ExecCondition(imgui.ConditionAppearing)
+)
+
+// SetNextWindowPos sets position of next window.
+func SetNextWindowPos(x, y float32) {
+	imgui.SetNextWindowPos(imgui.Vec2{X: x, Y: y})
+}
+
+// SetNextWindowSizeV does similar to SetNextWIndowSize but allows to specify imgui.Condition.
+func SetNextWindowSizeV(width, height float32, condition ExecCondition) {
+	imgui.SetNextWindowSizeV(
+		imgui.Vec2{
+			X: width,
+			Y: height,
+		},
+		imgui.Condition(condition),
+	)
+}
+
+// SetItemDefaultFocus set the item focused by default.
+func SetItemDefaultFocus() {
+	imgui.SetItemDefaultFocus()
+}
+
+// SetKeyboardFocusHere sets keyboard focus at *NEXT* widget.
+func SetKeyboardFocusHere() {
+	SetKeyboardFocusHereV(0)
+}
+
+// SetKeyboardFocusHereV sets keyboard on the next widget. Use positive 'offset' to access sub components of a multiple component widget. Use -1 to access previous widget.
+func SetKeyboardFocusHereV(i int) {
+	imgui.SetKeyboardFocusHereV(i)
+}
+
+// PushClipRect pushes a clipping rectangle for both ImGui logic (hit-testing etc.) and low-level ImDrawList rendering.
+func PushClipRect(clipRectMin, clipRectMax image.Point, intersectWithClipRect bool) {
+	imgui.PushClipRect(ToVec2(clipRectMin), ToVec2(clipRectMax), intersectWithClipRect)
+}
+
+// PopClipRect should be called to end PushClipRect.
+func PopClipRect() {
+	imgui.PopClipRect()
+}
+
+// Assert checks if cond. If not cond, it alls golang panic.
+func Assert(cond bool, t, method, msg string, args ...any) {
+	if !cond {
+		fatal(t, method, msg, args...)
+	}
+}
+
+func fatal(widgetName, method, message string, args ...any) {
+	if widgetName != "" {
+		widgetName = fmt.Sprintf("(*%s)", widgetName)
+	}
+
+	log.Panicf("giu: %s.%s: %s", widgetName, method, fmt.Sprintf(message, args...))
+}
+
+// OpenURL opens `url` in default browser.
+func OpenURL(url string) {
+	if err := browser.OpenURL(url); err != nil {
+		log.Printf("Error opening %s: %v", url, err)
+	}
+}

+ 745 - 0
vendor/github.com/AllenDang/giu/Widgets.go

@@ -0,0 +1,745 @@
+package giu
+
+import (
+	"fmt"
+	"image/color"
+
+	"github.com/AllenDang/imgui-go"
+)
+
+// GenAutoID automatically generates fidget's id.
+func GenAutoID(id string) string {
+	return fmt.Sprintf("%s##%d", id, Context.GetWidgetIndex())
+}
+
+var _ Widget = &RowWidget{}
+
+// RowWidget joins a layout into one line
+// calls imgui.SameLine().
+type RowWidget struct {
+	widgets Layout
+}
+
+// Row creates RowWidget.
+func Row(widgets ...Widget) *RowWidget {
+	return &RowWidget{
+		widgets: widgets,
+	}
+}
+
+// Build implements Widget interface.
+func (l *RowWidget) Build() {
+	isFirst := true
+	l.widgets.Range(func(w Widget) {
+		switch w.(type) {
+		case *TooltipWidget,
+			*ContextMenuWidget, *PopupModalWidget,
+			*PopupWidget:
+			// noop
+		default:
+			if _, isLabel := w.(*LabelWidget); isLabel {
+				AlignTextToFramePadding()
+			}
+
+			if !isFirst {
+				imgui.SameLine()
+			} else {
+				isFirst = false
+			}
+		}
+
+		w.Build()
+	})
+}
+
+// SameLine wrapps imgui.SomeLine
+// Don't use if you don't have to (use RowWidget instead).
+func SameLine() {
+	imgui.SameLine()
+}
+
+var _ Widget = &ChildWidget{}
+
+type ChildWidget struct {
+	id     string
+	width  float32
+	height float32
+	border bool
+	flags  WindowFlags
+	layout Layout
+}
+
+// Build implements Widget interface.
+func (c *ChildWidget) Build() {
+	if imgui.BeginChildV(c.id, imgui.Vec2{X: c.width, Y: c.height}, c.border, int(c.flags)) {
+		c.layout.Build()
+	}
+
+	imgui.EndChild()
+}
+
+func (c *ChildWidget) Border(border bool) *ChildWidget {
+	c.border = border
+	return c
+}
+
+func (c *ChildWidget) Size(width, height float32) *ChildWidget {
+	c.width, c.height = width, height
+	return c
+}
+
+func (c *ChildWidget) Flags(flags WindowFlags) *ChildWidget {
+	c.flags = flags
+	return c
+}
+
+func (c *ChildWidget) Layout(widgets ...Widget) *ChildWidget {
+	c.layout = Layout(widgets)
+	return c
+}
+
+// ID sets the interval id of child widgets.
+func (c *ChildWidget) ID(id string) *ChildWidget {
+	c.id = id
+	return c
+}
+
+func Child() *ChildWidget {
+	return &ChildWidget{
+		id:     GenAutoID("Child"),
+		width:  0,
+		height: 0,
+		border: true,
+		flags:  0,
+		layout: nil,
+	}
+}
+
+var _ Widget = &ComboCustomWidget{}
+
+// ComboCustomWidget represents a combo with custom layout when opened.
+type ComboCustomWidget struct {
+	label        string
+	previewValue string
+	width        float32
+	flags        ComboFlags
+	layout       Layout
+}
+
+// ComboCustom creates a new combo custom widget.
+func ComboCustom(label, previewValue string) *ComboCustomWidget {
+	return &ComboCustomWidget{
+		label:        GenAutoID(label),
+		previewValue: tStr(previewValue),
+		width:        0,
+		flags:        0,
+		layout:       nil,
+	}
+}
+
+// Layout add combo's layout.
+func (cc *ComboCustomWidget) Layout(widgets ...Widget) *ComboCustomWidget {
+	cc.layout = Layout(widgets)
+	return cc
+}
+
+// Flags allows to set combo flags (see Flags.go).
+func (cc *ComboCustomWidget) Flags(flags ComboFlags) *ComboCustomWidget {
+	cc.flags = flags
+	return cc
+}
+
+// Size sets combo preiview width.
+func (cc *ComboCustomWidget) Size(width float32) *ComboCustomWidget {
+	cc.width = width
+	return cc
+}
+
+// Build implements Widget interface.
+func (cc *ComboCustomWidget) Build() {
+	if cc.width > 0 {
+		imgui.PushItemWidth(cc.width)
+		defer imgui.PopItemWidth()
+	}
+
+	if imgui.BeginComboV(tStr(cc.label), cc.previewValue, int(cc.flags)) {
+		cc.layout.Build()
+		imgui.EndCombo()
+	}
+}
+
+var _ Widget = &ComboWidget{}
+
+// ComboWidget is a wrapper of ComboCustomWidget.
+// It creates a combo of selectables. (it is the most frequently used).
+type ComboWidget struct {
+	label        string
+	previewValue string
+	items        []string
+	selected     *int32
+	width        float32
+	flags        ComboFlags
+	onChange     func()
+}
+
+// Combo creates a new ComboWidget.
+func Combo(label, previewValue string, items []string, selected *int32) *ComboWidget {
+	return &ComboWidget{
+		label:        GenAutoID(label),
+		previewValue: tStr(previewValue),
+		items:        tStrSlice(items),
+		selected:     selected,
+		flags:        0,
+		width:        0,
+		onChange:     nil,
+	}
+}
+
+// Build implements Widget interface.
+func (c *ComboWidget) Build() {
+	if c.width > 0 {
+		imgui.PushItemWidth(c.width)
+		defer imgui.PopItemWidth()
+	}
+
+	if imgui.BeginComboV(tStr(c.label), c.previewValue, int(c.flags)) {
+		for i, item := range c.items {
+			if imgui.Selectable(item) {
+				*c.selected = int32(i)
+				if c.onChange != nil {
+					c.onChange()
+				}
+			}
+		}
+
+		imgui.EndCombo()
+	}
+}
+
+// Flags allows to set combo flags (see Flags.go).
+func (c *ComboWidget) Flags(flags ComboFlags) *ComboWidget {
+	c.flags = flags
+	return c
+}
+
+// Size sets combo's width.
+func (c *ComboWidget) Size(width float32) *ComboWidget {
+	c.width = width
+	return c
+}
+
+// OnChange sets callback when combo value gets changed.
+func (c *ComboWidget) OnChange(onChange func()) *ComboWidget {
+	c.onChange = onChange
+	return c
+}
+
+var _ Widget = &ContextMenuWidget{}
+
+type ContextMenuWidget struct {
+	id          string
+	mouseButton MouseButton
+	layout      Layout
+}
+
+func ContextMenu() *ContextMenuWidget {
+	return &ContextMenuWidget{
+		mouseButton: MouseButtonRight,
+		layout:      nil,
+		id:          GenAutoID("ContextMenu"),
+	}
+}
+
+func (c *ContextMenuWidget) Layout(widgets ...Widget) *ContextMenuWidget {
+	c.layout = Layout(widgets)
+	return c
+}
+
+func (c *ContextMenuWidget) MouseButton(mouseButton MouseButton) *ContextMenuWidget {
+	c.mouseButton = mouseButton
+	return c
+}
+
+func (c *ContextMenuWidget) ID(id string) *ContextMenuWidget {
+	c.id = id
+	return c
+}
+
+// Build implements Widget interface.
+func (c *ContextMenuWidget) Build() {
+	if imgui.BeginPopupContextItemV(c.id, int(c.mouseButton)) {
+		c.layout.Build()
+		imgui.EndPopup()
+	}
+}
+
+var _ Widget = &DragIntWidget{}
+
+type DragIntWidget struct {
+	label  string
+	value  *int32
+	speed  float32
+	min    int32
+	max    int32
+	format string
+}
+
+func DragInt(label string, value *int32, min, max int32) *DragIntWidget {
+	return &DragIntWidget{
+		label:  GenAutoID(label),
+		value:  value,
+		speed:  1.0,
+		min:    min,
+		max:    max,
+		format: "%d",
+	}
+}
+
+func (d *DragIntWidget) Speed(speed float32) *DragIntWidget {
+	d.speed = speed
+	return d
+}
+
+func (d *DragIntWidget) Format(format string) *DragIntWidget {
+	d.format = format
+	return d
+}
+
+// Build implements Widget interface.
+func (d *DragIntWidget) Build() {
+	imgui.DragIntV(tStr(d.label), d.value, d.speed, d.min, d.max, d.format)
+}
+
+var _ Widget = &ColumnWidget{}
+
+// ColumnWidget will place all widgets one by one vertically.
+type ColumnWidget struct {
+	widgets Layout
+}
+
+// Column creates a new ColumnWidget.
+func Column(widgets ...Widget) *ColumnWidget {
+	return &ColumnWidget{
+		widgets: widgets,
+	}
+}
+
+// Build implements Widget interface.
+func (g *ColumnWidget) Build() {
+	imgui.BeginGroup()
+
+	g.widgets.Build()
+
+	imgui.EndGroup()
+}
+
+var _ Widget = &MainMenuBarWidget{}
+
+type MainMenuBarWidget struct {
+	layout Layout
+}
+
+func MainMenuBar() *MainMenuBarWidget {
+	return &MainMenuBarWidget{
+		layout: nil,
+	}
+}
+
+func (m *MainMenuBarWidget) Layout(widgets ...Widget) *MainMenuBarWidget {
+	m.layout = Layout(widgets)
+	return m
+}
+
+// Build implements Widget interface.
+func (m *MainMenuBarWidget) Build() {
+	if imgui.BeginMainMenuBar() {
+		m.layout.Build()
+		imgui.EndMainMenuBar()
+	}
+}
+
+var _ Widget = &MenuBarWidget{}
+
+type MenuBarWidget struct {
+	layout Layout
+}
+
+func MenuBar() *MenuBarWidget {
+	return &MenuBarWidget{
+		layout: nil,
+	}
+}
+
+func (m *MenuBarWidget) Layout(widgets ...Widget) *MenuBarWidget {
+	m.layout = Layout(widgets)
+	return m
+}
+
+// Build implements Widget interface.
+func (m *MenuBarWidget) Build() {
+	if imgui.BeginMenuBar() {
+		m.layout.Build()
+		imgui.EndMenuBar()
+	}
+}
+
+var _ Widget = &MenuItemWidget{}
+
+type MenuItemWidget struct {
+	label    string
+	selected bool
+	enabled  bool
+	onClick  func()
+}
+
+func MenuItem(label string) *MenuItemWidget {
+	return &MenuItemWidget{
+		label:    GenAutoID(label),
+		selected: false,
+		enabled:  true,
+		onClick:  nil,
+	}
+}
+
+func MenuItemf(format string, args ...any) *MenuItemWidget {
+	return MenuItem(fmt.Sprintf(format, args...))
+}
+
+func (m *MenuItemWidget) Selected(s bool) *MenuItemWidget {
+	m.selected = s
+	return m
+}
+
+func (m *MenuItemWidget) Enabled(e bool) *MenuItemWidget {
+	m.enabled = e
+	return m
+}
+
+func (m *MenuItemWidget) OnClick(onClick func()) *MenuItemWidget {
+	m.onClick = onClick
+	return m
+}
+
+// Build implements Widget interface.
+func (m *MenuItemWidget) Build() {
+	if imgui.MenuItemV(tStr(m.label), "", m.selected, m.enabled) && m.onClick != nil {
+		m.onClick()
+	}
+}
+
+var _ Widget = &MenuWidget{}
+
+type MenuWidget struct {
+	label   string
+	enabled bool
+	layout  Layout
+}
+
+func Menu(label string) *MenuWidget {
+	return &MenuWidget{
+		label:   GenAutoID(label),
+		enabled: true,
+		layout:  nil,
+	}
+}
+
+func Menuf(format string, args ...any) *MenuWidget {
+	return Menu(fmt.Sprintf(format, args...))
+}
+
+func (m *MenuWidget) Enabled(e bool) *MenuWidget {
+	m.enabled = e
+	return m
+}
+
+func (m *MenuWidget) Layout(widgets ...Widget) *MenuWidget {
+	m.layout = Layout(widgets)
+	return m
+}
+
+// Build implements Widget interface.
+func (m *MenuWidget) Build() {
+	if imgui.BeginMenuV(tStr(m.label), m.enabled) {
+		m.layout.Build()
+		imgui.EndMenu()
+	}
+}
+
+var _ Widget = &ProgressBarWidget{}
+
+type ProgressBarWidget struct {
+	fraction float32
+	width    float32
+	height   float32
+	overlay  string
+}
+
+func ProgressBar(fraction float32) *ProgressBarWidget {
+	return &ProgressBarWidget{
+		fraction: fraction,
+		width:    0,
+		height:   0,
+		overlay:  "",
+	}
+}
+
+func (p *ProgressBarWidget) Size(width, height float32) *ProgressBarWidget {
+	p.width, p.height = width, height
+	return p
+}
+
+func (p *ProgressBarWidget) Overlay(overlay string) *ProgressBarWidget {
+	p.overlay = tStr(overlay)
+	return p
+}
+
+func (p *ProgressBarWidget) Overlayf(format string, args ...any) *ProgressBarWidget {
+	return p.Overlay(fmt.Sprintf(format, args...))
+}
+
+// Build implements Widget interface.
+func (p *ProgressBarWidget) Build() {
+	imgui.ProgressBarV(p.fraction, imgui.Vec2{X: p.width, Y: p.height}, p.overlay)
+}
+
+var _ Widget = &SeparatorWidget{}
+
+type SeparatorWidget struct{}
+
+// Build implements Widget interface.
+func (s *SeparatorWidget) Build() {
+	imgui.Separator()
+}
+
+func Separator() *SeparatorWidget {
+	return &SeparatorWidget{}
+}
+
+var _ Widget = &DummyWidget{}
+
+type DummyWidget struct {
+	width  float32
+	height float32
+}
+
+// Build implements Widget interface.
+func (d *DummyWidget) Build() {
+	w, h := GetAvailableRegion()
+
+	if d.width < 0 {
+		d.width = w + d.width
+	}
+
+	if d.height < 0 {
+		d.height = h + d.height
+	}
+
+	imgui.Dummy(imgui.Vec2{X: d.width, Y: d.height})
+}
+
+func Dummy(width, height float32) *DummyWidget {
+	return &DummyWidget{
+		width:  width,
+		height: height,
+	}
+}
+
+type TabItemWidget struct {
+	label  string
+	open   *bool
+	flags  TabItemFlags
+	layout Layout
+}
+
+func TabItem(label string) *TabItemWidget {
+	return &TabItemWidget{
+		label:  tStr(label),
+		open:   nil,
+		flags:  0,
+		layout: nil,
+	}
+}
+
+func TabItemf(format string, args ...any) *TabItemWidget {
+	return TabItem(fmt.Sprintf(format, args...))
+}
+
+func (t *TabItemWidget) IsOpen(open *bool) *TabItemWidget {
+	t.open = open
+	return t
+}
+
+func (t *TabItemWidget) Flags(flags TabItemFlags) *TabItemWidget {
+	t.flags = flags
+	return t
+}
+
+func (t *TabItemWidget) Layout(widgets ...Widget) *TabItemWidget {
+	t.layout = Layout(widgets)
+	return t
+}
+
+// BuildTabItem executes tab item build steps.
+func (t *TabItemWidget) BuildTabItem() {
+	if imgui.BeginTabItemV(t.label, t.open, int(t.flags)) {
+		t.layout.Build()
+		imgui.EndTabItem()
+	}
+}
+
+var _ Widget = &TabBarWidget{}
+
+type TabBarWidget struct {
+	id       string
+	flags    TabBarFlags
+	tabItems []*TabItemWidget
+}
+
+func TabBar() *TabBarWidget {
+	return &TabBarWidget{
+		id:    GenAutoID("TabBar"),
+		flags: 0,
+	}
+}
+
+func (t *TabBarWidget) Flags(flags TabBarFlags) *TabBarWidget {
+	t.flags = flags
+	return t
+}
+
+func (t *TabBarWidget) ID(id string) *TabBarWidget {
+	t.id = id
+	return t
+}
+
+func (t *TabBarWidget) TabItems(items ...*TabItemWidget) *TabBarWidget {
+	t.tabItems = items
+	return t
+}
+
+// Build implements Widget interface.
+func (t *TabBarWidget) Build() {
+	if imgui.BeginTabBarV(t.id, int(t.flags)) {
+		for _, ti := range t.tabItems {
+			ti.BuildTabItem()
+		}
+		imgui.EndTabBar()
+	}
+}
+
+var _ Widget = &TooltipWidget{}
+
+type TooltipWidget struct {
+	tip    string
+	layout Layout
+}
+
+// Build implements Widget interface.
+func (t *TooltipWidget) Build() {
+	if imgui.IsItemHovered() {
+		if t.layout != nil {
+			imgui.BeginTooltip()
+			t.layout.Build()
+			imgui.EndTooltip()
+		} else {
+			imgui.SetTooltip(t.tip)
+		}
+	}
+}
+
+func Tooltip(tip string) *TooltipWidget {
+	return &TooltipWidget{
+		tip:    tStr(tip),
+		layout: nil,
+	}
+}
+
+func Tooltipf(format string, args ...any) *TooltipWidget {
+	return Tooltip(fmt.Sprintf(format, args...))
+}
+
+func (t *TooltipWidget) Layout(widgets ...Widget) *TooltipWidget {
+	t.layout = Layout(widgets)
+	return t
+}
+
+var _ Widget = &SpacingWidget{}
+
+type SpacingWidget struct{}
+
+// Build implements Widget interface.
+func (s *SpacingWidget) Build() {
+	imgui.Spacing()
+}
+
+func Spacing() *SpacingWidget {
+	return &SpacingWidget{}
+}
+
+var _ Widget = &ColorEditWidget{}
+
+type ColorEditWidget struct {
+	label    string
+	color    *color.RGBA
+	flags    ColorEditFlags
+	width    float32
+	onChange func()
+}
+
+func ColorEdit(label string, c *color.RGBA) *ColorEditWidget {
+	return &ColorEditWidget{
+		label: GenAutoID(label),
+		color: c,
+		flags: ColorEditFlagsNone,
+	}
+}
+
+func (ce *ColorEditWidget) OnChange(cb func()) *ColorEditWidget {
+	ce.onChange = cb
+	return ce
+}
+
+func (ce *ColorEditWidget) Flags(f ColorEditFlags) *ColorEditWidget {
+	ce.flags = f
+	return ce
+}
+
+func (ce *ColorEditWidget) Size(width float32) *ColorEditWidget {
+	ce.width = width
+	return ce
+}
+
+// Build implements Widget interface.
+func (ce *ColorEditWidget) Build() {
+	c := ToVec4Color(*ce.color)
+	col := [4]float32{
+		c.X,
+		c.Y,
+		c.Z,
+		c.W,
+	}
+
+	if ce.width > 0 {
+		imgui.PushItemWidth(ce.width)
+	}
+
+	if imgui.ColorEdit4V(
+		tStr(ce.label),
+		&col,
+		int(ce.flags),
+	) {
+		*ce.color = Vec4ToRGBA(imgui.Vec4{
+			X: col[0],
+			Y: col[1],
+			Z: col[2],
+			W: col[3],
+		})
+		if ce.onChange != nil {
+			ce.onChange()
+		}
+	}
+
+	if ce.width > 0 {
+		imgui.PopItemWidth()
+	}
+}

+ 202 - 0
vendor/github.com/AllenDang/giu/Window.go

@@ -0,0 +1,202 @@
+package giu
+
+import (
+	"fmt"
+
+	"github.com/AllenDang/imgui-go"
+)
+
+// SingleWindow creates one window filling all available space
+// in MasterWindow. If SingleWindow is set up, no other windows can't be
+// definied.
+func SingleWindow() *WindowWidget {
+	size := Context.platform.DisplaySize()
+	title := fmt.Sprintf("SingleWindow_%d", Context.GetWidgetIndex())
+	return Window(title).
+		Flags(
+			imgui.WindowFlagsNoTitleBar|
+				imgui.WindowFlagsNoCollapse|
+				imgui.WindowFlagsNoScrollbar|
+				imgui.WindowFlagsNoMove|
+				imgui.WindowFlagsNoResize).
+		Size(size[0], size[1])
+}
+
+// SingleWindowWithMenuBar creates a SingleWindow and allows to add menubar on its top.
+func SingleWindowWithMenuBar() *WindowWidget {
+	size := Context.platform.DisplaySize()
+	title := fmt.Sprintf("SingleWindow_%d", Context.GetWidgetIndex())
+	return Window(title).
+		Flags(
+			imgui.WindowFlagsNoTitleBar|
+				imgui.WindowFlagsNoCollapse|
+				imgui.WindowFlagsNoScrollbar|
+				imgui.WindowFlagsNoMove|
+				imgui.WindowFlagsMenuBar|
+				imgui.WindowFlagsNoResize).Size(size[0], size[1])
+}
+
+var _ Disposable = &windowState{}
+
+type windowState struct {
+	hasFocus bool
+	currentPosition,
+	currentSize imgui.Vec2
+}
+
+// Dispose implements Disposable interface.
+func (s *windowState) Dispose() {
+	// noop
+}
+
+// WindowWidget represents imgui.Window
+// Windows are used to display ui widgets.
+// They are in second place in the giu hierarchy (after the MasterWindow)
+// NOTE: to disable multiple window, use SingleWindow.
+type WindowWidget struct {
+	title         string
+	open          *bool
+	flags         WindowFlags
+	x, y          float32
+	width, height float32
+	bringToFront  bool
+}
+
+// Window creates a WindowWidget.
+func Window(title string) *WindowWidget {
+	return &WindowWidget{
+		title: title,
+	}
+}
+
+// IsOpen sets if window widget is `opened` (minimalized).
+func (w *WindowWidget) IsOpen(open *bool) *WindowWidget {
+	w.open = open
+	return w
+}
+
+// Flags sets window flags.
+func (w *WindowWidget) Flags(flags WindowFlags) *WindowWidget {
+	w.flags = flags
+	return w
+}
+
+// Size sets window size
+// NOTE: size can be changed by user, if you want to prevent
+// user from changing window size, use NoResize flag.
+func (w *WindowWidget) Size(width, height float32) *WindowWidget {
+	w.width, w.height = width, height
+	return w
+}
+
+// Pos sets the window start position
+// NOTE: The position could be changed by user later.
+// To prevent user from changin window position use
+// WIndowFlagsNoMove.
+func (w *WindowWidget) Pos(x, y float32) *WindowWidget {
+	w.x, w.y = x, y
+	return w
+}
+
+// Layout is a final step of the window setup.
+// it should be called to add a layout to the window and build it.
+func (w *WindowWidget) Layout(widgets ...Widget) {
+	if widgets == nil {
+		return
+	}
+
+	ws := w.getState()
+
+	if w.flags&imgui.WindowFlagsNoMove != 0 && w.flags&imgui.WindowFlagsNoResize != 0 {
+		imgui.SetNextWindowPos(imgui.Vec2{X: w.x, Y: w.y})
+		imgui.SetNextWindowSize(imgui.Vec2{X: w.width, Y: w.height})
+	} else {
+		imgui.SetNextWindowPosV(imgui.Vec2{X: w.x, Y: w.y}, imgui.ConditionFirstUseEver, imgui.Vec2{X: 0, Y: 0})
+		imgui.SetNextWindowSizeV(imgui.Vec2{X: w.width, Y: w.height}, imgui.ConditionFirstUseEver)
+	}
+
+	if w.bringToFront {
+		imgui.SetNextWindowFocus()
+		w.bringToFront = false
+	}
+
+	widgets = append(widgets,
+		Custom(func() {
+			hasFocus := IsWindowFocused(0)
+			if !hasFocus && ws.hasFocus {
+				Context.InputHandler.UnregisterWindowShortcuts()
+			}
+
+			ws.hasFocus = hasFocus
+
+			ws.currentPosition = imgui.WindowPos()
+			ws.currentSize = imgui.WindowSize()
+		}),
+	)
+
+	showed := imgui.BeginV(tStr(w.title), w.open, int(w.flags))
+
+	if showed {
+		Layout(widgets).Build()
+	}
+
+	imgui.End()
+}
+
+// CurrentPosition returns a current position of the window.
+func (w *WindowWidget) CurrentPosition() (x, y float32) {
+	pos := w.getState().currentPosition
+	return pos.X, pos.Y
+}
+
+// CurrentSize returns current size of the window.
+func (w *WindowWidget) CurrentSize() (width, height float32) {
+	size := w.getState().currentSize
+	return size.X, size.Y
+}
+
+// BringToFront sets window focused.
+func (w *WindowWidget) BringToFront() {
+	w.bringToFront = true
+}
+
+// HasFocus returns true if window is focused.
+func (w *WindowWidget) HasFocus() bool {
+	return w.getState().hasFocus
+}
+
+// RegisterKeyboardShortcuts adds local (window-level) keyboard shortcuts
+// see InputHandler.go.
+func (w *WindowWidget) RegisterKeyboardShortcuts(s ...WindowShortcut) *WindowWidget {
+	if w.HasFocus() {
+		for _, shortcut := range s {
+			Context.InputHandler.RegisterKeyboardShortcuts(Shortcut{
+				Key:      shortcut.Key,
+				Modifier: shortcut.Modifier,
+				Callback: shortcut.Callback,
+				IsGlobal: LocalShortcut,
+			})
+		}
+	}
+
+	return w
+}
+
+func (w *WindowWidget) getStateID() string {
+	return fmt.Sprintf("%s_windowState", w.title)
+}
+
+// returns window state.
+func (w *WindowWidget) getState() (state *windowState) {
+	if s := Context.GetState(w.getStateID()); s != nil {
+		var isOk bool
+		state, isOk = s.(*windowState)
+		Assert(isOk, "WindowWidget", "getState", "unexpected state recovered.")
+	} else {
+		state = &windowState{}
+
+		Context.SetState(w.getStateID(), state)
+	}
+
+	return state
+}

+ 7 - 0
vendor/github.com/AllenDang/giu/build_windows.go

@@ -0,0 +1,7 @@
+//go:build windows
+// +build windows
+
+package giu
+
+// #cgo LDFLAGS: -static
+import "C"

+ 5 - 0
vendor/github.com/AllenDang/giu/doc.go

@@ -0,0 +1,5 @@
+// Package giu - A rapid cross-platform GUI framework for Go based on Dear ImGui
+// and the great Go binding imgui-go.
+//
+// for details and usage see README of the project.
+package giu

+ 21 - 0
vendor/github.com/AllenDang/go-findfont/LICENSE

@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Florian Pigorsch
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 57 - 0
vendor/github.com/AllenDang/go-findfont/README.md

@@ -0,0 +1,57 @@
+[![GoDoc](https://godoc.org/github.com/flopp/go-findfont?status.svg)](https://godoc.org/github.com/flopp/go-findfont)
+[![Go Report Card](http://goreportcard.com/badge/flopp/go-findfont)](http://goreportcard.com/report/flopp/go-findfont)
+[![License MIT](https://img.shields.io/badge/license-MIT-lightgrey.svg?style=flat)](https://github.com/flopp/go-findfont/)
+
+# go-findfont
+A platform-agnostic go (golang) library to easily locate truetype font files in your system's user and system font directories.
+
+## What?
+go-findfont is a golang library that allows you to locate font file on your system. The library is currently aware of the default font directories on Linux/Unix, Windows, and MacOS.
+
+## How?
+
+### Installation
+
+Installing go-findfont is as easy as
+
+```bash
+go get -u github.com/flopp/go-findfont
+```
+
+### Library Usage
+
+```go
+
+import (
+  "fmt"
+  "io/ioutil"
+  
+  "github.com/flopp/go-findfont"
+  "github.com/golang/freetype/truetype"
+)
+
+func main() {
+  fontPath, err := findfont.Find("arial.ttf")
+  if err != nil {
+    panic(err)
+  }
+  fmt.Printf("Found 'arial.ttf' in '%s'\n", fontPath)
+
+  // load the font with the freetype library
+  fontData, err := ioutil.ReadFile(fontPath)
+  if err != nil {
+    panic(err)
+  }
+  font, err := truetype.Parse(fontData)
+  if err != nil {
+    panic(err)
+  }
+
+  // use the font...
+}
+```
+
+## License
+Copyright 2016 Florian Pigorsch. All rights reserved.
+
+Use of this source code is governed by a MIT-style license that can be found in the LICENSE file.

+ 110 - 0
vendor/github.com/AllenDang/go-findfont/findfont.go

@@ -0,0 +1,110 @@
+// Copyright 2016 Florian Pigorsch. All rights reserved.
+//
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package findfont
+
+import (
+	"fmt"
+	"os"
+	"os/user"
+	"path/filepath"
+	"strings"
+)
+
+// Find tries to locate the specified font file in the current directory as
+// well as in platform specific user and system font directories; if there is
+// no exact match, Find tries substring matching.
+func Find(fileName string) (filePath string, err error) {
+	// check if fileName already points to a readable file
+	if _, err := os.Stat(fileName); err == nil {
+		return fileName, nil
+	}
+
+	// search in user and system directories
+	return find(filepath.Base(fileName))
+}
+
+// List returns a list of all font files found on the system.
+func List() (filePaths []string) {
+	pathList := []string{}
+
+	walkF := func(path string, info os.FileInfo, err error) error {
+		if err == nil {
+			lowerPath := strings.ToLower(path)
+			if !info.IsDir() && (strings.HasSuffix(lowerPath, ".ttf") || strings.HasSuffix(lowerPath, ".ttc") || strings.HasSuffix(lowerPath, ".otf")) {
+				pathList = append(pathList, path)
+			}
+		}
+		return nil
+	}
+	for _, dir := range getFontDirectories() {
+		_ = filepath.Walk(dir, walkF)
+	}
+
+	return pathList
+}
+
+func stripExtension(fileName string) string {
+	return strings.TrimSuffix(fileName, filepath.Ext(fileName))
+}
+
+func expandUser(path string) (expandedPath string) {
+	if strings.HasPrefix(path, "~") {
+		if u, err := user.Current(); err == nil {
+			return strings.Replace(path, "~", u.HomeDir, -1)
+		}
+	}
+	return path
+}
+
+func find(needle string) (filePath string, err error) {
+	lowerNeedle := strings.ToLower(needle)
+	lowerNeedleBase := stripExtension(lowerNeedle)
+
+	match := ""
+	partial := ""
+	partialScore := -1
+
+	walkF := func(path string, info os.FileInfo, err error) error {
+		// we have already found a match -> nothing to do
+		if match != "" {
+			return nil
+		}
+		if err != nil {
+			return nil
+		}
+
+		lowerPath := strings.ToLower(info.Name())
+
+		if !info.IsDir() && (strings.HasSuffix(lowerPath, ".ttf") || strings.HasSuffix(lowerPath, ".ttc") || strings.HasSuffix(lowerPath, ".otf")) {
+			lowerBase := stripExtension(lowerPath)
+			if lowerPath == lowerNeedle {
+				// exact match
+				match = path
+			} else if strings.Contains(lowerBase, lowerNeedleBase) {
+				// partial match
+				score := len(lowerBase) - len(lowerNeedle)
+				if partialScore < 0 || score < partialScore {
+					partialScore = score
+					partial = path
+				}
+			}
+		}
+		return nil
+	}
+
+	for _, dir := range getFontDirectories() {
+		_ = filepath.Walk(dir, walkF)
+		if match != "" {
+			return match, nil
+		}
+	}
+
+	if partial != "" {
+		return partial, nil
+	}
+
+	return "", fmt.Errorf("cannot find font '%s' in user or system directories", needle)
+}

+ 14 - 0
vendor/github.com/AllenDang/go-findfont/fontdirs_darwin.go

@@ -0,0 +1,14 @@
+// Copyright 2016 Florian Pigorsch. All rights reserved.
+//
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package findfont
+
+func getFontDirectories() (paths []string) {
+	return []string{
+		expandUser("~/Library/Fonts/"),
+		"/Library/Fonts/",
+		"/System/Library/Fonts/",
+	}
+}

+ 36 - 0
vendor/github.com/AllenDang/go-findfont/fontdirs_unix.go

@@ -0,0 +1,36 @@
+// +build dragonfly freebsd linux nacl netbsd openbsd solaris
+
+// Copyright 2016 Florian Pigorsch. All rights reserved.
+//
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package findfont
+
+import (
+	"os"
+	"path/filepath"
+)
+
+func getFontDirectories() (paths []string) {
+	directories := getUserFontDirs()
+	directories = append(directories, getSystemFontDirs()...)
+	return directories
+}
+
+func getUserFontDirs() (paths []string) {
+	if dataPath := os.Getenv("XDG_DATA_HOME"); dataPath != "" {
+		return []string{expandUser("~/.fonts/"), filepath.Join(expandUser(dataPath), "fonts")}
+	}
+	return []string{expandUser("~/.fonts/"), expandUser("~/.local/share/fonts/")}
+}
+
+func getSystemFontDirs() (paths []string) {
+	if dataPaths := os.Getenv("XDG_DATA_DIRS"); dataPaths != "" {
+		for _, dataPath := range filepath.SplitList(dataPaths) {
+			paths = append(paths, filepath.Join(expandUser(dataPath), "fonts"))
+		}
+		return paths
+	}
+	return []string{"/usr/local/share/fonts/", "/usr/share/fonts/"}
+}

+ 18 - 0
vendor/github.com/AllenDang/go-findfont/fontdirs_windows.go

@@ -0,0 +1,18 @@
+// Copyright 2016 Florian Pigorsch. All rights reserved.
+//
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package findfont
+
+import (
+	"os"
+	"path/filepath"
+)
+
+func getFontDirectories() (paths []string) {
+	return []string{
+		filepath.Join(os.Getenv("windir"), "Fonts"),
+		filepath.Join(os.Getenv("localappdata"), "Microsoft", "Windows", "Fonts"),
+	}
+}

+ 7 - 0
vendor/github.com/AllenDang/imgui-go/.gitignore

@@ -0,0 +1,7 @@
+.idea/
+
+imgui.ini
+
+
+.DS_Store
+.ccls-cache

BIN
vendor/github.com/AllenDang/imgui-go/.go.mod.swp


+ 33 - 0
vendor/github.com/AllenDang/imgui-go/Assert.go

@@ -0,0 +1,33 @@
+package imgui
+
+import "C"
+import (
+	"errors"
+	"fmt"
+)
+
+// AssertHandler is a handler for an assertion that happened in the native part of ImGui.
+type AssertHandler func(expression string, file string, line int)
+
+var assertHandler AssertHandler = func(expression string, file string, line int) {
+	message := fmt.Sprintf(`Assertion failed!
+File: %s, Line %d
+
+Expression: %s
+`, file, line, expression)
+	panic(errors.New(message))
+}
+
+// SetAssertHandler registers a handler function for all future assertions.
+// Setting nil will disable special handling.
+// The default handler panics.
+func SetAssertHandler(handler AssertHandler) {
+	assertHandler = handler
+}
+
+//export iggAssert
+func iggAssert(result C.int, expression *C.char, file *C.char, line C.int) {
+	if (result == 0) && (assertHandler != nil) {
+		assertHandler(C.GoString(expression), C.GoString(file), int(line))
+	}
+}

+ 17 - 0
vendor/github.com/AllenDang/imgui-go/BackendFlags.go

@@ -0,0 +1,17 @@
+package imgui
+
+const (
+	// BackendFlagNone default = 0
+	BackendFlagNone = 0
+	// BackendFlagHasGamepad back-end Platform supports gamepad and currently has one connected.
+	BackendFlagHasGamepad = 1 << 0
+	// BackendFlagHasMouseCursors back-end Platform supports honoring GetMouseCursor() value to change the OS cursor
+	// shape.
+	BackendFlagHasMouseCursors = 1 << 1
+	// BackendFlagHasSetMousePos back-end Platform supports io.WantSetMousePos requests to reposition the OS mouse
+	// position (only used if ImGuiConfigFlags_NavEnableSetMousePos is set).
+	BackendFlagHasSetMousePos = 1 << 2
+	// BackendFlagsRendererHasVtxOffset back-end Renderer supports ImDrawCmd::VtxOffset. This enables output of large
+	// meshes (64K+ vertices) while still using 16-bits indices.
+	BackendFlagsRendererHasVtxOffset = 1 << 3
+)

+ 89 - 0
vendor/github.com/AllenDang/imgui-go/CONTRIBUTING.md

@@ -0,0 +1,89 @@
+## Contributing Guidelines
+
+Thank you for considering to contribute to this library!
+
+The following text lists guidelines for contributions.
+These guidelines don't have legal status, so use them as a reference and common sense - and feel free to update them as well!
+
+
+### "I just want to know..."
+
+For questions, or general usage-information about **Dear ImGui**, please refer to the [homepage](https://github.com/ocornut/imgui), or look in the detailed documentation of the C++ source.
+This wrapper houses next to no functionality. As long as it is not a Go-specific issue, help will rather be there.
+
+### Scope
+
+This wrapper exposes minimal functionality of **Dear ImGui**. Ideally, this functionality is that of the common minimum that someone would want. This wrapper does not strife for full configurability, like the original library. This is not even possible in some cases, as it requires compilation flags.
+
+### Extensions
+At the moment, this library is primarily used by **InkyBlackness**. If you can and want to make use of this library in your own projects, you are happy to do so. Pull-requests with extensions are happily accepted, provided that they uphold the following minimum requirements:
+* Code is properly formatted & linted (use [golangci-lint](https://github.com/golangci/golangci-lint) for a full check)
+* Public Go API is documented. Copied documentation from **Dear ImGui** is acceptable and recommended, assuming it is adapted regarding type names. If there is no documentation in the original, try to spend some time figuring it out. In any case, please make the comments readable as complete English sentences, as recommended by Go.
+* API and version philosophies are respected (see README.md)
+
+#### Clarification on API naming and signatures
+
+If an **Dear ImGui** function has the signature of
+
+```
+SomeControl(const char *label, int value, int optArg1 = 0, const char *optArg2 = "stuff");
+```
+
+then the wrapper functions should be
+
+```
+// SomeControl calls SomeControlV(label, value, 0, "stuff"). 
+SomeControl(label string, value int32) {
+    SomeControlV(label, value, 0, "stuff")
+}
+
+// SomeControlV does things (text possibly copied from imgui.h).
+SomeControlV(label string, value int32, optArg1 int32, optArg2 string) {
+    // ...
+}
+```
+
+The "idiomatic" function should have only the required parameters of the underlying function, and its comment specifies all the defaults, matching that of `imgui.h`.
+The "verbose" variant should require all the parameters of the underlying function.
+
+### Code Style
+
+Please make sure code is formatted according to `go fmt`, and use the following linter: [golangci-lint](https://github.com/golangci/golangci-lint).
+
+> If there are linter errors that you didn't introduce, you don't have to clean them up - I might have missed them and will be handling them separately.
+
+### Upgrade to newer Dear ImGui version
+
+An upgrade with _major_ changes in the API should be on purpose and with coordination. Such a change requires a bump of the major version of this wrapper.
+
+Otherwise, try to keep the API of this wrapper stable and keep compatible wrapper functions for changed/upgraded functions.
+  
+On an upgrade of **Dear ImGui**, apart from updating the actual files, be sure to do the following steps:
+* In case `imconfig.h` is changed, be sure to keep the intentional changes: Obsolete functions should not be compiled, and the `iggAssert()` function must survive.
+* Have a look at any extended enumerations. The Go variant will need extension/change as well, otherwise the constants will be wrong.
+* Check for any documentation changes of exported functions. The Go documentation should reflect such changes as well.
+* Run `go test ./...` . There is at least one test that is bound to the version and needs change as well.
+* Update the screenshots of the examples, they show the version number.
+* Update the `README.md` file, it indicates the version number.
+* Check if the license of **Dear ImGui** has changed and update the `_licenses/imgui-LICENSE.txt` file. This may happen every year (copyright year).
+
+#### Handling of removed functions
+
+In order to avoid needing a major version bump of the wrapper just for one removed function, use the following pattern:
+
+```
+// NewFunction does new stuff.
+func NewFunction() {
+}
+
+// OldFunction did something and is now delegating to NewFunction().
+// Deprecated: Use NewFunction instead.  
+func OldFunction() {
+    NewFunction()
+}
+```
+
+The `OldFunction` is implemented using the new API, and is marked as `Deprecated` in the comment.
+IDEs tend to respect this and notify the user.
+
+If, however, a whole set of functionality is replaced, this then probably warrants a major version bump.

+ 43 - 0
vendor/github.com/AllenDang/imgui-go/ColorEditFlags.go

@@ -0,0 +1,43 @@
+package imgui
+
+const (
+	// ColorEditFlagsNone default = 0
+	ColorEditFlagsNone = 0
+	// ColorEditFlagsNoAlpha ignores Alpha component (read 3 components from the input pointer).
+	ColorEditFlagsNoAlpha = 1 << iota
+	// ColorEditFlagsNoPicker disables picker when clicking on colored square.
+	ColorEditFlagsNoPicker
+	// ColorEditFlagsNoOptions disables toggling options menu when right-clicking on inputs/small preview.
+	ColorEditFlagsNoOptions
+	// ColorEditFlagsNoSmallPreview disables colored square preview next to the inputs. (e.g. to show only the inputs)
+	ColorEditFlagsNoSmallPreview
+	// ColorEditFlagsNoInputs disables inputs sliders/text widgets (e.g. to show only the small preview colored square).
+	ColorEditFlagsNoInputs
+	// ColorEditFlagsNoTooltip disables tooltip when hovering the preview.
+	ColorEditFlagsNoTooltip
+	// ColorEditFlagsNoLabel disables display of inline text label (the label is still forwarded to the tooltip and picker).
+	ColorEditFlagsNoLabel
+	// ColorEditFlagsNoDragDrop disables drag and drop target. ColorButton: disable drag and drop source.
+	ColorEditFlagsNoDragDrop
+
+	// User Options (right-click on widget to change some of them). You can set application defaults using SetColorEditOptions(). The idea is that you probably don't want to override them in most of your calls, let the user choose and/or call SetColorEditOptions() during startup.
+
+	// ColorEditFlagsAlphaBar shows vertical alpha bar/gradient in picker.
+	ColorEditFlagsAlphaBar = 1 << 16
+	// ColorEditFlagsAlphaPreview displays preview as a transparent color over a checkerboard, instead of opaque.
+	ColorEditFlagsAlphaPreview = 1 << 17
+	// ColorEditFlagsAlphaPreviewHalf displays half opaque / half checkerboard, instead of opaque.
+	ColorEditFlagsAlphaPreviewHalf = 1 << 18
+	// ColorEditFlagsHDR = (WIP) surrently only disable 0.0f..1.0f limits in RGBA edition (note: you probably want to use ImGuiColorEditFlags_Float flag as well).
+	ColorEditFlagsHDR = 1 << 19
+	// ColorEditFlagsRGB sets the format as RGB
+	ColorEditFlagsRGB = 1 << 20
+	// ColorEditFlagsHSV sets the format as HSV
+	ColorEditFlagsHSV = 1 << 21
+	// ColorEditFlagsHEX sets the format as HEX
+	ColorEditFlagsHEX = 1 << 22
+	// ColorEditFlagsUint8 _display_ values formatted as 0..255.
+	ColorEditFlagsUint8 = 1 << 23
+	// ColorEditFlagsFloat _display_ values formatted as 0.0f..1.0f floats instead of 0..255 integers. No round-trip of value via integers.
+	ColorEditFlagsFloat = 1 << 24
+)

+ 41 - 0
vendor/github.com/AllenDang/imgui-go/ColorPickerFlags.go

@@ -0,0 +1,41 @@
+package imgui
+
+const (
+	// ColorPickerFlagsNone default = 0
+	ColorPickerFlagsNone = 0
+	// ColorPickerFlagsNoAlpha ignoreс Alpha component (read 3 components from the input pointer).
+	ColorPickerFlagsNoAlpha = 1 << iota
+	// ColorPickerFlagsNoSmallPreview disables colored square preview next to the inputs. (e.g. to show only the inputs)
+	ColorPickerFlagsNoSmallPreview = 1 << 4
+	// ColorPickerFlagsNoInputs disables inputs sliders/text widgets (e.g. to show only the small preview colored square).
+	ColorPickerFlagsNoInputs = 1 << 5
+	// ColorPickerFlagsNoTooltip disables tooltip when hovering the preview.
+	ColorPickerFlagsNoTooltip = 1 << 6
+	// ColorPickerFlagsNoLabel disables display of inline text label (the label is still forwarded to the tooltip and picker).
+	ColorPickerFlagsNoLabel = 1 << 7
+	// ColorPickerFlagsNoSidePreview disables bigger color preview on right side of the picker, use small colored square preview instead.
+	ColorPickerFlagsNoSidePreview = 1 << 8
+
+	// User Options (right-click on widget to change some of them). You can set application defaults using SetColorEditOptions(). The idea is that you probably don't want to override them in most of your calls, let the user choose and/or call SetColorPickerOptions() during startup.
+
+	// ColorPickerFlagsAlphaBar shows vertical alpha bar/gradient in picker.
+	ColorPickerFlagsAlphaBar = 1 << 16
+	// ColorPickerFlagsAlphaPreview displays preview as a transparent color over a checkerboard, instead of opaque.
+	ColorPickerFlagsAlphaPreview = 1 << 17
+	// ColorPickerFlagsAlphaPreviewHalf displays half opaque / half checkerboard, instead of opaque.
+	ColorPickerFlagsAlphaPreviewHalf = 1 << 18
+	// ColorPickerFlagsRGB sets the format as RGB
+	ColorPickerFlagsRGB = 1 << 20
+	// ColorPickerFlagsHSV sets the format as HSV
+	ColorPickerFlagsHSV = 1 << 21
+	// ColorPickerFlagsHEX sets the format as HEX
+	ColorPickerFlagsHEX = 1 << 22
+	// ColorPickerFlagsUint8 _display_ values formatted as 0..255.
+	ColorPickerFlagsUint8 = 1 << 23
+	// ColorPickerFlagsFloat _display_ values formatted as 0.0f..1.0f floats instead of 0..255 integers. No round-trip of value via integers.
+	ColorPickerFlagsFloat = 1 << 24
+	// ColorPickerFlagsPickerHueBar bar for Hue, rectangle for Sat/Value.
+	ColorPickerFlagsPickerHueBar = 1 << 25
+	// ColorPickerFlagsPickerHueWheel wheel for Hue, triangle for Sat/Value.
+	ColorPickerFlagsPickerHueWheel = 1 << 26
+)

+ 23 - 0
vendor/github.com/AllenDang/imgui-go/ComboFlags.go

@@ -0,0 +1,23 @@
+package imgui
+
+const (
+	// ComboFlagsNone default = 0
+	ComboFlagsNone = 0
+	// ComboFlagsPopupAlignLeft aligns the popup toward the left by default.
+	ComboFlagsPopupAlignLeft = 1 << 0
+	// ComboFlagsHeightSmall has max ~4 items visible.
+	// Tip: If you want your combo popup to be a specific size you can use SetNextWindowSizeConstraints() prior to calling BeginCombo().
+	ComboFlagsHeightSmall = 1 << 1
+	// ComboFlagsHeightRegular has max ~8 items visible (default).
+	ComboFlagsHeightRegular = 1 << 2
+	// ComboFlagsHeightLarge has max ~20 items visible.
+	ComboFlagsHeightLarge = 1 << 3
+	// ComboFlagsHeightLargest has as many fitting items as possible.
+	ComboFlagsHeightLargest = 1 << 4
+	// ComboFlagsNoArrowButton displays on the preview box without the square arrow button.
+	ComboFlagsNoArrowButton = 1 << 5
+	// ComboFlagsNoPreview displays only a square arrow button.
+	ComboFlagsNoPreview = 1 << 6
+
+	ComboFlagsHeightMask = ComboFlagsHeightSmall | ComboFlagsHeightRegular | ComboFlagsHeightLarge | ComboFlagsHeightLargest
+)

+ 17 - 0
vendor/github.com/AllenDang/imgui-go/Conditions.go

@@ -0,0 +1,17 @@
+package imgui
+
+// Condition for SetWindow***(), SetNextWindow***(), SetNextTreeNode***() functions.
+// Important: Treat as a regular enum! Do NOT combine multiple values using binary operators!
+// All the functions above treat 0 as a shortcut to ConditionAlways.
+type Condition int
+
+const (
+	// ConditionAlways sets the variable.
+	ConditionAlways Condition = 1 << 0
+	// ConditionOnce sets the variable once per runtime session (only the first call with succeed).
+	ConditionOnce = 1 << 1
+	// ConditionFirstUseEver sets the variable if the object/window has no persistently saved data (no entry in .ini file).
+	ConditionFirstUseEver = 1 << 2
+	// ConditionAppearing sets the variable if the object/window is appearing after being hidden/inactive (or the first time).
+	ConditionAppearing = 1 << 3
+)

+ 38 - 0
vendor/github.com/AllenDang/imgui-go/ConfigFlags.go

@@ -0,0 +1,38 @@
+package imgui
+
+const (
+	// ConfigFlagNone default = 0
+	ConfigFlagNone = 0
+	// ConfigFlagNavEnableKeyboard master keyboard navigation enable flag. NewFrame() will automatically fill
+	// io.NavInputs[] based on io.KeysDown[].
+	ConfigFlagNavEnableKeyboard = 1 << 0
+	// ConfigFlagNavEnableGamepad master gamepad navigation enable flag.
+	// This is mostly to instruct your imgui back-end to fill io.NavInputs[]. Back-end also needs to set
+	// BackendFlagHasGamepad.
+	ConfigFlagNavEnableGamepad = 1 << 1
+	// ConfigFlagNavEnableSetMousePos instruct navigation to move the mouse cursor. May be useful on TV/console systems
+	// where moving a virtual mouse is awkward. Will update io.MousePos and set io.WantSetMousePos=true. If enabled you
+	// MUST honor io.WantSetMousePos requests in your binding, otherwise ImGui will react as if the mouse is jumping
+	// around back and forth.
+	ConfigFlagNavEnableSetMousePos = 1 << 2
+	// ConfigFlagNavNoCaptureKeyboard instruct navigation to not set the io.WantCaptureKeyboard flag when io.NavActive
+	// is set.
+	ConfigFlagNavNoCaptureKeyboard = 1 << 3
+	// ConfigFlagNoMouse instruct imgui to clear mouse position/buttons in NewFrame(). This allows ignoring the mouse
+	// information set by the back-end.
+	ConfigFlagNoMouse = 1 << 4
+	// ConfigFlagNoMouseCursorChange instruct back-end to not alter mouse cursor shape and visibility. Use if the
+	// back-end cursor changes are interfering with yours and you don't want to use SetMouseCursor() to change mouse
+	// cursor. You may want to honor requests from imgui by reading GetMouseCursor() yourself instead.
+	ConfigFlagNoMouseCursorChange = 1 << 5
+
+	ConfigFlagEnablePowerSavingMode = 1 << 6
+
+	// User storage (to allow your back-end/engine to communicate to code that may be shared between multiple projects.
+	// Those flags are not used by core Dear ImGui)
+
+	// ConfigFlagIsSRGB application is SRGB-aware.
+	ConfigFlagIsSRGB = 1 << 20
+	// ConfigFlagIsTouchScreen application is using a touch screen instead of a mouse.
+	ConfigFlagIsTouchScreen = 1 << 21
+)

+ 68 - 0
vendor/github.com/AllenDang/imgui-go/Context.go

@@ -0,0 +1,68 @@
+package imgui
+
+import (
+	"errors"
+)
+
+// #include "imguiWrapper.h"
+import "C"
+
+// Context specifies a scope of ImGui.
+//
+// All contexts share a same FontAtlas by default.
+// If you want different font atlas, you can create them and overwrite the CurrentIO.Fonts of an ImGui context.
+type Context struct {
+	handle C.IggContext
+}
+
+// CreateContext produces a new internal state scope.
+// Passing nil for the fontAtlas creates a default font.
+func CreateContext(fontAtlas *FontAtlas) *Context {
+	var fontAtlasPtr C.IggFontAtlas
+	if fontAtlas != nil {
+		fontAtlasPtr = fontAtlas.handle()
+	}
+	return &Context{handle: C.iggCreateContext(fontAtlasPtr)}
+}
+
+func (c *Context) GetHandle() C.IggContext {
+	return c.handle
+}
+
+// ErrNoContext is used when no context is current.
+var ErrNoContext = errors.New("no current context")
+
+// CurrentContext returns the currently active state scope.
+// Returns ErrNoContext if no context is available.
+func CurrentContext() (*Context, error) {
+	raw := C.iggGetCurrentContext()
+	if raw == nil {
+		return nil, ErrNoContext
+	}
+	return &Context{handle: raw}, nil
+}
+
+// Destroy removes the internal state scope.
+// Trying to destroy an already destroyed context does nothing.
+func (context *Context) Destroy() {
+	if context.handle != nil {
+		C.iggDestroyContext(context.handle)
+		context.handle = nil
+	}
+}
+
+// ErrContextDestroyed is returned when trying to use an already destroyed context.
+var ErrContextDestroyed = errors.New("context is destroyed")
+
+// SetCurrent activates this context as the currently active state scope.
+func (context Context) SetCurrent() error {
+	if context.handle == nil {
+		return ErrContextDestroyed
+	}
+	C.iggSetCurrentContext(context.handle)
+	return nil
+}
+
+func SetMaxWaitBeforeNextFrame(time float32) {
+	C.iggSetMaxWaitBeforeNextFrame(C.double(time))
+}

+ 61 - 0
vendor/github.com/AllenDang/imgui-go/DragDrop.go

@@ -0,0 +1,61 @@
+package imgui
+
+// #include "DragDropWrapper.h"
+import "C"
+import (
+	"unsafe"
+)
+
+type Payload uintptr
+
+func (p Payload) handle() C.IggPayload {
+	return C.IggPayload(p)
+}
+
+func (p Payload) Data() int {
+	raw := C.iggPayloadGetData(p.handle())
+	return *(*int)((unsafe.Pointer)(raw))
+}
+
+func BeginDragDropSource() bool {
+	return BeginDragDropSourceV(0)
+}
+
+func BeginDragDropSourceV(flags int) bool {
+	return C.iggBeginDragDropSource(C.int(flags)) != 0
+}
+
+func SetDragDropPayload(payloadType string, data int) bool {
+	return SetDragDropPayloadV(payloadType, data, 0)
+}
+
+func SetDragDropPayloadV(payloadType string, data int, cond int) bool {
+	typeArg, typeFn := wrapString(payloadType)
+	defer typeFn()
+
+	return C.iggSetDragDropPayload(typeArg, unsafe.Pointer(&data), C.uint(unsafe.Sizeof(&data)), C.int(cond)) != 0
+}
+
+func EndDragDropSource() {
+	C.iggEndDragDropSource()
+}
+
+func BeginDragDropTarget() bool {
+	return C.iggBeginDragDropTarget() != 0
+}
+
+func AcceptDragDropPayload(payloadType string) Payload {
+	return AcceptDragDropPayloadV(payloadType, 0)
+}
+
+func AcceptDragDropPayloadV(payloadType string, flags int) Payload {
+	typeArg, typeFn := wrapString(payloadType)
+	defer typeFn()
+
+	payload := C.iggAcceptDragDropPayload(typeArg, C.int(flags))
+	return Payload(payload)
+}
+
+func EndDragDropTarget() {
+	C.iggEndDragDropTarget()
+}

+ 32 - 0
vendor/github.com/AllenDang/imgui-go/DragDropWrapper.cpp

@@ -0,0 +1,32 @@
+#include "imguiWrappedHeader.h"
+#include "DragDropWrapper.h"
+
+void* iggPayloadGetData(IggPayload handle) {
+  ImGuiPayload *payload = reinterpret_cast<ImGuiPayload*>(handle);
+  return payload->Data;
+}
+
+IggBool iggBeginDragDropSource(int flags) {
+  return ImGui::BeginDragDropSource(flags) != 0 ? 1 : 0;
+}
+
+IggBool iggSetDragDropPayload(const char* type, const void* data, unsigned int sz, int cond) {
+  return ImGui::SetDragDropPayload(type, data, sz, cond) != 0 ? 1 : 0;
+}
+
+void iggEndDragDropSource() {
+  ImGui::EndDragDropSource();
+}
+
+IggBool iggBeginDragDropTarget() {
+  return ImGui::BeginDragDropTarget() != 0 ? 1 : 0;
+}
+
+IggPayload iggAcceptDragDropPayload(const char *type, int flags) {
+  const ImGuiPayload *payload = ImGui::AcceptDragDropPayload(type, flags);
+  return static_cast<IggPayload>(const_cast<ImGuiPayload*>(payload));
+}
+
+void iggEndDragDropTarget() {
+  ImGui::EndDragDropTarget();
+}

+ 24 - 0
vendor/github.com/AllenDang/imgui-go/DragDropWrapper.h

@@ -0,0 +1,24 @@
+#pragma once
+
+#include "imguiWrapperTypes.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef void* IggPayload;
+
+extern void* iggPayloadGetData(IggPayload handle);
+
+extern IggBool iggBeginDragDropSource(int flags);
+extern IggBool iggSetDragDropPayload(const char* type, const void* data, unsigned int sz, int cond);
+extern void iggEndDragDropSource();
+extern IggBool iggBeginDragDropTarget();
+extern IggPayload iggAcceptDragDropPayload(const char *type, int flags);
+extern void iggEndDragDropTarget();
+
+
+#ifdef __cplusplus
+}
+#endif

+ 60 - 0
vendor/github.com/AllenDang/imgui-go/DrawCommand.go

@@ -0,0 +1,60 @@
+package imgui
+
+// #include "DrawCommandWrapper.h"
+import "C"
+
+// DrawCommand describes one GPU call (or a callback).
+type DrawCommand uintptr
+
+func (cmd DrawCommand) handle() C.IggDrawCmd {
+	return C.IggDrawCmd(cmd)
+}
+
+func (cmd DrawCommand) IdxOffset() uint {
+	return uint(C.iggDrawCommandIdxOffset(cmd.handle()))
+}
+
+// VertexOffset is the start offset in vertex buffer.
+// ImGuiBackendFlags_RendererHasVtxOffset: false always 0,
+// otherwise may be >0 to support meshes larger than 64K vertices with 16-bit indices.
+func (cmd DrawCommand) VertexOffset() int {
+	var count C.uint
+	C.iggDrawCommandGetVertexOffset(cmd.handle(), &count)
+	return int(count)
+}
+
+// ElementCount is the number of indices (multiple of 3) to be rendered as triangles.
+// Vertices are stored in the callee DrawList's VertexBuffer, indices in IndexBuffer.
+func (cmd DrawCommand) ElementCount() int {
+	var count C.uint
+	C.iggDrawCommandGetElementCount(cmd.handle(), &count)
+	return int(count)
+}
+
+// ClipRect defines the clipping rectangle (x1, y1, x2, y2).
+func (cmd DrawCommand) ClipRect() (rect Vec4) {
+	rectArg, rectFin := rect.wrapped()
+	defer rectFin()
+	C.iggDrawCommandGetClipRect(cmd.handle(), rectArg)
+	return
+}
+
+// TextureID is the user-provided texture ID.
+// Set by user in FontAtlas.SetTextureID() for fonts or passed to Image*() functions.
+// Ignore if never using images or multiple fonts atlas.
+func (cmd DrawCommand) TextureID() TextureID {
+	var id C.IggTextureID
+	C.iggDrawCommandGetTextureID(cmd.handle(), &id)
+	return TextureID(id)
+}
+
+// HasUserCallback returns true if this handle command should be deferred.
+func (cmd DrawCommand) HasUserCallback() bool {
+	return C.iggDrawCommandHasUserCallback(cmd.handle()) != 0
+}
+
+// CallUserCallback calls the user callback instead of rendering the vertices.
+// ClipRect and TextureID will be set normally.
+func (cmd DrawCommand) CallUserCallback(list DrawList) {
+	C.iggDrawCommandCallUserCallback(cmd.handle(), list.handle())
+}

+ 39 - 0
vendor/github.com/AllenDang/imgui-go/DrawCommandWrapper.cpp

@@ -0,0 +1,39 @@
+#include "DrawCommandWrapper.h"
+#include "WrapperConverter.h"
+#include "imguiWrappedHeader.h"
+
+unsigned int iggDrawCommandIdxOffset(IggDrawCmd handle) {
+  ImDrawCmd *cmd = reinterpret_cast<ImDrawCmd *>(handle);
+  return cmd->IdxOffset;
+}
+
+void iggDrawCommandGetVertexOffset(IggDrawCmd handle, unsigned int *count) {
+  ImDrawCmd *cmd = reinterpret_cast<ImDrawCmd *>(handle);
+  *count = cmd->VtxOffset;
+}
+
+void iggDrawCommandGetElementCount(IggDrawCmd handle, unsigned int *count) {
+  ImDrawCmd *cmd = reinterpret_cast<ImDrawCmd *>(handle);
+  *count = cmd->ElemCount;
+}
+
+void iggDrawCommandGetClipRect(IggDrawCmd handle, IggVec4 *rect) {
+  ImDrawCmd *cmd = reinterpret_cast<ImDrawCmd *>(handle);
+  exportValue(*rect, cmd->ClipRect);
+}
+
+void iggDrawCommandGetTextureID(IggDrawCmd handle, IggTextureID *id) {
+  ImDrawCmd *cmd = reinterpret_cast<ImDrawCmd *>(handle);
+  *id = reinterpret_cast<IggTextureID>(cmd->TextureId);
+}
+
+IggBool iggDrawCommandHasUserCallback(IggDrawCmd handle) {
+  ImDrawCmd *cmd = reinterpret_cast<ImDrawCmd *>(handle);
+  return (cmd->UserCallback != 0) ? 1 : 0;
+}
+
+void iggDrawCommandCallUserCallback(IggDrawCmd handle, IggDrawList listHandle) {
+  ImDrawCmd *cmd = reinterpret_cast<ImDrawCmd *>(handle);
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(listHandle);
+  cmd->UserCallback(list, cmd);
+}

+ 19 - 0
vendor/github.com/AllenDang/imgui-go/DrawCommandWrapper.h

@@ -0,0 +1,19 @@
+#pragma once
+
+#include "imguiWrapperTypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern unsigned int iggDrawCommandIdxOffset(IggDrawCmd handle);
+extern void iggDrawCommandGetVertexOffset(IggDrawCmd handle, unsigned int *count);
+extern void iggDrawCommandGetElementCount(IggDrawCmd handle, unsigned int *count);
+extern void iggDrawCommandGetClipRect(IggDrawCmd handle, IggVec4 *rect);
+extern void iggDrawCommandGetTextureID(IggDrawCmd handle, IggTextureID *id);
+extern IggBool iggDrawCommandHasUserCallback(IggDrawCmd handle);
+extern void iggDrawCommandCallUserCallback(IggDrawCmd handle, IggDrawList listHandle);
+
+#ifdef __cplusplus
+}
+#endif

+ 42 - 0
vendor/github.com/AllenDang/imgui-go/DrawData.go

@@ -0,0 +1,42 @@
+package imgui
+
+// #include "DrawDataWrapper.h"
+import "C"
+import "unsafe"
+
+// DrawData contains all draw data to render an ImGui frame.
+type DrawData uintptr
+
+func (data DrawData) handle() C.IggDrawData {
+	return C.IggDrawData(data)
+}
+
+// Valid indicates whether the structure is usable.
+// It is valid only after Render() is called and before the next NewFrame() is called.
+func (data DrawData) Valid() bool {
+	return (data.handle() != nil) && (C.iggDrawDataValid(data.handle()) != 0)
+}
+
+// CommandLists is an array of DrawList to render.
+// The DrawList are owned by the context and only pointed to from here.
+func (data DrawData) CommandLists() []DrawList {
+	var handles unsafe.Pointer
+	var count C.int
+
+	C.iggDrawDataGetCommandLists(data.handle(), &handles, &count)
+	list := make([]DrawList, int(count))
+	for i := 0; i < int(count); i++ {
+		list[i] = DrawList(*((*uintptr)(handles)))
+		handles = unsafe.Pointer(uintptr(handles) + unsafe.Sizeof(handles)) // nolint: gas
+	}
+
+	return list
+}
+
+// ScaleClipRects is a helper to scale the ClipRect field of each DrawCmd.
+// Use if your final output buffer is at a different scale than ImGui expects,
+// or if there is a difference between your window resolution and framebuffer resolution.
+func (data DrawData) ScaleClipRects(scale Vec2) {
+	scaleArg, _ := scale.wrapped()
+	C.iggDrawDataScaleClipRects(data.handle(), scaleArg)
+}

+ 25 - 0
vendor/github.com/AllenDang/imgui-go/DrawDataWrapper.cpp

@@ -0,0 +1,25 @@
+#include "imguiWrappedHeader.h"
+#include "DrawDataWrapper.h"
+#include "WrapperConverter.h"
+
+IggBool iggDrawDataValid(IggDrawData handle)
+{
+   ImDrawData *drawData = reinterpret_cast<ImDrawData *>(handle);
+   IggBool result = 0;
+   exportValue(result, drawData->Valid);
+   return result;
+}
+
+void iggDrawDataGetCommandLists(IggDrawData handle, void **handles, int *count)
+{
+   ImDrawData *drawData = reinterpret_cast<ImDrawData *>(handle);
+   *handles = reinterpret_cast<void **>(drawData->CmdLists);
+   *count = drawData->CmdListsCount;
+}
+
+void iggDrawDataScaleClipRects(IggDrawData handle, IggVec2 const *scale)
+{
+   ImDrawData *drawData = reinterpret_cast<ImDrawData *>(handle);
+   Vec2Wrapper wrappedScale(scale);
+   drawData->ScaleClipRects(*wrappedScale);
+}

+ 16 - 0
vendor/github.com/AllenDang/imgui-go/DrawDataWrapper.h

@@ -0,0 +1,16 @@
+#pragma once
+
+#include "imguiWrapperTypes.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+extern IggBool iggDrawDataValid(IggDrawData handle);
+extern void iggDrawDataGetCommandLists(IggDrawData handle, void **handles, int *count);
+extern void iggDrawDataScaleClipRects(IggDrawData handle, IggVec2 const *scale);
+
+#ifdef __cplusplus
+}
+#endif

+ 226 - 0
vendor/github.com/AllenDang/imgui-go/DrawList.go

@@ -0,0 +1,226 @@
+package imgui
+
+// #include "DrawListWrapper.h"
+import "C"
+import (
+	"unsafe"
+)
+
+// DrawList is a draw-command list.
+// This is the low-level list of polygons that ImGui functions are filling.
+// At the end of the frame, all command lists are passed to your render function for rendering.
+//
+// Each ImGui window contains its own DrawList. You can use GetWindowDrawList() to access
+// the current window draw list and draw custom primitives.
+//
+// You can interleave normal ImGui calls and adding primitives to the current draw list.
+//
+// All positions are generally in pixel coordinates (top-left at (0,0), bottom-right at io.DisplaySize),
+// however you are totally free to apply whatever transformation matrix to want to the data
+// (if you apply such transformation you'll want to apply it to ClipRect as well)
+//
+// Important: Primitives are always added to the list and not culled (culling is done at
+// higher-level by ImGui functions), if you use this API a lot consider coarse culling your drawn objects.
+type DrawList uintptr
+
+func (list DrawList) handle() C.IggDrawList {
+	return C.IggDrawList(list)
+}
+
+// Commands returns the list of draw commands.
+// Typically 1 command = 1 GPU draw call, unless the command is a callback.
+func (list DrawList) Commands() []DrawCommand {
+	count := int(C.iggDrawListGetCommandCount(list.handle()))
+	commands := make([]DrawCommand, count)
+	for i := 0; i < count; i++ {
+		commands[i] = DrawCommand(C.iggDrawListGetCommand(list.handle(), C.int(i)))
+	}
+	return commands
+}
+
+// VertexBufferLayout returns the byte sizes necessary to select fields in a vertex buffer of a DrawList.
+func VertexBufferLayout() (entrySize int, posOffset int, uvOffset int, colOffset int) {
+	var entrySizeArg C.size_t
+	var posOffsetArg C.size_t
+	var uvOffsetArg C.size_t
+	var colOffsetArg C.size_t
+	C.iggGetVertexBufferLayout(&entrySizeArg, &posOffsetArg, &uvOffsetArg, &colOffsetArg)
+	entrySize = int(entrySizeArg)
+	posOffset = int(posOffsetArg)
+	uvOffset = int(uvOffsetArg)
+	colOffset = int(colOffsetArg)
+	return
+}
+
+// VertexBuffer returns the handle information of the whole vertex buffer.
+// Returned are the handle pointer and the total byte size.
+// The buffer is a packed array of vertex entries, each consisting of a 2D position vector, a 2D UV vector,
+// and a 4-byte color value. To determine the byte size and offset values, call VertexBufferLayout.
+func (list DrawList) VertexBuffer() (unsafe.Pointer, int) {
+	var data unsafe.Pointer
+	var size C.int
+
+	C.iggDrawListGetRawVertexBuffer(list.handle(), &data, &size)
+
+	return data, int(size)
+}
+
+// IndexBufferLayout returns the byte size necessary to select fields in an index buffer of DrawList.
+func IndexBufferLayout() (entrySize int) {
+	var entrySizeArg C.size_t
+	C.iggGetIndexBufferLayout(&entrySizeArg)
+	entrySize = int(entrySizeArg)
+	return
+}
+
+// IndexBuffer returns the handle information of the whole index buffer.
+// Returned are the handle pointer and the total byte size.
+// The buffer is a packed array of index entries, each consisting of an integer offset.
+// To determine the byte size, call IndexBufferLayout.
+func (list DrawList) IndexBuffer() (unsafe.Pointer, int) {
+	var data unsafe.Pointer
+	var size C.int
+
+	C.iggDrawListGetRawIndexBuffer(list.handle(), &data, &size)
+
+	return data, int(size)
+}
+
+func (list DrawList) AddLine(p1, p2 Vec2, col Vec4, thickness float32) {
+	c := GetColorU32(col)
+	p1Arg, _ := p1.wrapped()
+	p2Arg, _ := p2.wrapped()
+	C.iggDrawListAddLine(list.handle(), p1Arg, p2Arg, C.uint(c), C.float(thickness))
+}
+
+func (list DrawList) AddRect(pMin, pMax Vec2, col Vec4, rounding float32, rounding_corners int, thickness float32) {
+	c := GetColorU32(col)
+	pMinArg, _ := pMin.wrapped()
+	pMaxArg, _ := pMax.wrapped()
+	C.iggDrawListAddRect(list.handle(), pMinArg, pMaxArg, C.uint(c), C.float(rounding), C.int(rounding_corners), C.float(thickness))
+}
+
+func (list DrawList) AddRectFilled(pMin, pMax Vec2, col Vec4, rounding float32, rounding_corners int) {
+	c := GetColorU32(col)
+	pMinArg, _ := pMin.wrapped()
+	pMaxArg, _ := pMax.wrapped()
+	C.iggDrawListAddRectFilled(list.handle(), pMinArg, pMaxArg, C.uint(c), C.float(rounding), C.int(rounding_corners))
+}
+
+func (list DrawList) AddText(pos Vec2, col Vec4, text string) {
+	c := GetColorU32(col)
+	posArg, _ := pos.wrapped()
+	textArg, textFin := wrapString(text)
+	defer textFin()
+	C.iggDrawListAddText(list.handle(), posArg, C.uint(c), textArg)
+}
+
+func (list DrawList) AddBezierCubic(pos0, cp0, cp1, pos1 Vec2, col Vec4, thickness float32, num_segments int) {
+	c := GetColorU32(col)
+	pos0Arg, _ := pos0.wrapped()
+	cp0Arg, _ := cp0.wrapped()
+	cp1Arg, _ := cp1.wrapped()
+	pos1Arg, _ := pos1.wrapped()
+	C.iggDrawListAddBezierCubic(list.handle(), pos0Arg, cp0Arg, cp1Arg, pos1Arg, C.uint(c), C.float(thickness), C.int(num_segments))
+}
+
+func (list DrawList) AddTriangle(p1, p2, p3 Vec2, col Vec4, thickness float32) {
+	c := GetColorU32(col)
+	p1Arg, _ := p1.wrapped()
+	p2Arg, _ := p2.wrapped()
+	p3Arg, _ := p3.wrapped()
+	C.iggDrawListAddTriangle(list.handle(), p1Arg, p2Arg, p3Arg, C.uint(c), C.float(thickness))
+}
+
+func (list DrawList) AddTriangleFilled(p1, p2, p3 Vec2, col Vec4) {
+	c := GetColorU32(col)
+	p1Arg, _ := p1.wrapped()
+	p2Arg, _ := p2.wrapped()
+	p3Arg, _ := p3.wrapped()
+	C.iggDrawListAddTriangleFilled(list.handle(), p1Arg, p2Arg, p3Arg, C.uint(c))
+}
+
+func (list DrawList) AddCircle(center Vec2, radius float32, col Vec4, segments int, thickness float32) {
+	c := GetColorU32(col)
+	centerArg, _ := center.wrapped()
+	C.iggDrawListAddCircle(list.handle(), centerArg, C.float(radius), C.uint(c), C.int(segments), C.float(thickness))
+}
+
+func (list DrawList) AddCircleFilled(center Vec2, radius float32, col Vec4) {
+	c := GetColorU32(col)
+	centerArg, _ := center.wrapped()
+	C.iggDrawListAddCircleFilled(list.handle(), centerArg, C.float(radius), C.uint(c), 0)
+}
+
+func (list DrawList) AddQuad(p1, p2, p3, p4 Vec2, col Vec4, thickness float32) {
+	c := GetColorU32(col)
+	p1Arg, _ := p1.wrapped()
+	p2Arg, _ := p2.wrapped()
+	p3Arg, _ := p3.wrapped()
+	p4Arg, _ := p4.wrapped()
+	C.iggDrawListAddQuad(list.handle(), p1Arg, p2Arg, p3Arg, p4Arg, C.uint(c), C.float(thickness))
+}
+
+func (list DrawList) AddQuadFilled(p1, p2, p3, p4 Vec2, col Vec4) {
+	c := GetColorU32(col)
+	p1Arg, _ := p1.wrapped()
+	p2Arg, _ := p2.wrapped()
+	p3Arg, _ := p3.wrapped()
+	p4Arg, _ := p4.wrapped()
+	C.iggDrawListAddQuadFilled(list.handle(), p1Arg, p2Arg, p3Arg, p4Arg, C.uint(c))
+}
+
+// Stateful path API, add points then finish with PathFillConvex() or PathStroke()
+func (list DrawList) PathClear() {
+	C.iggDrawListPathClear(list.handle())
+}
+
+func (list DrawList) PathLineTo(pos Vec2) {
+	posArg, _ := pos.wrapped()
+	C.iggDrawListPathLineTo(list.handle(), posArg)
+}
+
+func (list DrawList) PathLineToMergeDuplicate(pos Vec2) {
+	posArg, _ := pos.wrapped()
+	C.iggDrawListPathLineToMergeDuplicate(list.handle(), posArg)
+}
+
+func (list DrawList) PathFillConvex(col Vec4) {
+	C.iggDrawListPathFillConvex(list.handle(), C.uint(GetColorU32(col)))
+}
+
+func (list DrawList) PathStroke(col Vec4, closed bool, thickness float32) {
+	C.iggDrawListPathStroke(list.handle(), C.uint(GetColorU32(col)), castBool(closed), C.float(thickness))
+}
+
+func (list DrawList) PathArcTo(center Vec2, radius, a_min, a_max float32, num_segments int) {
+	centerArg, _ := center.wrapped()
+	C.iggDrawListPathArcTo(list.handle(), centerArg, C.float(radius), C.float(a_min), C.float(a_max), C.int(num_segments))
+}
+
+func (list DrawList) PathArcToFast(center Vec2, radius float32, a_min_of_12, a_max_of_12 int) {
+	centerArg, _ := center.wrapped()
+	C.iggDrawListPathArcToFast(list.handle(), centerArg, C.float(radius), C.int(a_min_of_12), C.int(a_max_of_12))
+}
+
+func (list DrawList) PathBezierCubicCurveTo(p1, p2, p3 Vec2, num_segments int) {
+	p1Arg, _ := p1.wrapped()
+	p2Arg, _ := p2.wrapped()
+	p3Arg, _ := p3.wrapped()
+	C.iggDrawListPathBezierCubicCurveTo(list.handle(), p1Arg, p2Arg, p3Arg, C.int(num_segments))
+}
+
+func (list DrawList) AddImage(textureId TextureID, pMin, pMax Vec2) {
+	pMinArg, _ := pMin.wrapped()
+	pMaxArg, _ := pMax.wrapped()
+	C.iggDrawListAddImage(list.handle(), C.IggTextureID(textureId), pMinArg, pMaxArg)
+}
+
+func (list DrawList) AddImageV(textureId TextureID, pMin, pMax Vec2, uvMin, uvMax Vec2, col Vec4) {
+	c := GetColorU32(col)
+	pMinArg, _ := pMin.wrapped()
+	pMaxArg, _ := pMax.wrapped()
+	uvMinArg, _ := uvMin.wrapped()
+	uvMaxArg, _ := uvMax.wrapped()
+	C.iggDrawListAddImageV(list.handle(), C.IggTextureID(textureId), pMinArg, pMaxArg, uvMinArg, uvMaxArg, C.uint(c))
+}

+ 206 - 0
vendor/github.com/AllenDang/imgui-go/DrawListWrapper.cpp

@@ -0,0 +1,206 @@
+#include "imguiWrappedHeader.h"
+#include "DrawListWrapper.h"
+#include "WrapperConverter.h"
+
+int iggDrawListGetCommandCount(IggDrawList handle) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  return list->CmdBuffer.Size;
+}
+
+IggDrawCmd iggDrawListGetCommand(IggDrawList handle, int index) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  return reinterpret_cast<IggDrawCmd>(&list->CmdBuffer.Data[index]);
+}
+
+void iggDrawListGetRawIndexBuffer(IggDrawList handle, void **data,
+                                  int *byteSize) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  *data = list->IdxBuffer.Data;
+  *byteSize = static_cast<int>(sizeof(ImDrawIdx)) * list->IdxBuffer.Size;
+}
+
+void iggDrawListGetRawVertexBuffer(IggDrawList handle, void **data,
+                                   int *byteSize) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  *data = list->VtxBuffer.Data;
+  *byteSize = static_cast<int>(sizeof(ImDrawVert)) * list->VtxBuffer.Size;
+}
+
+void iggGetIndexBufferLayout(size_t *entrySize) {
+  *entrySize = sizeof(ImDrawIdx);
+}
+
+void iggGetVertexBufferLayout(size_t *entrySize, size_t *posOffset,
+                              size_t *uvOffset, size_t *colOffset) {
+  *entrySize = sizeof(ImDrawVert);
+  *posOffset = IM_OFFSETOF(ImDrawVert, pos);
+  *uvOffset = IM_OFFSETOF(ImDrawVert, uv);
+  *colOffset = IM_OFFSETOF(ImDrawVert, col);
+}
+
+void iggDrawListAddLine(IggDrawList handle, IggVec2 *p1, IggVec2 *p2,
+                        unsigned int col, float thickness) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper p1Arg(p1);
+  Vec2Wrapper p2Arg(p2);
+  list->AddLine(*p1Arg, *p2Arg, col, thickness);
+}
+
+void iggDrawListAddRect(IggDrawList handle, IggVec2 *p_min, IggVec2 *p_max,
+                        unsigned int col, float rounding, int rounding_corners,
+                        float thickness) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper p1Arg(p_min);
+  Vec2Wrapper p2Arg(p_max);
+  list->AddRect(*p1Arg, *p2Arg, col, rounding, rounding_corners, thickness);
+}
+
+void iggDrawListAddRectFilled(IggDrawList handle, IggVec2 *p_min,
+                              IggVec2 *p_max, unsigned int col, float rounding,
+                              int rounding_corners) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper p1Arg(p_min);
+  Vec2Wrapper p2Arg(p_max);
+  list->AddRectFilled(*p1Arg, *p2Arg, col, rounding, rounding_corners);
+}
+
+void iggDrawListAddText(IggDrawList handle, IggVec2 *pos, unsigned int col,
+                        const char *text) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper posArg(pos);
+  list->AddText(*posArg, col, text);
+}
+
+void iggDrawListAddBezierCubic(IggDrawList handle, IggVec2 *pos0, IggVec2 *cp0,
+                               IggVec2 *cp1, IggVec2 *pos1, unsigned int col,
+                               float thickness, int num_segments) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper pos0Arg(pos0);
+  Vec2Wrapper pos1Arg(pos1);
+  Vec2Wrapper cp0Arg(cp0);
+  Vec2Wrapper cp1Arg(cp1);
+  list->AddBezierCubic(*pos0Arg, *cp0Arg, *cp1Arg, *pos1Arg, col, thickness,
+                       num_segments);
+}
+
+void iggDrawListAddTriangle(IggDrawList handle, IggVec2 *p1, IggVec2 *p2,
+                            IggVec2 *p3, unsigned int col, float thickness) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper p1Arg(p1);
+  Vec2Wrapper p2Arg(p2);
+  Vec2Wrapper p3Arg(p3);
+  list->AddTriangle(*p1Arg, *p2Arg, *p3Arg, col, thickness);
+}
+
+void iggDrawListAddTriangleFilled(IggDrawList handle, IggVec2 *p1, IggVec2 *p2,
+                                  IggVec2 *p3, unsigned int col) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper p1Arg(p1);
+  Vec2Wrapper p2Arg(p2);
+  Vec2Wrapper p3Arg(p3);
+  list->AddTriangleFilled(*p1Arg, *p2Arg, *p3Arg, col);
+}
+
+void iggDrawListAddCircle(IggDrawList handle, IggVec2 *center, float radius,
+                          unsigned int col, int num_segments, float thickness) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper centerArg(center);
+  list->AddCircle(*centerArg, radius, col, num_segments, thickness);
+}
+
+void iggDrawListAddCircleFilled(IggDrawList handle, IggVec2 *center,
+                                float radius, unsigned int col,
+                                int num_segments) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper centerArg(center);
+  list->AddCircleFilled(*centerArg, radius, col, num_segments);
+}
+
+void iggDrawListAddQuad(IggDrawList handle, IggVec2 *p1, IggVec2 *p2,
+                        IggVec2 *p3, IggVec2 *p4, unsigned int col,
+                        float thickness) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper p1Arg(p1);
+  Vec2Wrapper p2Arg(p2);
+  Vec2Wrapper p3Arg(p3);
+  Vec2Wrapper p4Arg(p4);
+  list->AddQuad(*p1Arg, *p2Arg, *p3Arg, *p4Arg, col, thickness);
+}
+
+void iggDrawListAddQuadFilled(IggDrawList handle, IggVec2 *p1, IggVec2 *p2,
+                              IggVec2 *p3, IggVec2 *p4, unsigned int col) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper p1Arg(p1);
+  Vec2Wrapper p2Arg(p2);
+  Vec2Wrapper p3Arg(p3);
+  Vec2Wrapper p4Arg(p4);
+  list->AddQuadFilled(*p1Arg, *p2Arg, *p3Arg, *p4Arg, col);
+}
+
+void iggDrawListPathClear(IggDrawList handle) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  list->PathClear();
+}
+
+void iggDrawListPathLineTo(IggDrawList handle, IggVec2 *pos) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper posArg(pos);
+  list->PathLineTo(*posArg);
+}
+
+void iggDrawListPathLineToMergeDuplicate(IggDrawList handle, IggVec2 *pos) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper posArg(pos);
+  list->PathLineToMergeDuplicate(*posArg);
+}
+
+void iggDrawListPathFillConvex(IggDrawList handle, unsigned int col) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  list->PathFillConvex(col);
+}
+
+void iggDrawListPathStroke(IggDrawList handle, unsigned int col, IggBool closed,
+                           float thickness) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  list->PathStroke(col, closed != 0, thickness);
+}
+
+void iggDrawListPathArcTo(IggDrawList handle, IggVec2 *center, float radius,
+                          float a_min, float a_max, int num_segments) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper centerArg(center);
+  list->PathArcTo(*centerArg, radius, a_min, a_max, num_segments);
+}
+
+void iggDrawListPathArcToFast(IggDrawList handle, IggVec2 *center, float radius,
+                              int a_min_of_12, int a_max_of_12) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper centerArg(center);
+  list->PathArcToFast(*centerArg, radius, a_min_of_12, a_max_of_12);
+}
+
+void iggDrawListPathBezierCubicCurveTo(IggDrawList handle, IggVec2 *p1, IggVec2 *p2,
+                                  IggVec2 *p3, int num_segments) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper p1Arg(p1);
+  Vec2Wrapper p2Arg(p2);
+  Vec2Wrapper p3Arg(p3);
+  list->PathBezierCubicCurveTo(*p1Arg, *p2Arg, *p3Arg, num_segments);
+}
+
+void iggDrawListAddImage(IggDrawList handle, IggTextureID id, IggVec2 *p_min,
+                         IggVec2 *p_max) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper pMinArg(p_min);
+  Vec2Wrapper pMaxArg(p_max);
+  list->AddImage(ImTextureID(id), *pMinArg, *pMaxArg);
+}
+void iggDrawListAddImageV(IggDrawList handle, IggTextureID id, IggVec2 *p_min,
+                         IggVec2 *p_max, IggVec2 *uv_min, IggVec2 *uv_max, unsigned int color) {
+  ImDrawList *list = reinterpret_cast<ImDrawList *>(handle);
+  Vec2Wrapper pMinArg(p_min);
+  Vec2Wrapper pMaxArg(p_max);
+  Vec2Wrapper uvMinArg(uv_min);
+  Vec2Wrapper uvMaxArg(uv_max);
+  list->AddImage(ImTextureID(id), *pMinArg, *pMaxArg, *uvMinArg, *uvMaxArg, color);
+}

+ 78 - 0
vendor/github.com/AllenDang/imgui-go/DrawListWrapper.h

@@ -0,0 +1,78 @@
+#pragma once
+
+#include "imguiWrapperTypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int iggDrawListGetCommandCount(IggDrawList handle);
+extern IggDrawCmd iggDrawListGetCommand(IggDrawList handle, int index);
+extern void iggDrawListGetRawIndexBuffer(IggDrawList handle, void **data,
+                                         int *byteSize);
+extern void iggDrawListGetRawVertexBuffer(IggDrawList handle, void **data,
+                                          int *byteSize);
+
+extern void iggGetIndexBufferLayout(size_t *entrySize);
+extern void iggGetVertexBufferLayout(size_t *entrySize, size_t *posOffset,
+                                     size_t *uvOffset, size_t *colOffset);
+
+extern void iggDrawListAddLine(IggDrawList handle, IggVec2 *p1, IggVec2 *p2,
+                               unsigned int col, float thickness);
+extern void iggDrawListAddRect(IggDrawList handle, IggVec2 *p_min,
+                               IggVec2 *p_max, unsigned int col, float rounding,
+                               int rounding_corners, float thickness);
+extern void iggDrawListAddRectFilled(IggDrawList handle, IggVec2 *p_min,
+                                     IggVec2 *p_max, unsigned int col,
+                                     float rounding, int rounding_corners);
+extern void iggDrawListAddText(IggDrawList handle, IggVec2 *pos,
+                               unsigned int col, const char *text);
+extern void iggDrawListAddBezierCubic(IggDrawList handle, IggVec2 *pos0,
+                                      IggVec2 *cp0, IggVec2 *cp1, IggVec2 *pos1,
+                                      unsigned int col, float thickness,
+                                      int num_segments);
+extern void iggDrawListAddTriangle(IggDrawList handle, IggVec2 *p1, IggVec2 *p2,
+                                   IggVec2 *p3, unsigned int col,
+                                   float thickness);
+extern void iggDrawListAddTriangleFilled(IggDrawList handle, IggVec2 *p1,
+                                         IggVec2 *p2, IggVec2 *p3,
+                                         unsigned int col);
+extern void iggDrawListAddCircle(IggDrawList handle, IggVec2 *center,
+                                 float radius, unsigned int col,
+                                 int num_segments, float thickness);
+extern void iggDrawListAddCircleFilled(IggDrawList handle, IggVec2 *center,
+                                       float radius, unsigned int col,
+                                       int num_segments);
+extern void iggDrawListAddQuad(IggDrawList handle, IggVec2 *p1, IggVec2 *p2,
+                               IggVec2 *p3, IggVec2 *p4, unsigned int col,
+                               float thickness);
+extern void iggDrawListAddQuadFilled(IggDrawList handle, IggVec2 *p1,
+                                     IggVec2 *p2, IggVec2 *p3, IggVec2 *p4,
+                                     unsigned int col);
+
+extern void iggDrawListPathClear(IggDrawList handle);
+extern void iggDrawListPathLineTo(IggDrawList handle, IggVec2 *pos);
+extern void iggDrawListPathLineToMergeDuplicate(IggDrawList handle,
+                                                IggVec2 *pos);
+extern void iggDrawListPathFillConvex(IggDrawList handle, unsigned int col);
+extern void iggDrawListPathStroke(IggDrawList handle, unsigned int col,
+                                  IggBool closed, float thickness);
+extern void iggDrawListPathArcTo(IggDrawList handle, IggVec2 *center,
+                                 float radius, float a_min, float a_max,
+                                 int num_segments);
+extern void iggDrawListPathArcToFast(IggDrawList handle, IggVec2 *center,
+                                     float radius, int a_min_of_12,
+                                     int a_max_of_12);
+extern void iggDrawListPathBezierCubicCurveTo(IggDrawList handle, IggVec2 *p1,
+                                         IggVec2 *p2, IggVec2 *p3,
+                                         int num_segments);
+extern void iggDrawListAddImage(IggDrawList handle, IggTextureID id,
+                                IggVec2 *p_min, IggVec2 *p_max);
+extern void iggDrawListAddImageV(IggDrawList handle, IggTextureID id,
+                                IggVec2 *p_min, IggVec2 *p_max,
+                                IggVec2 *uv_min, IggVec2 *uv_max,
+                                unsigned int color);
+
+#ifdef __cplusplus
+}
+#endif

+ 13 - 0
vendor/github.com/AllenDang/imgui-go/FocusFlags.go

@@ -0,0 +1,13 @@
+package imgui
+
+type GocusedFlags int
+
+const (
+	FocusedFlagsNone             = 0
+	FocusedFlagsChildWindows     = 1 << 0 // Return true if any children of the window is focused
+	FocusedFlagsRootWindow       = 1 << 1 // Test from root window (top most parent of the current hierarchy)
+	FocusedFlagsAnyWindow        = 1 << 2 // Return true if any window is focused. Important: If you are trying to tell how to dispatch your low-level inputs, do NOT use this. Use 'io.WantCaptureMouse' instead! Please read the FAQ!
+	FocusedFlagsNoPopupHierarchy = 1 << 3 // Do not consider popup hierarchy (do not treat popup emitter as parent of popup) (when used with ChildWindows or RootWindow)
+	//FocusedFlagsDockHierarchy               = 1 << 4   // Consider docking hierarchy (treat dockspace host as parent of docked window) (when used with ChildWindows or RootWindow)
+	FocusedFlagsRootAndChildWindows = FocusedFlagsRootWindow | FocusedFlagsChildWindows
+)

+ 19 - 0
vendor/github.com/AllenDang/imgui-go/Font.go

@@ -0,0 +1,19 @@
+package imgui
+
+// #include "FontWrapper.h"
+import "C"
+
+// Font describes one loaded font in an atlas.
+type Font uintptr
+
+// DefaultFont can be used to refer to the default font of the current font atlas without
+// having the actual font reference.
+const DefaultFont Font = 0
+
+func (font Font) handle() C.IggFont {
+	return C.IggFont(font)
+}
+
+func (font Font) FindGlyph(c rune) C.IggFontGlyph {
+	return C.iggFontFindGlyph(font.handle(), C.uint(c))
+}

+ 193 - 0
vendor/github.com/AllenDang/imgui-go/FontAtlas.go

@@ -0,0 +1,193 @@
+package imgui
+
+// #include "FontAtlasWrapper.h"
+import "C"
+import "unsafe"
+
+// Alpha8Image represents a imgui backed 8-bit alpha value image.
+type Alpha8Image struct {
+	Width, Height int
+	Pixels        unsafe.Pointer
+}
+
+// RGBA32Image represents a imgui backed 32-bit RGBA (8 bits per channel) value image.
+type RGBA32Image struct {
+	Width, Height int
+	Pixels        unsafe.Pointer
+}
+
+// FontAtlas contains runtime data for multiple fonts,
+// bake multiple fonts into a single texture, TTF/OTF font loader
+type FontAtlas uintptr
+
+func (atlas FontAtlas) handle() C.IggFontAtlas {
+	return C.IggFontAtlas(atlas)
+}
+
+func GlyphRangesAll() GlyphRanges {
+	return GlyphRanges(C.iggGetGlyphRangesAll())
+}
+
+// GlyphRangesDefault describes Basic Latin, Extended Latin.
+func (atlas FontAtlas) GlyphRangesDefault() GlyphRanges {
+	return GlyphRanges(C.iggGetGlyphRangesDefault(atlas.handle()))
+}
+
+// GlyphRangesKorean describes Default + Korean characters.
+func (atlas FontAtlas) GlyphRangesKorean() GlyphRanges {
+	return GlyphRanges(C.iggGetGlyphRangesKorean(atlas.handle()))
+}
+
+// GlyphRangesJapanese describes Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs.
+func (atlas FontAtlas) GlyphRangesJapanese() GlyphRanges {
+	return GlyphRanges(C.iggGetGlyphRangesJapanese(atlas.handle()))
+}
+
+// GlyphRangesChineseFull describes Default + Half-Width + Japanese Hiragana/Katakana + full set of about 21000 CJK
+// Unified Ideographs.
+func (atlas FontAtlas) GlyphRangesChineseFull() GlyphRanges {
+	return GlyphRanges(C.iggGetGlyphRangesChineseFull(atlas.handle()))
+}
+
+// GlyphRangesChineseSimplifiedCommon describes Default + Half-Width + Japanese Hiragana/Katakana + set of 2500 CJK
+// Unified Ideographs for common simplified Chinese.
+func (atlas FontAtlas) GlyphRangesChineseSimplifiedCommon() GlyphRanges {
+	return GlyphRanges(C.iggGetGlyphRangesChineseSimplifiedCommon(atlas.handle()))
+}
+
+// GlyphRangesCyrillic describes Default + about 400 Cyrillic characters.
+func (atlas FontAtlas) GlyphRangesCyrillic() GlyphRanges {
+	return GlyphRanges(C.iggGetGlyphRangesCyrillic(atlas.handle()))
+}
+
+// GlyphRangesThai describes Default + Thai characters.
+func (atlas FontAtlas) GlyphRangesThai() GlyphRanges {
+	return GlyphRanges(C.iggGetGlyphRangesThai(atlas.handle()))
+}
+
+// AddFontDefault adds the default font to the atlas. This is done by default if you do not call any
+// of the AddFont* methods before retrieving the texture data.
+func (atlas FontAtlas) AddFontDefault() Font {
+	fontHandle := C.iggAddFontDefault(atlas.handle())
+	return Font(fontHandle)
+}
+
+// AddFontDefaultV adds the default font to the atlas using the specified FontConfig.
+func (atlas FontAtlas) AddFontDefaultV(cfg FontConfig) Font {
+	fontHandle := C.iggAddFontDefaultV(atlas.handle(), cfg.handle())
+	return Font(fontHandle)
+}
+
+// AddFontFromFileTTFV attempts to load a font from given TTF file.
+func (atlas FontAtlas) AddFontFromFileTTFV(filename string, sizePixels float32,
+	config FontConfig, glyphRange GlyphRanges) Font {
+	filenameArg, filenameFin := wrapString(filename)
+	defer filenameFin()
+
+	fontHandle := C.iggAddFontFromFileTTF(atlas.handle(), filenameArg, C.float(sizePixels),
+		config.handle(), glyphRange.handle())
+	return Font(fontHandle)
+}
+
+// AddFontFromFileTTF calls AddFontFromFileTTFV(filename, sizePixels, DefaultFontConfig, EmptyGlyphRanges).
+func (atlas FontAtlas) AddFontFromFileTTF(filename string, sizePixels float32) Font {
+	return atlas.AddFontFromFileTTFV(filename, sizePixels, DefaultFontConfig, EmptyGlyphRanges)
+}
+
+// AddFontFromMemoryTTFV attempts to load a font from given TTF byte array.
+func (atlas FontAtlas) AddFontFromMemoryTTFV(
+	fontData []byte, sizePixels float32,
+	config FontConfig,
+	glyphRange GlyphRanges,
+) Font {
+	// NOTE: We never free the fontDataC array because IMGUI's AddFontFromMemoryTTF takes ownership if
+	// FontConfig.FontDataOwnedByAtlas == true (which it is by default). We do not expose this flag in Go
+	// so we can assume in most cases it is true.
+	if !config.getFontDataOwnedByAtlas() {
+		panic("Only ImFontConfig.FontDataOwnedByAtlas == true is supported.")
+	}
+
+	fontDataC := C.malloc(C.size_t(len(fontData)))
+	cBuf := (*[1 << 30]byte)(fontDataC)
+
+	copy(cBuf[:], fontData)
+
+	fontHandle := C.iggAddFontFromMemoryTTF(atlas.handle(), (*C.char)(fontDataC), C.int(len(fontData)), C.float(sizePixels),
+		config.handle(), glyphRange.handle())
+
+	return Font(fontHandle)
+}
+
+// AddFontFromMemoryTTF calls AddFontFromMemoryTTFV(fontData, sizePixels, DefaultFontConfig, EmptyGlyphRanges).
+func (atlas FontAtlas) AddFontFromMemoryTTF(fontData []byte, sizePixels float32) Font {
+	return atlas.AddFontFromMemoryTTFV(fontData, sizePixels, DefaultFontConfig, EmptyGlyphRanges)
+}
+
+// SetTexDesiredWidth registers the width desired by user before building the image. Must be a power-of-two.
+// If have many glyphs your graphics API have texture size restrictions you may want to increase texture width to decrease height.
+// Set to 0 by default, causing auto-calculation.
+func (atlas FontAtlas) SetTexDesiredWidth(value int) {
+	C.iggFontAtlasSetTexDesiredWidth(atlas.handle(), C.int(value))
+}
+
+// TextureDataAlpha8 returns the image in 8-bit alpha values for the font atlas.
+// The returned image is valid as long as the font atlas is.
+func (atlas FontAtlas) TextureDataAlpha8() *Alpha8Image {
+	var pixels *C.uchar
+	var width C.int
+	var height C.int
+	var bytesPerPixel C.int
+	C.iggFontAtlasGetTexDataAsAlpha8(atlas.handle(), &pixels, &width, &height, &bytesPerPixel)
+
+	return &Alpha8Image{
+		Width:  int(width),
+		Height: int(height),
+		Pixels: unsafe.Pointer(pixels), // nolint: gas
+	}
+}
+
+// TextureDataRGBA32 returns the image in 32-bit RGBA values for the font atlas.
+// The returned image is valid as long as the font atlas is.
+func (atlas FontAtlas) TextureDataRGBA32() *RGBA32Image {
+	var pixels *C.uchar
+	var width C.int
+	var height C.int
+	var bytesPerPixel C.int
+	C.iggFontAtlasGetTexDataAsRGBA32(atlas.handle(), &pixels, &width, &height, &bytesPerPixel)
+
+	return &RGBA32Image{
+		Width:  int(width),
+		Height: int(height),
+		Pixels: unsafe.Pointer(pixels), // nolint: gas
+	}
+}
+
+// SetTextureID sets user data to refer to the texture once it has been uploaded to user's graphic systems.
+// It is passed back to you during rendering via the DrawCommand.
+func (atlas FontAtlas) SetTextureID(id TextureID) {
+	C.iggFontAtlasSetTextureID(atlas.handle(), id.handle())
+}
+
+func (atlas FontAtlas) Clear() {
+	C.iggFontAtlasClear(atlas.handle())
+}
+
+func (atlas FontAtlas) Build() {
+	C.iggFontAtlasBuild(atlas.handle())
+}
+
+// FontBuilderFlags returns shared flags (for all fonts) for custom font builder.
+func (atlas FontAtlas) FontBuilderFlags() uint {
+	return uint(C.iggFontAtlasGetFontBuilderFlags(atlas.handle()))
+}
+
+// SetFontBuilderFlags sets shared flags (for all fonts) for custom font builder.
+// THIS IS BUILD IMPLEMENTATION DEPENDENT. Per-font override is also available in FontConfig.
+func (atlas FontAtlas) SetFontBuilderFlags(flags uint) {
+	C.iggFontAtlasSetFontBuilderFlags(atlas.handle(), C.uint(flags))
+}
+
+// Returns fonts count currently available.
+func (atlas FontAtlas) GetFontCount() int {
+	return int(C.iggFontAtlasFontCount(atlas.handle()))
+}

+ 121 - 0
vendor/github.com/AllenDang/imgui-go/FontAtlasWrapper.cpp

@@ -0,0 +1,121 @@
+#include "FontAtlasWrapper.h"
+#include "WrapperConverter.h"
+#include "imguiWrappedHeader.h"
+
+IggGlyphRanges iggGetGlyphRangesAll() {
+  static const ImWchar ranges[] = {
+      0x0001,
+      0xFFFF,
+      0,
+  };
+  return static_cast<IggGlyphRanges>(const_cast<ImWchar *>(&ranges[0]));
+}
+
+IggGlyphRanges iggGetGlyphRangesDefault(IggFontAtlas handle) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  return static_cast<IggGlyphRanges>(const_cast<ImWchar *>(fontAtlas->GetGlyphRangesDefault()));
+}
+
+IggGlyphRanges iggGetGlyphRangesKorean(IggFontAtlas handle) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  return static_cast<IggGlyphRanges>(const_cast<ImWchar *>(fontAtlas->GetGlyphRangesKorean()));
+}
+
+IggGlyphRanges iggGetGlyphRangesJapanese(IggFontAtlas handle) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  return static_cast<IggGlyphRanges>(const_cast<ImWchar *>(fontAtlas->GetGlyphRangesJapanese()));
+}
+
+IggGlyphRanges iggGetGlyphRangesChineseFull(IggFontAtlas handle) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  return static_cast<IggGlyphRanges>(const_cast<ImWchar *>(fontAtlas->GetGlyphRangesChineseFull()));
+}
+
+IggGlyphRanges iggGetGlyphRangesChineseSimplifiedCommon(IggFontAtlas handle) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  return static_cast<IggGlyphRanges>(const_cast<ImWchar *>(fontAtlas->GetGlyphRangesChineseSimplifiedCommon()));
+}
+
+IggGlyphRanges iggGetGlyphRangesCyrillic(IggFontAtlas handle) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  return static_cast<IggGlyphRanges>(const_cast<ImWchar *>(fontAtlas->GetGlyphRangesCyrillic()));
+}
+
+IggGlyphRanges iggGetGlyphRangesThai(IggFontAtlas handle) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  return static_cast<IggGlyphRanges>(const_cast<ImWchar *>(fontAtlas->GetGlyphRangesThai()));
+}
+
+IggFont iggAddFontDefault(IggFontAtlas handle) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  ImFont *font = fontAtlas->AddFontDefault();
+  return static_cast<IggFont>(font);
+}
+
+IggFont iggAddFontDefaultV(IggFontAtlas handle, IggFontConfig config) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  ImFontConfig *fontConfig = reinterpret_cast<ImFontConfig *>(config);
+  ImFont *font = fontAtlas->AddFontDefault(fontConfig);
+  return static_cast<IggFont>(font);
+}
+
+IggFont iggAddFontFromFileTTF(IggFontAtlas handle, char const *filename, float sizePixels, IggFontConfig config, IggGlyphRanges glyphRanges) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  ImFontConfig *fontConfig = reinterpret_cast<ImFontConfig *>(config);
+  ImWchar *glyphChars = reinterpret_cast<ImWchar *>(glyphRanges);
+  ImFont *font = fontAtlas->AddFontFromFileTTF(filename, sizePixels, fontConfig, glyphChars);
+  return static_cast<IggFont>(font);
+}
+
+IggFont iggAddFontFromMemoryTTF(IggFontAtlas handle, char *font_data, int font_size, float sizePixels, IggFontConfig config, IggGlyphRanges glyphRanges) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  ImFontConfig *fontConfig = reinterpret_cast<ImFontConfig *>(config);
+  ImWchar *glyphChars = reinterpret_cast<ImWchar *>(glyphRanges);
+  ImFont *font = fontAtlas->AddFontFromMemoryTTF(font_data, font_size, sizePixels, fontConfig, glyphChars);
+  return static_cast<IggFont>(font);
+}
+
+void iggFontAtlasSetTexDesiredWidth(IggFontAtlas handle, int value) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  fontAtlas->TexDesiredWidth = value;
+}
+
+void iggFontAtlasGetTexDataAsAlpha8(IggFontAtlas handle, unsigned char **pixels, int *width, int *height, int *bytesPerPixel) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  fontAtlas->GetTexDataAsAlpha8(pixels, width, height, bytesPerPixel);
+}
+
+void iggFontAtlasGetTexDataAsRGBA32(IggFontAtlas handle, unsigned char **pixels, int *width, int *height, int *bytesPerPixel) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  fontAtlas->GetTexDataAsRGBA32(pixels, width, height, bytesPerPixel);
+}
+
+void iggFontAtlasSetTextureID(IggFontAtlas handle, IggTextureID id) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  fontAtlas->SetTexID(reinterpret_cast<ImTextureID>(id));
+}
+
+void iggFontAtlasBuild(IggFontAtlas handle) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  fontAtlas->Build();
+}
+
+void iggFontAtlasClear(IggFontAtlas handle) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  fontAtlas->Clear();
+}
+
+unsigned int iggFontAtlasGetFontBuilderFlags(IggFontAtlas handle) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  return fontAtlas->FontBuilderFlags;
+}
+
+void iggFontAtlasSetFontBuilderFlags(IggFontAtlas handle, unsigned int flags) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  fontAtlas->FontBuilderFlags = flags;
+}
+
+int iggFontAtlasFontCount(IggFontAtlas handle) {
+  ImFontAtlas *fontAtlas = reinterpret_cast<ImFontAtlas *>(handle);
+  return fontAtlas->Fonts.size();
+}

+ 44 - 0
vendor/github.com/AllenDang/imgui-go/FontAtlasWrapper.h

@@ -0,0 +1,44 @@
+#pragma once
+
+#include "imguiWrapperTypes.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+extern IggGlyphRanges iggGetGlyphRangesAll();
+extern IggGlyphRanges iggGetGlyphRangesDefault(IggFontAtlas handle);
+extern IggGlyphRanges iggGetGlyphRangesKorean(IggFontAtlas handle);
+extern IggGlyphRanges iggGetGlyphRangesJapanese(IggFontAtlas handle);
+extern IggGlyphRanges iggGetGlyphRangesChineseFull(IggFontAtlas handle);
+extern IggGlyphRanges iggGetGlyphRangesChineseSimplifiedCommon(IggFontAtlas handle);
+extern IggGlyphRanges iggGetGlyphRangesCyrillic(IggFontAtlas handle);
+extern IggGlyphRanges iggGetGlyphRangesThai(IggFontAtlas handle);
+
+extern IggFont iggAddFontDefault(IggFontAtlas handle);
+extern IggFont iggAddFontDefaultV(IggFontAtlas handle, IggFontConfig config);
+extern IggFont iggAddFontFromFileTTF(IggFontAtlas handle, char const *filename, float sizePixels,
+		IggFontConfig config, IggGlyphRanges glyphRanges);
+extern IggFont iggAddFontFromMemoryTTF(IggFontAtlas handle, char *font_data, int font_size, float sizePixels,
+		IggFontConfig config, IggGlyphRanges glyphRanges);
+
+extern int iggFontAtlasFontCount(IggFontAtlas handle);
+
+extern void iggFontAtlasSetTexDesiredWidth(IggFontAtlas handle, int value);
+
+extern void iggFontAtlasGetTexDataAsAlpha8(IggFontAtlas handle, unsigned char **pixels,
+      int *width, int *height, int *bytesPerPixel);
+extern void iggFontAtlasGetTexDataAsRGBA32(IggFontAtlas handle, unsigned char **pixels,
+      int *width, int *height, int *bytesPerPixel);
+extern void iggFontAtlasSetTextureID(IggFontAtlas handle, IggTextureID id);
+
+extern void iggFontAtlasBuild(IggFontAtlas handle);
+extern void iggFontAtlasClear(IggFontAtlas handle);
+
+extern unsigned int iggFontAtlasGetFontBuilderFlags(IggFontAtlas handle);
+extern void iggFontAtlasSetFontBuilderFlags(IggFontAtlas handle, unsigned int flags);
+
+#ifdef __cplusplus
+}
+#endif

+ 117 - 0
vendor/github.com/AllenDang/imgui-go/FontConfig.go

@@ -0,0 +1,117 @@
+package imgui
+
+// #include "FontConfigWrapper.h"
+import "C"
+
+// FontConfig describes properties of a single font.
+type FontConfig uintptr
+
+// DefaultFontConfig lets ImGui take default properties as per implementation.
+// The properties of the default configuration cannot be changed using the SetXXX functions.
+const DefaultFontConfig FontConfig = 0
+
+func (config FontConfig) handle() C.IggFontConfig {
+	return C.IggFontConfig(config)
+}
+
+// NewFontConfig creates a new font configuration.
+// Delete must be called on the returned config.
+func NewFontConfig() FontConfig {
+	configHandle := C.iggNewFontConfig()
+	return FontConfig(configHandle)
+}
+
+// Delete removes the font configuration and resets it to the DefaultFontConfig.
+func (config *FontConfig) Delete() {
+	if *config != DefaultFontConfig {
+		C.iggFontConfigDelete(config.handle())
+		*config = DefaultFontConfig
+	}
+}
+
+// SetSize sets the size in pixels for rasterizer (more or less maps to the
+// resulting font height).
+func (config FontConfig) SetSize(sizePixels float32) {
+	if config != DefaultFontConfig {
+		C.iggFontConfigSetSize(config.handle(), C.float(sizePixels))
+	}
+}
+
+// SetOversampleH sets the oversampling amount for the X axis.
+// Rasterize at higher quality for sub-pixel positioning.
+// We don't use sub-pixel positions on the Y axis.
+func (config FontConfig) SetOversampleH(value int) {
+	if config != DefaultFontConfig {
+		C.iggFontConfigSetOversampleH(config.handle(), C.int(value))
+	}
+}
+
+// SetOversampleV sets the oversampling amount for the Y axis.
+// Rasterize at higher quality for sub-pixel positioning.
+// We don't use sub-pixel positions on the Y axis.
+func (config FontConfig) SetOversampleV(value int) {
+	if config != DefaultFontConfig {
+		C.iggFontConfigSetOversampleV(config.handle(), C.int(value))
+	}
+}
+
+// SetPixelSnapH aligns every glyph to pixel boundary if enabled. Useful e.g. if
+// you are merging a non-pixel aligned font with the default font. If enabled,
+// you can set OversampleH/V to 1.
+func (config FontConfig) SetPixelSnapH(value bool) {
+	if config != DefaultFontConfig {
+		C.iggFontConfigSetPixelSnapH(config.handle(), castBool(value))
+	}
+}
+
+// SetGlyphMinAdvanceX sets the minimum AdvanceX for glyphs.
+// Set Min to align font icons, set both Min/Max to enforce mono-space font.
+func (config FontConfig) SetGlyphMinAdvanceX(value float32) {
+	if config != DefaultFontConfig {
+		C.iggFontConfigSetGlyphMinAdvanceX(config.handle(), C.float(value))
+	}
+}
+
+// SetGlyphMaxAdvanceX sets the maximum AdvanceX for glyphs.
+// Set both Min/Max to enforce mono-space font.
+func (config FontConfig) SetGlyphMaxAdvanceX(value float32) {
+	if config != DefaultFontConfig {
+		C.iggFontConfigSetGlyphMaxAdvanceX(config.handle(), C.float(value))
+	}
+}
+
+// SetMergeMode merges the new fonts into the previous font if enabled. This way
+// you can combine multiple input fonts into one (e.g. ASCII font + icons +
+// Japanese glyphs). You may want to use GlyphOffset.y when merge font of
+// different heights.
+func (config FontConfig) SetMergeMode(value bool) {
+	if config != DefaultFontConfig {
+		C.iggFontConfigSetMergeMode(config.handle(), castBool(value))
+	}
+}
+
+// getFontDataOwnedByAtlas gets the current ownership status of the font data.
+func (config FontConfig) getFontDataOwnedByAtlas() bool {
+	if config != DefaultFontConfig {
+		return C.iggFontConfigGetFontDataOwnedByAtlas(config.handle()) != 0
+	}
+
+	return true
+}
+
+// Brighten (>1.0f) or darken (<1.0f) font output. Brightening small fonts may be a good workaround to make them more readable.
+func (config FontConfig) SetRasterizerMultiply(value float32) {
+	if config != DefaultFontConfig {
+		C.iggFontConfigSetRasterizerMultiply(config.handle(), C.float(value))
+	}
+}
+
+// FontBuilderFlags returns settings for custom font builder.
+func (config FontConfig) FontBuilderFlags() uint {
+	return uint(C.iggFontConfigGetFontBuilderFlags(config.handle()))
+}
+
+// SetFontBuilderFlags sets settings for custom font builder. THIS IS BUILDER IMPLEMENTATION DEPENDENT. Leave as zero if unsure.
+func (config FontConfig) SetFontBuilderFlags(flags uint) {
+	C.iggFontConfigSetFontBuilderFlags(config.handle(), C.uint(flags))
+}

+ 80 - 0
vendor/github.com/AllenDang/imgui-go/FontConfigWrapper.cpp

@@ -0,0 +1,80 @@
+#include "imguiWrappedHeader.h"
+#include "FontConfigWrapper.h"
+
+IggFontConfig iggNewFontConfig()
+{
+   ImFontConfig *fontConfig = new ImFontConfig();
+   return static_cast<IggFontConfig>(fontConfig);
+}
+
+void iggFontConfigDelete(IggFontConfig handle)
+{
+   ImFontConfig *fontConfig = reinterpret_cast<ImFontConfig *>(handle);
+   delete fontConfig;
+}
+
+void iggFontConfigSetSize(IggFontConfig handle, float sizePixels)
+{
+   ImFontConfig *fontConfig = reinterpret_cast<ImFontConfig *>(handle);
+   fontConfig->SizePixels = sizePixels;
+}
+
+void iggFontConfigSetOversampleH(IggFontConfig handle, int value)
+{
+   ImFontConfig *fontConfig = reinterpret_cast<ImFontConfig *>(handle);
+   fontConfig->OversampleH = value;
+}
+
+void iggFontConfigSetOversampleV(IggFontConfig handle, int value)
+{
+   ImFontConfig *fontConfig = reinterpret_cast<ImFontConfig *>(handle);
+   fontConfig->OversampleV = value;
+}
+
+void iggFontConfigSetPixelSnapH(IggFontConfig handle, IggBool value)
+{
+   ImFontConfig *fontConfig = reinterpret_cast<ImFontConfig *>(handle);
+   fontConfig->PixelSnapH = value;
+}
+
+void iggFontConfigSetGlyphMinAdvanceX(IggFontConfig handle, float value)
+{
+   ImFontConfig *fontConfig = reinterpret_cast<ImFontConfig *>(handle);
+   fontConfig->GlyphMinAdvanceX = value;
+}
+
+void iggFontConfigSetGlyphMaxAdvanceX(IggFontConfig handle, float value)
+{
+   ImFontConfig *fontConfig = reinterpret_cast<ImFontConfig *>(handle);
+   fontConfig->GlyphMaxAdvanceX = value;
+}
+
+void iggFontConfigSetMergeMode(IggFontConfig handle, IggBool value)
+{
+   ImFontConfig *fontConfig = reinterpret_cast<ImFontConfig *>(handle);
+   fontConfig->MergeMode = value;
+}
+
+int iggFontConfigGetFontDataOwnedByAtlas(IggFontConfig handle)
+{
+   ImFontConfig *fontConfig = reinterpret_cast<ImFontConfig *>(handle);
+   return fontConfig->FontDataOwnedByAtlas;
+}
+
+void iggFontConfigSetRasterizerMultiply(IggFontConfig handle, float value)
+{
+   ImFontConfig *fontConfig = reinterpret_cast<ImFontConfig *>(handle);
+   fontConfig->RasterizerMultiply = value;
+}
+
+unsigned int iggFontConfigGetFontBuilderFlags(IggFontConfig handle)
+{
+   ImFontConfig *fontConfig = reinterpret_cast<ImFontConfig *>(handle);
+   return fontConfig->FontBuilderFlags;
+}
+
+void iggFontConfigSetFontBuilderFlags(IggFontConfig handle, unsigned int flags)
+{
+   ImFontConfig *fontConfig = reinterpret_cast<ImFontConfig *>(handle);
+   fontConfig->FontBuilderFlags = flags;
+}

+ 27 - 0
vendor/github.com/AllenDang/imgui-go/FontConfigWrapper.h

@@ -0,0 +1,27 @@
+#pragma once
+
+#include "imguiWrapperTypes.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+extern IggFontConfig iggNewFontConfig();
+extern void iggFontConfigDelete(IggFontConfig handle);
+
+extern void iggFontConfigSetSize(IggFontConfig handle, float sizePixels);
+extern void iggFontConfigSetOversampleH(IggFontConfig handle, int value);
+extern void iggFontConfigSetOversampleV(IggFontConfig handle, int value);
+extern void iggFontConfigSetPixelSnapH(IggFontConfig handle, IggBool value);
+extern void iggFontConfigSetGlyphMinAdvanceX(IggFontConfig handle, float value);
+extern void iggFontConfigSetGlyphMaxAdvanceX(IggFontConfig handle, float value);
+extern void iggFontConfigSetMergeMode(IggFontConfig handle, IggBool value);
+extern int iggFontConfigGetFontDataOwnedByAtlas(IggFontConfig handle);
+extern void iggFontConfigSetRasterizerMultiply(IggFontConfig handle, float value);
+extern unsigned int iggFontConfigGetFontBuilderFlags(IggFontConfig handle);
+extern void iggFontConfigSetFontBuilderFlags(IggFontConfig handle, unsigned int flags);
+
+#ifdef __cplusplus
+}
+#endif

+ 43 - 0
vendor/github.com/AllenDang/imgui-go/FontGlyphRangesBuilderWrapper.cpp

@@ -0,0 +1,43 @@
+#include "imguiWrappedHeader.h" 
+#include "FontGlyphRangesBuilderWrapper.h"
+
+IggGlyphRanges IggNewGlyphRanges() {
+  ImVector<ImWchar> *ranges = new ImVector<ImWchar>();
+  return static_cast<IggGlyphRanges>(ranges);
+}
+
+IggGlyphRanges IggGlyphRangesData(IggGlyphRanges handle) {
+  ImVector<ImWchar> *ranges = reinterpret_cast<ImVector<ImWchar>*>(handle); 
+  return static_cast<IggGlyphRanges>(ranges->Data);
+}
+
+IggFontGlyphRangesBuilder IggNewFontGlyphRangesBuilder()
+{
+  ImFontGlyphRangesBuilder *builder = new ImFontGlyphRangesBuilder();
+  return static_cast<IggFontGlyphRangesBuilder>(builder);
+}
+
+void IggFontGlyphRangesBuilderClear(IggFontGlyphRangesBuilder handle)
+{
+  ImFontGlyphRangesBuilder *builder = reinterpret_cast<ImFontGlyphRangesBuilder*>(handle);
+  builder->Clear();
+}
+
+void IggFontGlyphRangesBuilderAddText(IggFontGlyphRangesBuilder handle, const char* text)
+{
+  ImFontGlyphRangesBuilder *builder = reinterpret_cast<ImFontGlyphRangesBuilder*>(handle);
+  builder->AddText(text);
+}
+
+void IggFontGlyphRangesBuilderAddRanges(IggFontGlyphRangesBuilder handle, IggGlyphRanges ranges)
+{
+  ImFontGlyphRangesBuilder *builder = reinterpret_cast<ImFontGlyphRangesBuilder*>(handle);
+  builder->AddRanges(reinterpret_cast<ImWchar*>(ranges));
+}
+
+void IggFontGlyphRangesBuilderBuildRanges(IggFontGlyphRangesBuilder handle, IggGlyphRanges ranges)
+{
+  ImFontGlyphRangesBuilder *builder = reinterpret_cast<ImFontGlyphRangesBuilder*>(handle);
+  builder->BuildRanges(reinterpret_cast<ImVector<ImWchar>*>(ranges));
+}
+

+ 21 - 0
vendor/github.com/AllenDang/imgui-go/FontGlyphRangesBuilderWrapper.h

@@ -0,0 +1,21 @@
+#pragma once
+
+#include "imguiWrapperTypes.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+extern IggGlyphRanges IggNewGlyphRanges();
+extern IggGlyphRanges IggGlyphRangesData(IggGlyphRanges handle);
+
+extern IggFontGlyphRangesBuilder IggNewFontGlyphRangesBuilder();
+extern void IggFontGlyphRangesBuilderClear(IggFontGlyphRangesBuilder handle);
+extern void IggFontGlyphRangesBuilderAddRanges(IggFontGlyphRangesBuilder handle, IggGlyphRanges ranges);
+extern void IggFontGlyphRangesBuilderAddText(IggFontGlyphRangesBuilder handle, const char* text);
+extern void IggFontGlyphRangesBuilderBuildRanges(IggFontGlyphRangesBuilder handle, IggGlyphRanges ranges);
+
+#ifdef __cplusplus 
+}
+#endif

+ 43 - 0
vendor/github.com/AllenDang/imgui-go/FontGlyphRnagesBuilder.go

@@ -0,0 +1,43 @@
+package imgui
+
+// #include "FontGlyphRangesBuilderWrapper.h"
+import "C"
+
+type FontGlyphRangesBuilder uintptr
+
+func NewGlyphRanges() GlyphRanges {
+	handle := C.IggNewGlyphRanges()
+	return GlyphRanges(handle)
+}
+
+func (ranges GlyphRanges) Data() GlyphRanges {
+	return GlyphRanges(C.IggGlyphRangesData(ranges.handle()))
+}
+
+func NewFontGlyphRangesBuilder() FontGlyphRangesBuilder {
+	handle := C.IggNewFontGlyphRangesBuilder()
+	return FontGlyphRangesBuilder(handle)
+}
+
+func (builder FontGlyphRangesBuilder) handle() C.IggFontGlyphRangesBuilder {
+	return C.IggFontGlyphRangesBuilder(builder)
+}
+
+func (builder FontGlyphRangesBuilder) AddText(text string) {
+	textArg, textFin := wrapString(text)
+	defer textFin()
+
+	C.IggFontGlyphRangesBuilderAddText(builder.handle(), textArg)
+}
+
+func (builder FontGlyphRangesBuilder) AddRanges(ranges GlyphRanges) {
+	C.IggFontGlyphRangesBuilderAddRanges(builder.handle(), C.IggGlyphRanges(ranges))
+}
+
+func (builder FontGlyphRangesBuilder) Clear() {
+	C.IggFontGlyphRangesBuilderClear(builder.handle())
+}
+
+func (builder FontGlyphRangesBuilder) BuildRanges(ranges GlyphRanges) {
+	C.IggFontGlyphRangesBuilderBuildRanges(builder.handle(), C.IggGlyphRanges(ranges))
+}

+ 8 - 0
vendor/github.com/AllenDang/imgui-go/FontWrapper.cpp

@@ -0,0 +1,8 @@
+#include "imguiWrappedHeader.h"
+#include "FontWrapper.h"
+
+IggFontGlyph iggFontFindGlyph(IggFont handle, unsigned int c)
+{
+  ImFont *font = reinterpret_cast<ImFont *>(handle);
+  return static_cast<IggFontGlyph>(const_cast<ImFontGlyph *>(font->FindGlyph(c)));
+}

+ 14 - 0
vendor/github.com/AllenDang/imgui-go/FontWrapper.h

@@ -0,0 +1,14 @@
+#pragma once
+
+#include "imguiWrapperTypes.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+extern IggFontGlyph iggFontFindGlyph(IggFont handle, unsigned int c);
+  
+#ifdef __cplusplus
+}
+#endif

+ 15 - 0
vendor/github.com/AllenDang/imgui-go/GlyphRanges.go

@@ -0,0 +1,15 @@
+package imgui
+
+// #include "imguiWrapperTypes.h"
+import "C"
+
+// GlyphRanges describes a list of Unicode ranges; 2 value per range, values are inclusive.
+// Standard ranges can be queried from FontAtlas.GlyphRanges*() functions.
+type GlyphRanges uintptr
+
+// EmptyGlyphRanges is one that does not contain any ranges.
+const EmptyGlyphRanges GlyphRanges = 0
+
+func (glyphs GlyphRanges) handle() C.IggGlyphRanges {
+	return C.IggGlyphRanges(glyphs)
+}

+ 17 - 0
vendor/github.com/AllenDang/imgui-go/HoveredFlags.go

@@ -0,0 +1,17 @@
+package imgui
+
+const (
+	HoveredFlagsNone             = 0      // Return true if directly over the item/window, not obstructed by another window, not obstructed by an active popup or modal blocking inputs under them.
+	HoveredFlagsChildWindows     = 1 << 0 // IsWindowHovered() only: Return true if any children of the window is hovered
+	HoveredFlagsRootWindow       = 1 << 1 // IsWindowHovered() only: Test from root window (top most parent of the current hierarchy)
+	HoveredFlagsAnyWindow        = 1 << 2 // IsWindowHovered() only: Return true if any window is hovered
+	HoveredFlagsNoPopupHierarchy = 1 << 3 // IsWindowHovered() only: Do not consider popup hierarchy (do not treat popup emitter as parent of popup) (when used with ChildWindows or RootWindow)
+	//HoveredFlagsDockHierarchy               = 1 << 4   // IsWindowHovered() only: Consider docking hierarchy (treat dockspace host as parent of docked window) (when used with ChildWindows or RootWindow)
+	HoveredFlagsAllowWhenBlockedByPopup = 1 << 5 // Return true even if a popup window is normally blocking access to this item/window
+	//HoveredFlagsAllowWhenBlockedByModal     = 1 << 6   // Return true even if a modal popup window is normally blocking access to this item/window. FIXME-TODO: Unavailable yet.
+	HoveredFlagsAllowWhenBlockedByActiveItem = 1 << 7 // Return true even if an active item is blocking access to this item/window. Useful for Drag and Drop patterns.
+	HoveredFlagsAllowWhenOverlapped          = 1 << 8 // IsItemHovered() only: Return true even if the position is obstructed or overlapped by another window
+	HoveredFlagsAllowWhenDisabled            = 1 << 9 // IsItemHovered() only: Return true even if the item is disabled
+	HoveredFlagsRectOnly                     = HoveredFlagsAllowWhenBlockedByPopup | HoveredFlagsAllowWhenBlockedByActiveItem | HoveredFlagsAllowWhenOverlapped
+	HoveredFlagsRootAndChildWindows          = HoveredFlagsRootWindow | HoveredFlagsChildWindows
+)

+ 250 - 0
vendor/github.com/AllenDang/imgui-go/IO.go

@@ -0,0 +1,250 @@
+package imgui
+
+// #include "IOWrapper.h"
+import "C"
+
+// IO is where your app communicate with ImGui. Access via CurrentIO().
+// Read 'Programmer guide' section in imgui.cpp file for general usage.
+type IO struct {
+	handle C.IggIO
+}
+
+// WantCaptureMouse returns true if imgui will use the mouse inputs.
+// Do not dispatch them to your main game/application in this case.
+// In either case, always pass on mouse inputs to imgui.
+// (e.g. unclicked mouse is hovering over an imgui window, widget is active, mouse was clicked over an imgui window, etc.)
+func (io IO) WantCaptureMouse() bool {
+	return C.iggWantCaptureMouse(io.handle) != 0
+}
+
+// WantCaptureKeyboard returns true if imgui will use the keyboard inputs.
+// Do not dispatch them to your main game/application (in both cases, always pass keyboard inputs to imgui).
+// (e.g. InputText active, or an imgui window is focused and navigation is enabled, etc.).
+func (io IO) WantCaptureKeyboard() bool {
+	return C.iggWantCaptureKeyboard(io.handle) != 0
+}
+
+// WantTextInput is true, you may display an on-screen keyboard.
+// This is set by ImGui when it wants textual keyboard input to happen (e.g. when a InputText widget is active).
+func (io IO) WantTextInput() bool {
+	return C.iggWantTextInput(io.handle) != 0
+}
+
+// SetDisplaySize sets the size in pixels.
+func (io IO) SetDisplaySize(value Vec2) {
+	out, _ := value.wrapped()
+	C.iggIoSetDisplaySize(io.handle, out)
+}
+
+func (io IO) GetMouseDrawCursor() bool {
+	return C.iggIoGetMouseDrawCursor(io.handle) != 0
+}
+
+func (io IO) SetMouseDrawCursor(b bool) {
+	C.iggIoSetMouseDrawCursor(io.handle, castBool(b))
+}
+
+// Fonts returns the font atlas to load and assemble one or more fonts into a single tightly packed texture.
+func (io IO) Fonts() FontAtlas {
+	return FontAtlas(C.iggIoGetFonts(io.handle))
+}
+
+// SetMousePosition sets the mouse position, in pixels.
+// Set to Vec2(-math.MaxFloat32,-mathMaxFloat32) if mouse is unavailable (on another screen, etc.)
+func (io IO) SetMousePosition(value Vec2) {
+	posArg, _ := value.wrapped()
+	C.iggIoSetMousePosition(io.handle, posArg)
+}
+
+// SetMouseButtonDown sets whether a specific mouse button is currently pressed.
+// Mouse buttons: left, right, middle + extras.
+// ImGui itself mostly only uses left button (BeginPopupContext** are using right button).
+// Other buttons allows us to track if the mouse is being used by your application +
+// available to user as a convenience via IsMouse** API.
+func (io IO) SetMouseButtonDown(index int, down bool) {
+	var downArg C.IggBool
+	if down {
+		downArg = 1
+	}
+	C.iggIoSetMouseButtonDown(io.handle, C.int(index), downArg)
+}
+
+// AddMouseWheelDelta adds the given offsets to the current mouse wheel values.
+// 1 vertical unit scrolls about 5 lines text.
+// Most users don't have a mouse with an horizontal wheel, may not be provided by all back-ends.
+func (io IO) AddMouseWheelDelta(horizontal, vertical float32) {
+	C.iggIoAddMouseWheelDelta(io.handle, C.float(horizontal), C.float(vertical))
+}
+
+// GetMouseWheelDelta returns the vertical delta of the mouse wheel.
+func (io IO) GetMouseWheelDelta() float32 {
+	var delta float32
+	deltaArg, deltaFin := wrapFloat(&delta)
+	C.iggIoGetMouseWheelDelta(io.handle, deltaArg)
+	deltaFin()
+	return delta
+}
+
+// GetMouseWheelHDelta returns the horizontal delta of the mouse wheel.
+func (io IO) GetMouseWheelHDelta() float32 {
+	var delta float32
+	deltaArg, deltaFin := wrapFloat(&delta)
+	C.iggIoGetMouseWheelHDelta(io.handle, deltaArg)
+	deltaFin()
+	return delta
+}
+
+func (io IO) GetMouseDelta() Vec2 {
+	var delta Vec2
+	deltaArg, deltaFin := delta.wrapped()
+	C.iggIoGetMouseDelta(io.handle, deltaArg)
+	deltaFin()
+	return delta
+}
+
+// SetDeltaTime sets the time elapsed since last frame, in seconds.
+func (io IO) SetDeltaTime(value float32) {
+	C.iggIoSetDeltaTime(io.handle, C.float(value))
+}
+
+// SetFontGlobalScale sets the global scaling factor for all fonts.
+func (io IO) SetFontGlobalScale(value float32) {
+	C.iggIoSetFontGlobalScale(io.handle, C.float(value))
+}
+
+// KeyPress sets the KeysDown flag.
+func (io IO) KeyPress(key int) {
+	C.iggIoKeyPress(io.handle, C.int(key))
+}
+
+// KeyRelease clears the KeysDown flag.
+func (io IO) KeyRelease(key int) {
+	C.iggIoKeyRelease(io.handle, C.int(key))
+}
+
+// KeyMap maps a key into the KeysDown array which represents your "native" keyboard state.
+func (io IO) KeyMap(imguiKey int, nativeKey int) {
+	C.iggIoKeyMap(io.handle, C.int(imguiKey), C.int(nativeKey))
+}
+
+// KeyCtrl sets the keyboard modifier control pressed.
+func (io IO) KeyCtrl(leftCtrl int, rightCtrl int) {
+	C.iggIoKeyCtrl(io.handle, C.int(leftCtrl), C.int(rightCtrl))
+}
+
+// KeyShift sets the keyboard modifier shift pressed.
+func (io IO) KeyShift(leftShift int, rightShift int) {
+	C.iggIoKeyShift(io.handle, C.int(leftShift), C.int(rightShift))
+}
+
+// KeyAlt sets the keyboard modifier alt pressed.
+func (io IO) KeyAlt(leftAlt int, rightAlt int) {
+	C.iggIoKeyAlt(io.handle, C.int(leftAlt), C.int(rightAlt))
+}
+
+// KeySuper sets the keyboard modifier super pressed.
+func (io IO) KeySuper(leftSuper int, rightSuper int) {
+	C.iggIoKeySuper(io.handle, C.int(leftSuper), C.int(rightSuper))
+}
+
+// AddInputCharacters adds a new character into InputCharacters[].
+func (io IO) AddInputCharacters(chars string) {
+	textArg, textFin := wrapString(chars)
+	defer textFin()
+	C.iggIoAddInputCharactersUTF8(io.handle, textArg)
+}
+
+// SetIniFilename changes the filename for the settings. Default: "imgui.ini".
+// Use an empty string to disable the ini from being used.
+func (io IO) SetIniFilename(value string) {
+	valueArg, valueFin := wrapString(value)
+	defer valueFin()
+	C.iggIoSetIniFilename(io.handle, valueArg)
+}
+
+// SetConfigFlags sets the gamepad/keyboard navigation options, etc.
+func (io IO) SetConfigFlags(flags int) {
+	C.iggIoSetConfigFlags(io.handle, C.int(flags))
+}
+
+func (io IO) GetConfigFlags() int {
+	return int(C.iggIoGetConfigFlags(io.handle))
+}
+
+// SetBackendFlags sets back-end capabilities.
+func (io IO) SetBackendFlags(flags int) {
+	C.iggIoSetBackendFlags(io.handle, C.int(flags))
+}
+
+func (io IO) GetFrameCountSinceLastInput() int {
+	return int(C.iggGetFrameCountSinceLastInput(io.handle))
+}
+
+func (io IO) SetFrameCountSinceLastInput(count int) {
+	C.iggSetFrameCountSinceLastInput(io.handle, C.int(count))
+}
+
+func (io IO) AddFocusEvent(focused bool) {
+  C.iggIoAddFocusEvent(io.handle, castBool(focused))
+}
+
+// Clipboard describes the access to the text clipboard of the window manager.
+type Clipboard interface {
+	// Text returns the current text from the clipboard, if available.
+	Text() (string, error)
+	// SetText sets the text as the current text on the clipboard.
+	SetText(value string)
+}
+
+var clipboards = map[C.IggIO]Clipboard{}
+var dropLastClipboardText = func() {}
+
+// SetClipboard registers a clipboard for text copy/paste actions.
+// If no clipboard is set, then a fallback implementation may be used, if available for the OS.
+// To disable clipboard handling overall, pass nil as the Clipboard.
+//
+// Since ImGui queries the clipboard text via a return value, the wrapper has to hold the
+// current clipboard text as a copy in memory. This memory will be freed at the next clipboard operation.
+func (io IO) SetClipboard(board Clipboard) {
+	dropLastClipboardText()
+
+	if board != nil {
+		clipboards[io.handle] = board
+		C.iggIoRegisterClipboardFunctions(io.handle)
+	} else {
+		C.iggIoClearClipboardFunctions(io.handle)
+		delete(clipboards, io.handle)
+	}
+}
+
+//export iggIoGetClipboardText
+func iggIoGetClipboardText(handle C.IggIO) *C.char {
+	dropLastClipboardText()
+
+	board := clipboards[handle]
+	if board == nil {
+		return nil
+	}
+
+	text, err := board.Text()
+	if err != nil {
+		return nil
+	}
+	textPtr, textFin := wrapString(text)
+	dropLastClipboardText = func() {
+		dropLastClipboardText = func() {}
+		textFin()
+	}
+	return textPtr
+}
+
+//export iggIoSetClipboardText
+func iggIoSetClipboardText(handle C.IggIO, text *C.char) {
+	dropLastClipboardText()
+
+	board := clipboards[handle]
+	if board == nil {
+		return
+	}
+	board.SetText(C.GoString(text))
+}

+ 218 - 0
vendor/github.com/AllenDang/imgui-go/IOWrapper.cpp

@@ -0,0 +1,218 @@
+#include "imguiWrappedHeader.h"
+#include "IOWrapper.h"
+#include "WrapperConverter.h"
+
+#include <string>
+
+IggBool iggWantCaptureMouse(IggIO handle)
+{
+   ImGuiIO *io = reinterpret_cast<ImGuiIO *>(handle);
+   return io->WantCaptureMouse ? 1 : 0;
+}
+
+IggBool iggWantCaptureKeyboard(IggIO handle)
+{
+   ImGuiIO *io = reinterpret_cast<ImGuiIO *>(handle);
+   return io->WantCaptureKeyboard ? 1 : 0;
+}
+
+IggBool iggWantTextInput(IggIO handle)
+{
+   ImGuiIO *io = reinterpret_cast<ImGuiIO *>(handle);
+   return io->WantTextInput ? 1 : 0;
+}
+
+IggFontAtlas iggIoGetFonts(IggIO handle)
+{
+   ImGuiIO *io = reinterpret_cast<ImGuiIO *>(handle);
+   return reinterpret_cast<IggFontAtlas>(io->Fonts);
+}
+
+void iggIoSetDisplaySize(IggIO handle, IggVec2 const *value)
+{
+   ImGuiIO *io = reinterpret_cast<ImGuiIO *>(handle);
+   importValue(io->DisplaySize, *value);
+}
+
+void iggIoSetMousePosition(IggIO handle, IggVec2 const *value)
+{
+   ImGuiIO *io = reinterpret_cast<ImGuiIO *>(handle);
+   importValue(io->MousePos, *value);
+}
+
+void iggIoSetMouseButtonDown(IggIO handle, int index, IggBool value)
+{
+   ImGuiIO *io = reinterpret_cast<ImGuiIO *>(handle);
+   io->MouseDown[index] = value != 0;
+}
+
+void iggIoAddMouseWheelDelta(IggIO handle, float horizontal, float vertical)
+{
+   ImGuiIO *io = reinterpret_cast<ImGuiIO *>(handle);
+   io->MouseWheelH += horizontal;
+   io->MouseWheel += vertical;
+}
+
+void iggIoGetMouseWheelDelta(IggIO handle, IggFloat *value)
+{
+  ImGuiIO *io = reinterpret_cast<ImGuiIO *>(handle);
+  exportValue(*value, io->MouseWheel);
+}
+
+void iggIoGetMouseWheelHDelta(IggIO handle, IggFloat *value)
+{
+  ImGuiIO *io = reinterpret_cast<ImGuiIO *>(handle);
+  exportValue(*value, io->MouseWheelH);
+}
+
+void iggIoGetMouseDelta(IggIO handle, IggVec2 *value)
+{
+  ImGuiIO *io = reinterpret_cast<ImGuiIO *>(handle);
+  exportValue(*value, io->MouseDelta);
+}
+
+void iggIoSetDeltaTime(IggIO handle, float value)
+{
+   ImGuiIO *io = reinterpret_cast<ImGuiIO *>(handle);
+   io->DeltaTime = value;
+}
+
+void iggIoSetFontGlobalScale(IggIO handle, float value)
+{
+   ImGuiIO *io = reinterpret_cast<ImGuiIO *>(handle);
+   io->FontGlobalScale = value;
+}
+
+
+IggBool iggIoGetMouseDrawCursor(IggIO handle)
+{
+   ImGuiIO *io = reinterpret_cast<ImGuiIO *>(handle);
+   return io->MouseDrawCursor ? 1 : 0;
+}
+
+void iggIoSetMouseDrawCursor(IggIO handle, IggBool value)
+{
+   ImGuiIO *io = reinterpret_cast<ImGuiIO *>(handle);
+   io->MouseDrawCursor = value != 0;
+}
+
+void iggIoKeyPress(IggIO handle, int key)
+{
+   ImGuiIO &io = *reinterpret_cast<ImGuiIO *>(handle);
+   io.KeysDown[key] = true;
+}
+
+void iggIoKeyRelease(IggIO handle, int key)
+{
+   ImGuiIO &io = *reinterpret_cast<ImGuiIO *>(handle);
+   io.KeysDown[key] = false;
+}
+
+void iggIoKeyMap(IggIO handle, int imguiKey, int nativeKey)
+{
+   ImGuiIO &io = *reinterpret_cast<ImGuiIO *>(handle);
+   io.KeyMap[imguiKey] = nativeKey;
+}
+
+void iggIoKeyCtrl(IggIO handle, int leftCtrl, int rightCtrl)
+{
+   ImGuiIO &io = *reinterpret_cast<ImGuiIO *>(handle);
+   io.KeyCtrl = io.KeysDown[leftCtrl] || io.KeysDown[rightCtrl];
+}
+
+void iggIoKeyShift(IggIO handle, int leftShift, int rightShift)
+{
+   ImGuiIO &io = *reinterpret_cast<ImGuiIO *>(handle);
+   io.KeyShift = io.KeysDown[leftShift] || io.KeysDown[rightShift];
+}
+
+void iggIoKeyAlt(IggIO handle, int leftAlt, int rightAlt)
+{
+   ImGuiIO &io = *reinterpret_cast<ImGuiIO *>(handle);
+   io.KeyAlt = io.KeysDown[leftAlt] || io.KeysDown[rightAlt];
+}
+
+void iggIoKeySuper(IggIO handle, int leftSuper, int rightSuper)
+{
+   ImGuiIO &io = *reinterpret_cast<ImGuiIO *>(handle);
+   io.KeySuper = io.KeysDown[leftSuper] || io.KeysDown[rightSuper];
+}
+
+void iggIoAddInputCharactersUTF8(IggIO handle, char const *utf8Chars)
+{
+   ImGuiIO &io = *reinterpret_cast<ImGuiIO *>(handle);
+   io.AddInputCharactersUTF8(utf8Chars);
+}
+
+void iggIoSetIniFilename(IggIO handle, char const *value)
+{
+   static std::string bufferValue;
+   ImGuiIO &io = *reinterpret_cast<ImGuiIO *>(handle);
+   bufferValue = (value != nullptr) ? value : "";
+   io.IniFilename = bufferValue.empty() ? nullptr : bufferValue.c_str();
+}
+
+void iggIoSetConfigFlags(IggIO handle, int flags)
+{
+   ImGuiIO &io = *reinterpret_cast<ImGuiIO *>(handle);
+   io.ConfigFlags = flags;
+}
+
+int iggIoGetConfigFlags(IggIO handle)
+{
+   ImGuiIO &io = *reinterpret_cast<ImGuiIO *>(handle);
+   return io.ConfigFlags;
+}
+
+void iggIoSetBackendFlags(IggIO handle, int flags)
+{
+   ImGuiIO &io = *reinterpret_cast<ImGuiIO *>(handle);
+   io.BackendFlags = flags;
+}
+
+extern "C" void iggIoSetClipboardText(IggIO handle, char *text);
+extern "C" char *iggIoGetClipboardText(IggIO handle);
+
+static void iggIoSetClipboardTextWrapper(void *userData, char const *text)
+{
+   iggIoSetClipboardText(userData, const_cast<char *>(text));
+}
+
+static char const *iggIoGetClipboardTextWrapper(void *userData)
+{
+   return iggIoGetClipboardText(userData);
+}
+
+void iggIoRegisterClipboardFunctions(IggIO handle)
+{
+   ImGuiIO &io = *reinterpret_cast<ImGuiIO *>(handle);
+   io.ClipboardUserData = handle;
+   io.GetClipboardTextFn = iggIoGetClipboardTextWrapper;
+   io.SetClipboardTextFn = iggIoSetClipboardTextWrapper;
+}
+
+void iggIoClearClipboardFunctions(IggIO handle)
+{
+   ImGuiIO &io = *reinterpret_cast<ImGuiIO *>(handle);
+   io.GetClipboardTextFn = nullptr;
+   io.SetClipboardTextFn = nullptr;
+   io.ClipboardUserData = nullptr;
+}
+
+int iggGetFrameCountSinceLastInput(IggIO handle)
+{
+   ImGuiIO &io = *reinterpret_cast<ImGuiIO *>(handle);
+   return io.FrameCountSinceLastInput;
+}
+
+void iggSetFrameCountSinceLastInput(IggIO handle, int count)
+{
+   ImGuiIO &io = *reinterpret_cast<ImGuiIO *>(handle);
+   io.FrameCountSinceLastInput = count;
+}
+
+void iggIoAddFocusEvent(IggIO handle, IggBool focused)
+{
+   ImGuiIO &io = *reinterpret_cast<ImGuiIO *>(handle);
+   io.AddFocusEvent(focused);
+}

+ 52 - 0
vendor/github.com/AllenDang/imgui-go/IOWrapper.h

@@ -0,0 +1,52 @@
+#pragma once
+
+#include "imguiWrapperTypes.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+    extern IggBool iggWantCaptureMouse(IggIO handle);
+    extern IggBool iggWantCaptureKeyboard(IggIO handle);
+    extern IggBool iggWantTextInput(IggIO handle);
+
+    extern IggFontAtlas iggIoGetFonts(IggIO handle);
+
+    extern void iggIoSetDisplaySize(IggIO handle, IggVec2 const *value);
+    extern void iggIoSetMousePosition(IggIO handle, IggVec2 const *value);
+    extern void iggIoSetMouseButtonDown(IggIO handle, int index, IggBool value);
+    extern void iggIoAddMouseWheelDelta(IggIO handle, float x, float y);
+    extern void iggIoGetMouseWheelDelta(IggIO handle, float *vertical);
+    extern void iggIoGetMouseWheelHDelta(IggIO handle, float *horizontal);
+    extern void iggIoGetMouseDelta(IggIO handle, IggVec2 *delta);
+    extern void iggIoSetDeltaTime(IggIO handle, float value);
+    extern void iggIoSetFontGlobalScale(IggIO handle, float value);
+
+    extern IggBool iggIoGetMouseDrawCursor(IggIO handle);
+    extern void iggIoSetMouseDrawCursor(IggIO handle, IggBool value);
+
+    extern void iggIoKeyPress(IggIO handle, int key);
+    extern void iggIoKeyRelease(IggIO handle, int key);
+    extern void iggIoKeyMap(IggIO handle, int imguiKey, int nativeKey);
+    extern void iggIoKeyCtrl(IggIO handle, int leftCtrl, int rightCtrl);
+    extern void iggIoKeyShift(IggIO handle, int leftShift, int rightShift);
+    extern void iggIoKeyAlt(IggIO handle, int leftAlt, int rightAlt);
+    extern void iggIoKeySuper(IggIO handle, int leftSuper, int rightSuper);
+    extern void iggIoAddInputCharactersUTF8(IggIO handle, char const *utf8Chars);
+    extern void iggIoSetIniFilename(IggIO handle, char const *value);
+    extern void iggIoSetConfigFlags(IggIO handle, int flags);
+    extern int iggIoGetConfigFlags(IggIO handle);
+    extern void iggIoSetBackendFlags(IggIO handle, int flags);
+
+    extern void iggIoRegisterClipboardFunctions(IggIO handle);
+    extern void iggIoClearClipboardFunctions(IggIO handle);
+
+    extern int iggGetFrameCountSinceLastInput(IggIO handle);
+    extern void iggSetFrameCountSinceLastInput(IggIO handle, int count);
+
+    extern void iggIoAddFocusEvent(IggIO handle, IggBool focused);
+
+#ifdef __cplusplus
+}
+#endif

+ 273 - 0
vendor/github.com/AllenDang/imgui-go/InputText.go

@@ -0,0 +1,273 @@
+package imgui
+
+// #include "InputTextCallbackDataWrapper.h"
+import "C"
+import (
+	"sync"
+	"unsafe"
+)
+
+const (
+	// InputTextFlagsNone sets everything default.
+	InputTextFlagsNone = 0
+	// InputTextFlagsCharsDecimal allows 0123456789.+-
+	InputTextFlagsCharsDecimal = 1 << 0
+	// InputTextFlagsCharsHexadecimal allow 0123456789ABCDEFabcdef
+	InputTextFlagsCharsHexadecimal = 1 << 1
+	// InputTextFlagsCharsUppercase turns a..z into A..Z.
+	InputTextFlagsCharsUppercase = 1 << 2
+	// InputTextFlagsCharsNoBlank filters out spaces, tabs.
+	InputTextFlagsCharsNoBlank = 1 << 3
+	// InputTextFlagsAutoSelectAll selects entire text when first taking mouse focus.
+	InputTextFlagsAutoSelectAll = 1 << 4
+	// InputTextFlagsEnterReturnsTrue returns 'true' when Enter is pressed (as opposed to when the value was modified).
+	InputTextFlagsEnterReturnsTrue = 1 << 5
+	// InputTextFlagsCallbackCompletion for callback on pressing TAB (for completion handling).
+	InputTextFlagsCallbackCompletion = 1 << 6
+	// InputTextFlagsCallbackHistory for callback on pressing Up/Down arrows (for history handling).
+	InputTextFlagsCallbackHistory = 1 << 7
+	// InputTextFlagsCallbackAlways for callback on each iteration. User code may query cursor position, modify text buffer.
+	InputTextFlagsCallbackAlways = 1 << 8
+	// InputTextFlagsCallbackCharFilter for callback on character inputs to replace or discard them.
+	// Modify 'EventChar' to replace or discard, or return 1 in callback to discard.
+	InputTextFlagsCallbackCharFilter = 1 << 9
+	// InputTextFlagsAllowTabInput when pressing TAB to input a '\t' character into the text field.
+	InputTextFlagsAllowTabInput = 1 << 10
+	// InputTextFlagsCtrlEnterForNewLine in multi-line mode, unfocus with Enter, add new line with Ctrl+Enter
+	// (default is opposite: unfocus with Ctrl+Enter, add line with Enter).
+	InputTextFlagsCtrlEnterForNewLine = 1 << 11
+	// InputTextFlagsNoHorizontalScroll disables following the cursor horizontally.
+	InputTextFlagsNoHorizontalScroll = 1 << 12
+	// InputTextFlagsAlwaysInsertMode sets insert mode.
+	InputTextFlagsAlwaysInsertMode = 1 << 13
+	// InputTextFlagsReadOnly sets read-only mode.
+	InputTextFlagsReadOnly = 1 << 14
+	// InputTextFlagsPassword sets password mode, display all characters as '*'.
+	InputTextFlagsPassword = 1 << 15
+	// InputTextFlagsNoUndoRedo disables undo/redo. Note that input text owns the text data while active,
+	// if you want to provide your own undo/redo stack you need e.g. to call ClearActiveID().
+	InputTextFlagsNoUndoRedo = 1 << 16
+	// InputTextFlagsCharsScientific allows 0123456789.+-*/eE (Scientific notation input).
+	InputTextFlagsCharsScientific = 1 << 17
+	// inputTextFlagsCallbackResize for callback on buffer capacity change requests.
+	inputTextFlagsCallbackResize = 1 << 18
+)
+
+// InputTextCallback is called for sharing state of an input field.
+// By default, the callback should return 0.
+type InputTextCallback func(InputTextCallbackData) int32
+
+type inputTextState struct {
+	buf *stringBuffer
+
+	key      C.int
+	callback InputTextCallback
+}
+
+var inputTextStates = make(map[C.int]*inputTextState)
+var inputTextStatesMutex sync.Mutex
+
+func newInputTextState(text string, cb InputTextCallback) *inputTextState {
+	state := &inputTextState{}
+	state.buf = newStringBuffer(text)
+	state.callback = cb
+	state.register()
+	return state
+}
+
+func (state *inputTextState) register() {
+	inputTextStatesMutex.Lock()
+	defer inputTextStatesMutex.Unlock()
+	key := C.int(len(inputTextStates) + 1)
+	for _, existing := inputTextStates[key]; existing; _, existing = inputTextStates[key] {
+		key++
+	}
+	state.key = key
+	inputTextStates[key] = state
+}
+
+func (state *inputTextState) release() {
+	state.buf.free()
+
+	if state.key != 0 {
+		inputTextStatesMutex.Lock()
+		defer inputTextStatesMutex.Unlock()
+		delete(inputTextStates, state.key)
+	}
+}
+
+func (state *inputTextState) onCallback(handle C.IggInputTextCallbackData) C.int {
+	data := InputTextCallbackData{state: state, handle: handle}
+	if data.EventFlag() == inputTextFlagsCallbackResize {
+		state.buf.resizeTo(data.bufSize())
+		data.setBuf(state.buf.ptr, state.buf.size, data.bufTextLen())
+		return 0
+	}
+	if state.callback == nil {
+		return 0
+	}
+	return C.int(state.callback(data))
+}
+
+//export iggInputTextCallback
+func iggInputTextCallback(handle C.IggInputTextCallbackData, key C.int) C.int {
+	state := iggInputTextStateFor(key)
+	return state.onCallback(handle)
+}
+
+func iggInputTextStateFor(key C.int) *inputTextState {
+	inputTextStatesMutex.Lock()
+	defer inputTextStatesMutex.Unlock()
+	return inputTextStates[key]
+}
+
+// InputTextCallbackData represents the shared state of InputText(), passed as an argument to your callback.
+type InputTextCallbackData struct {
+	state  *inputTextState
+	handle C.IggInputTextCallbackData
+}
+
+// EventFlag returns one of the InputTextFlagsCallback* constants to indicate the nature of the callback.
+func (data InputTextCallbackData) EventFlag() int {
+	return int(C.iggInputTextCallbackDataGetEventFlag(data.handle))
+}
+
+// Flags returns the set of flags that the user originally passed to InputText.
+func (data InputTextCallbackData) Flags() int {
+	return int(C.iggInputTextCallbackDataGetFlags(data.handle)) & ^inputTextFlagsCallbackResize
+}
+
+// EventChar returns the current character input. Only valid during CharFilter callback.
+func (data InputTextCallbackData) EventChar() rune {
+	return rune(C.iggInputTextCallbackDataGetEventChar(data.handle))
+}
+
+// SetEventChar overrides what the user entered. Set to zero do drop the current input.
+// Returning 1 from the callback also drops the current input.
+// Only valid during CharFilter callback.
+//
+// Note: The internal representation of characters is based on uint16, so less than rune would provide.
+func (data InputTextCallbackData) SetEventChar(value rune) {
+	C.iggInputTextCallbackDataSetEventChar(data.handle, C.ushort(value))
+}
+
+// EventKey returns the currently pressed key. Valid for completion and history callbacks.
+func (data InputTextCallbackData) EventKey() int {
+	return int(C.iggInputTextCallbackDataGetEventKey(data.handle))
+}
+
+// Buffer returns a view into the current UTF-8 buffer.
+// Only during the callbacks of [Completion,History,Always] the current buffer is returned.
+// The returned slice is a temporary view into the underlying raw buffer. Do not keep it!
+// The underlying memory allocation may even change through a call to InsertBytes().
+//
+// You may change the buffer through the following ways:
+// If the new text has a different (encoded) length, use the functions InsertBytes() and/or DeleteBytes().
+// Otherwise you may keep the buffer as is and modify the bytes. If you change the buffer this way directly, mark the buffer
+// as modified with MarkBufferModified().
+func (data InputTextCallbackData) Buffer() []byte {
+	ptr := C.iggInputTextCallbackDataGetBuf(data.handle)
+	if ptr == nil {
+		return nil
+	}
+	textLen := data.bufTextLen()
+	return ((*[1 << 30]byte)(unsafe.Pointer(ptr)))[:textLen]
+}
+
+// MarkBufferModified indicates that the content of the buffer was modified during a callback.
+// Only considered during [Completion,History,Always] callbacks.
+func (data InputTextCallbackData) MarkBufferModified() {
+	C.iggInputTextCallbackDataMarkBufferModified(data.handle)
+}
+
+func (data InputTextCallbackData) setBuf(buf unsafe.Pointer, size, textLen int) {
+	C.iggInputTextCallbackDataSetBuf(data.handle, (*C.char)(buf), C.int(size), C.int(textLen))
+}
+
+func (data InputTextCallbackData) bufSize() int {
+	return int(C.iggInputTextCallbackDataGetBufSize(data.handle))
+}
+
+func (data InputTextCallbackData) bufTextLen() int {
+	return int(C.iggInputTextCallbackDataGetBufTextLen(data.handle))
+}
+
+// DeleteBytes removes the given count of bytes starting at the specified byte offset within the buffer.
+// This function can be called during the [Completion,History,Always] callbacks.
+// Clears the current selection.
+//
+// This function ignores the deletion beyond the current buffer length.
+// Calling with negative offset or count arguments will panic.
+func (data InputTextCallbackData) DeleteBytes(offset, count int) {
+	if offset < 0 {
+		panic("invalid offset")
+	}
+	if count < 0 {
+		panic("invalid count")
+	}
+	textLen := data.bufTextLen()
+	if offset >= textLen {
+		return
+	}
+	toRemove := count
+	available := textLen - offset
+	if toRemove > available {
+		toRemove = available
+	}
+	C.iggInputTextCallbackDataDeleteBytes(data.handle, C.int(offset), C.int(toRemove))
+}
+
+// InsertBytes inserts the given bytes at given byte offset into the buffer.
+// Calling this function may change the underlying buffer allocation.
+//
+// This function can be called during the [Completion,History,Always] callbacks.
+// Clears the current selection.
+//
+// Calling with an offset outside of the range of the buffer will panic.
+func (data InputTextCallbackData) InsertBytes(offset int, bytes []byte) {
+	if (offset < 0) || (offset > data.bufTextLen()) {
+		panic("invalid offset")
+	}
+	var bytesPtr *C.char
+	byteCount := len(bytes)
+	if byteCount > 0 {
+		bytesPtr = (*C.char)(unsafe.Pointer(&bytes[0]))
+		C.iggInputTextCallbackDataInsertBytes(data.handle, C.int(offset), bytesPtr, C.int(byteCount))
+	}
+}
+
+// CursorPos returns the byte-offset of the cursor within the buffer.
+// Only valid during [Completion,History,Always] callbacks.
+func (data InputTextCallbackData) CursorPos() int {
+	return int(C.iggInputTextCallbackDataGetCursorPos(data.handle))
+}
+
+// SetCursorPos changes the current byte-offset of the cursor within the buffer.
+// Only valid during [Completion,History,Always] callbacks.
+func (data InputTextCallbackData) SetCursorPos(value int) {
+	C.iggInputTextCallbackDataSetCursorPos(data.handle, C.int(value))
+}
+
+// SelectionStart returns the byte-offset of the selection start within the buffer.
+// Only valid during [Completion,History,Always] callbacks.
+func (data InputTextCallbackData) SelectionStart() int {
+	return int(C.iggInputTextCallbackDataGetSelectionStart(data.handle))
+}
+
+// SetSelectionStart changes the current byte-offset of the selection start within the buffer.
+// Only valid during [Completion,History,Always] callbacks.
+func (data InputTextCallbackData) SetSelectionStart(value int) {
+	C.iggInputTextCallbackDataSetSelectionStart(data.handle, C.int(value))
+}
+
+// SelectionEnd returns the byte-offset of the selection end within the buffer.
+// Only valid during [Completion,History,Always] callbacks.
+func (data InputTextCallbackData) SelectionEnd() int {
+	return int(C.iggInputTextCallbackDataGetSelectionEnd(data.handle))
+}
+
+// SetSelectionEnd changes the current byte-offset of the selection end within the buffer.
+// Only valid during [Completion,History,Always] callbacks.
+func (data InputTextCallbackData) SetSelectionEnd(value int) {
+	C.iggInputTextCallbackDataSetSelectionEnd(data.handle, C.int(value))
+}

+ 113 - 0
vendor/github.com/AllenDang/imgui-go/InputTextCallbackDataWrapper.cpp

@@ -0,0 +1,113 @@
+#include "imguiWrappedHeader.h"
+#include "InputTextCallbackDataWrapper.h"
+
+int iggInputTextCallbackDataGetEventFlag(IggInputTextCallbackData handle)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   return data->EventFlag;
+}
+
+int iggInputTextCallbackDataGetFlags(IggInputTextCallbackData handle)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   return data->Flags;
+}
+
+unsigned short iggInputTextCallbackDataGetEventChar(IggInputTextCallbackData handle)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   return data->EventChar;
+}
+
+void iggInputTextCallbackDataSetEventChar(IggInputTextCallbackData handle, unsigned short value)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   data->EventChar = value;
+}
+
+int iggInputTextCallbackDataGetEventKey(IggInputTextCallbackData handle)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   return data->EventKey;
+}
+
+char *iggInputTextCallbackDataGetBuf(IggInputTextCallbackData handle)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   return data->Buf;
+}
+
+void iggInputTextCallbackDataSetBuf(IggInputTextCallbackData handle, char *buf, int size, int textLen)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   data->Buf = buf;
+   data->BufSize = size;
+   data->BufTextLen = textLen;
+   data->BufDirty = true;
+}
+
+void iggInputTextCallbackDataMarkBufferModified(IggInputTextCallbackData handle)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   data->BufDirty = true;
+}
+
+int iggInputTextCallbackDataGetBufSize(IggInputTextCallbackData handle)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   return data->BufSize;
+}
+
+int iggInputTextCallbackDataGetBufTextLen(IggInputTextCallbackData handle)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   return data->BufTextLen;
+}
+
+void iggInputTextCallbackDataDeleteBytes(IggInputTextCallbackData handle, int offset, int count)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   data->DeleteChars(offset, count);
+}
+
+void iggInputTextCallbackDataInsertBytes(IggInputTextCallbackData handle, int offset, char *bytes, int count)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   data->InsertChars(offset, bytes, bytes+count);
+}
+
+int iggInputTextCallbackDataGetCursorPos(IggInputTextCallbackData handle)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   return data->CursorPos;
+}
+
+void iggInputTextCallbackDataSetCursorPos(IggInputTextCallbackData handle, int value)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   data->CursorPos = value;
+}
+
+int iggInputTextCallbackDataGetSelectionStart(IggInputTextCallbackData handle)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   return data->SelectionStart;
+}
+
+void iggInputTextCallbackDataSetSelectionStart(IggInputTextCallbackData handle, int value)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   data->SelectionStart = value;
+}
+
+int iggInputTextCallbackDataGetSelectionEnd(IggInputTextCallbackData handle)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   return data->SelectionEnd;
+}
+
+void iggInputTextCallbackDataSetSelectionEnd(IggInputTextCallbackData handle, int value)
+{
+   ImGuiInputTextCallbackData *data = reinterpret_cast<ImGuiInputTextCallbackData *>(handle);
+   data->SelectionEnd = value;
+}

+ 34 - 0
vendor/github.com/AllenDang/imgui-go/InputTextCallbackDataWrapper.h

@@ -0,0 +1,34 @@
+#pragma once
+
+#include "imguiWrapperTypes.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+extern int iggInputTextCallbackDataGetEventFlag(IggInputTextCallbackData handle);
+extern int iggInputTextCallbackDataGetFlags(IggInputTextCallbackData handle);
+
+extern unsigned short iggInputTextCallbackDataGetEventChar(IggInputTextCallbackData handle);
+extern void iggInputTextCallbackDataSetEventChar(IggInputTextCallbackData handle, unsigned short value);
+extern int iggInputTextCallbackDataGetEventKey(IggInputTextCallbackData handle);
+
+extern char *iggInputTextCallbackDataGetBuf(IggInputTextCallbackData handle);
+extern void iggInputTextCallbackDataSetBuf(IggInputTextCallbackData handle, char *buf, int size, int textLen);
+extern void iggInputTextCallbackDataMarkBufferModified(IggInputTextCallbackData handle);
+extern int iggInputTextCallbackDataGetBufSize(IggInputTextCallbackData handle);
+extern int iggInputTextCallbackDataGetBufTextLen(IggInputTextCallbackData handle);
+extern void iggInputTextCallbackDataDeleteBytes(IggInputTextCallbackData handle, int offset, int count);
+extern void iggInputTextCallbackDataInsertBytes(IggInputTextCallbackData handle, int offset, char *bytes, int count);
+
+extern int iggInputTextCallbackDataGetCursorPos(IggInputTextCallbackData handle);
+extern void iggInputTextCallbackDataSetCursorPos(IggInputTextCallbackData handle, int value);
+extern int iggInputTextCallbackDataGetSelectionStart(IggInputTextCallbackData handle);
+extern void iggInputTextCallbackDataSetSelectionStart(IggInputTextCallbackData handle, int value);
+extern int iggInputTextCallbackDataGetSelectionEnd(IggInputTextCallbackData handle);
+extern void iggInputTextCallbackDataSetSelectionEnd(IggInputTextCallbackData handle, int value);
+
+#ifdef __cplusplus
+}
+#endif

+ 28 - 0
vendor/github.com/AllenDang/imgui-go/Keys.go

@@ -0,0 +1,28 @@
+package imgui
+
+// Constants to fill IO.KeyMap() lookup with indices into the IO.KeysDown[512] array.
+// The mapped indices are then the ones reported to IO.KeyPress() and IO.KeyRelease().
+const (
+	KeyTab         = 0
+	KeyLeftArrow   = 1
+	KeyRightArrow  = 2
+	KeyUpArrow     = 3
+	KeyDownArrow   = 4
+	KeyPageUp      = 5
+	KeyPageDown    = 6
+	KeyHome        = 7
+	KeyEnd         = 8
+	KeyInsert      = 9
+	KeyDelete      = 10
+	KeyBackspace   = 11
+	KeySpace       = 12
+	KeyEnter       = 13
+	KeyEscape      = 14
+	KeyKeyPadEnter = 15
+	KeyA           = 16 // for text edit CTRL+A: select all
+	KeyC           = 17 // for text edit CTRL+C: copy
+	KeyV           = 18 // for text edit CTRL+V: paste
+	KeyX           = 19 // for text edit CTRL+X: cut
+	KeyY           = 20 // for text edit CTRL+Y: redo
+	KeyZ           = 21 // for text edit CTRL+Z: undo
+)

+ 21 - 0
vendor/github.com/AllenDang/imgui-go/LICENSE.txt

@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2014-2021 Omar Cornut
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 38 - 0
vendor/github.com/AllenDang/imgui-go/ListClipper.cpp

@@ -0,0 +1,38 @@
+#include "ListClipper.h"
+#include "WrapperConverter.h"
+#include "imguiWrappedHeader.h"
+
+IggListClipper iggNewListClipper() {
+  ImGuiListClipper *clipper = new ImGuiListClipper();
+  return static_cast<IggListClipper>(clipper);
+}
+
+int iggListClipperDisplayStart(IggListClipper handle) {
+  ImGuiListClipper *clipper = reinterpret_cast<ImGuiListClipper *>(handle);
+  return clipper->DisplayStart;
+}
+
+int iggListClipperDisplayEnd(IggListClipper handle) {
+  ImGuiListClipper *clipper = reinterpret_cast<ImGuiListClipper *>(handle);
+  return clipper->DisplayEnd;
+}
+
+void iggListClipperDelete(IggListClipper handle) {
+  ImGuiListClipper *clipper = reinterpret_cast<ImGuiListClipper *>(handle);
+  delete clipper;
+}
+
+IggBool iggListClipperStep(IggListClipper handle) {
+  ImGuiListClipper *clipper = reinterpret_cast<ImGuiListClipper *>(handle);
+  return clipper->Step();
+}
+
+void iggListClipperBegin(IggListClipper handle, int items_count, float items_height) {
+  ImGuiListClipper *clipper = reinterpret_cast<ImGuiListClipper *>(handle);
+  clipper->Begin(items_count, items_height);
+}
+
+void iggListClipperEnd(IggListClipper handle) {
+  ImGuiListClipper *clipper = reinterpret_cast<ImGuiListClipper *>(handle);
+  clipper->End();
+}

+ 82 - 0
vendor/github.com/AllenDang/imgui-go/ListClipper.go

@@ -0,0 +1,82 @@
+package imgui
+
+// #include "ListClipper.h"
+// #include "imguiWrapper.h"
+import "C"
+
+// ListClipper is a helper to manually clip large list of items.
+// If you are submitting lots of evenly spaced items and you have a random access to the list,
+// you can perform coarse clipping based on visibility to save yourself from processing those items at all.
+// The clipper calculates the range of visible items and advance the cursor to compensate for
+// the non-visible items we have skipped.
+// ImGui already clips items based on their bounds but it needs to measure text size to do so.
+// Coarse clipping before submission makes this cost and your own data fetching/submission cost null.
+//
+// Usage
+//  var clipper imgui.ListClipper
+//  clipper.Begin(1000)  // we have 1000 elements, evenly spaced.
+//  for clipper.Step()
+//      for i := clipper.DisplayStart; i < clipper.DisplayEnd; i++
+//          imgui.Text(fmt.Sprintf("line number %d", i))
+//
+// Step 0: the clipper let you process the first element, regardless of it being visible or not,
+// so it can measure the element height (step skipped if user passed a known height at begin).
+//
+// Step 1: the clipper infers height from first element, calculates the actual range of elements to display,
+// and positions the cursor before the first element.
+//
+// Step 2: dummy step only required if an explicit itemsHeight was passed to Begin() and user call Step().
+// Does nothing and switch to Step 3.
+//
+// Step 3: the clipper validates that we have reached the expected Y position (corresponding to element DisplayEnd),
+// advance the cursor to the end of the list and then returns 'false' to end the loop.
+type ListClipper uintptr
+
+func NewListClipper() ListClipper {
+	listClipper := C.iggNewListClipper()
+	return ListClipper(listClipper)
+}
+
+func (c ListClipper) handle() C.IggListClipper {
+	return C.IggListClipper(c)
+}
+
+func (c ListClipper) DisplayStart() int {
+	return int(C.iggListClipperDisplayStart(c.handle()))
+}
+
+func (c ListClipper) DisplayEnd() int {
+	return int(C.iggListClipperDisplayEnd(c.handle()))
+}
+
+// Step must be called in a loop until it returns false.
+// The DisplayStart/DisplayEnd fields will be set and you can process/draw those items.
+func (c *ListClipper) Step() bool {
+	return C.iggListClipperStep(c.handle()) != 0
+}
+
+// Begin calls BeginV(itemsCount, -1.0) .
+func (c *ListClipper) Begin(itemsCount int) {
+	c.BeginV(itemsCount, -1)
+}
+
+// BeginV must be called before stepping.
+// Use an itemCount of math.MaxInt if you don't know how many items you have.
+// In this case the cursor won't be advanced in the final step.
+//
+// For itemsHeight, use -1.0 to be calculated automatically on first step.
+// Otherwise pass in the distance between your items, typically
+// GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing().
+func (c *ListClipper) BeginV(itemsCount int, itemsHeight float32) {
+	C.iggListClipperBegin(c.handle(), C.int(itemsCount), C.float(itemsHeight))
+}
+
+// End resets the clipper. This function is automatically called on the last call of Step() that returns false.
+func (c *ListClipper) End() {
+	C.iggListClipperEnd(c.handle())
+}
+
+// Delete removes the list clipper from memory.
+func (c *ListClipper) Delete() {
+	C.iggListClipperDelete(c.handle())
+}

+ 21 - 0
vendor/github.com/AllenDang/imgui-go/ListClipper.h

@@ -0,0 +1,21 @@
+#pragma once
+
+#include "imguiWrapperTypes.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern IggListClipper iggNewListClipper();
+
+extern int iggListClipperDisplayStart(IggListClipper handle);
+extern int iggListClipperDisplayEnd(IggListClipper handle);
+
+extern void iggListClipperDelete(IggListClipper handle);
+extern IggBool iggListClipperStep(IggListClipper handle);
+extern void iggListClipperBegin(IggListClipper handle, int items_count, float items_height);
+extern void iggListClipperEnd(IggListClipper handle);
+
+#ifdef __cplusplus
+}
+#endif

+ 25 - 0
vendor/github.com/AllenDang/imgui-go/MouseCursorFlags.go

@@ -0,0 +1,25 @@
+package imgui
+
+// Enumeration for MouseCursor()
+// User code may request binding to display given cursor by calling SetMouseCursor(), which is why we have some cursors that are marked unused here
+const (
+	// MouseCursorNone no mouse cursor
+	MouseCursorNone = -1
+	// MouseCursorArrow standard arrow mouse cursor
+	MouseCursorArrow = 0
+	// MouseCursorTextInput when hovering over InputText, etc.
+	MouseCursorTextInput = 1
+	// MouseCursorResizeAll (Unused by imgui functions)
+	MouseCursorResizeAll = 2
+	// MouseCursorResizeNS when hovering over an horizontal border
+	MouseCursorResizeNS = 3
+	// MouseCursorResizeEW when hovering over a vertical border or a column
+	MouseCursorResizeEW = 4
+	// MouseCursorResizeNESW when hovering over the bottom-left corner of a window
+	MouseCursorResizeNESW = 5
+	// MouseCursorResizeNWSE when hovering over the bottom-right corner of a window
+	MouseCursorResizeNWSE = 6
+	// MouseCursorHand (Unused by imgui functions. Use for e.g. hyperlinks)
+	MouseCursorHand  = 7
+	MouseCursorCount = 8
+)

+ 522 - 0
vendor/github.com/AllenDang/imgui-go/PlatformGlfw.go

@@ -0,0 +1,522 @@
+package imgui
+
+import (
+	"fmt"
+	"image"
+	"math"
+	"runtime"
+
+	"github.com/go-gl/glfw/v3.3/glfw"
+)
+
+var GlfwDontCare int = glfw.DontCare
+
+type GLFWClipboard struct {
+	window *glfw.Window
+}
+
+func NewGLFWClipboard(w *glfw.Window) *GLFWClipboard {
+	return &GLFWClipboard{window: w}
+}
+
+func (c *GLFWClipboard) Text() (string, error) {
+	return c.window.GetClipboardString(), nil
+}
+
+func (c *GLFWClipboard) SetText(text string) {
+	c.window.SetClipboardString(text)
+}
+
+type GLFWWindowFlags uint8
+
+const (
+	GLFWWindowFlagsNotResizable GLFWWindowFlags = 1 << iota
+	GLFWWindowFlagsMaximized
+	GLFWWindowFlagsFloating
+	GLFWWindowFlagsFrameless
+	GLFWWindowFlagsTransparent
+)
+
+// GLFW implements a platform based on github.com/go-gl/glfw (v3.3).
+type GLFW struct {
+	imguiIO IO
+
+	window *glfw.Window
+
+	tps              int
+	time             float64
+	mouseJustPressed [3]bool
+
+	mouseCursors map[int]*glfw.Cursor
+
+	posChangeCallback  func(int, int)
+	sizeChangeCallback func(int, int)
+	dropCallback       func([]string)
+	inputCallback      func(key glfw.Key, mods glfw.ModifierKey, action glfw.Action)
+	closeCallback      func() bool
+}
+
+// NewGLFW attempts to initialize a GLFW context.
+func NewGLFW(io IO, title string, width, height int, flags GLFWWindowFlags) (*GLFW, error) {
+	runtime.LockOSThread()
+
+	err := glfw.Init()
+	if err != nil {
+		return nil, fmt.Errorf("failed to initialize glfw: %v", err)
+	}
+
+	glfw.WindowHint(glfw.ContextVersionMajor, 3)
+	glfw.WindowHint(glfw.ContextVersionMinor, 3)
+	glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
+	glfw.WindowHint(glfw.OpenGLForwardCompatible, 1)
+	glfw.WindowHint(glfw.ScaleToMonitor, glfw.True)
+	glfw.WindowHint(glfw.Visible, glfw.False)
+
+	if flags&GLFWWindowFlagsNotResizable != 0 {
+		glfw.WindowHint(glfw.Resizable, glfw.False)
+	}
+
+	if flags&GLFWWindowFlagsMaximized != 0 {
+		glfw.WindowHint(glfw.Maximized, glfw.True)
+	}
+
+	if flags&GLFWWindowFlagsFloating != 0 {
+		glfw.WindowHint(glfw.Floating, glfw.True)
+	}
+
+	if flags&GLFWWindowFlagsFrameless != 0 {
+		glfw.WindowHint(glfw.Decorated, glfw.False)
+	}
+
+	if flags&GLFWWindowFlagsTransparent != 0 {
+		glfw.WindowHint(glfw.TransparentFramebuffer, glfw.True)
+	}
+
+	window, err := glfw.CreateWindow(width, height, title, nil, nil)
+	if err != nil {
+		glfw.Terminate()
+		return nil, fmt.Errorf("failed to create window: %v", err)
+	}
+	window.MakeContextCurrent()
+	glfw.SwapInterval(1)
+
+	platform := &GLFW{
+		imguiIO: io,
+		window:  window,
+
+		tps: 60,
+	}
+	platform.setKeyMapping()
+	platform.installCallbacks()
+
+	// Create mosue cursors
+	platform.mouseCursors = make(map[int]*glfw.Cursor)
+	platform.mouseCursors[MouseCursorArrow] = glfw.CreateStandardCursor(glfw.ArrowCursor)
+	platform.mouseCursors[MouseCursorTextInput] = glfw.CreateStandardCursor(glfw.IBeamCursor)
+	platform.mouseCursors[MouseCursorResizeAll] = glfw.CreateStandardCursor(glfw.CrosshairCursor)
+	platform.mouseCursors[MouseCursorHand] = glfw.CreateStandardCursor(glfw.HandCursor)
+	platform.mouseCursors[MouseCursorResizeEW] = glfw.CreateStandardCursor(glfw.HResizeCursor)
+	platform.mouseCursors[MouseCursorResizeNS] = glfw.CreateStandardCursor(glfw.VResizeCursor)
+
+	io.SetClipboard(NewGLFWClipboard(window))
+
+	if flags&GLFWWindowFlagsMaximized == 0 {
+		// Center window to monitor
+		platform.centerWindow()
+	}
+
+	platform.window.Show()
+
+	return platform, nil
+}
+
+// Dispose cleans up the resources.
+func (platform *GLFW) Dispose() {
+	platform.window.Destroy()
+	glfw.Terminate()
+}
+
+func (platform *GLFW) GetContentScale() float32 {
+	x, _ := platform.window.GetContentScale()
+
+	// Do not scale on MacOS
+	if runtime.GOOS == "darwin" {
+		x = 1
+	}
+
+	return x
+}
+
+func (platform *GLFW) GetWindow() *glfw.Window {
+	return platform.window
+}
+
+func (platform *GLFW) GetPos() (x, y int) {
+	return platform.window.GetPos()
+}
+
+func (platform *GLFW) centerWindow() {
+	monitor := platform.getBestMonitor()
+	if monitor == nil {
+		return
+	}
+
+	mode := monitor.GetVideoMode()
+	if mode == nil {
+		return
+	}
+
+	monitorX, monitorY := monitor.GetPos()
+	windowWidth, windowHeight := platform.window.GetSize()
+
+	platform.window.SetPos(monitorX+(mode.Width-windowWidth)/2, monitorY+(mode.Height-windowHeight)/2)
+}
+
+func (platform *GLFW) getBestMonitor() *glfw.Monitor {
+	monitors := glfw.GetMonitors()
+
+	if len(monitors) == 0 {
+		return nil
+	}
+
+	width, height := platform.window.GetSize()
+	x, y := platform.window.GetPos()
+
+	var bestMonitor *glfw.Monitor
+	var bestArea int
+
+	for _, m := range monitors {
+		monitorX, monitorY := m.GetPos()
+		mode := m.GetVideoMode()
+		if mode == nil {
+			continue
+		}
+
+		areaMinX := int(math.Max(float64(x), float64(monitorX)))
+		areaMinY := int(math.Max(float64(y), float64(monitorY)))
+
+		areaMaxX := int(math.Min(float64(x+width), float64(monitorX+mode.Width)))
+		areaMaxY := int(math.Min(float64(y+height), float64(monitorY+mode.Height)))
+
+		area := (areaMaxX - areaMinX) * (areaMaxY - areaMinY)
+
+		if area > bestArea {
+			bestArea = area
+			bestMonitor = m
+		}
+	}
+
+	return bestMonitor
+}
+
+// ShouldStop returns true if the window is to be closed.
+func (platform *GLFW) ShouldStop() bool {
+	return platform.window.ShouldClose()
+}
+
+// SetShouldStop sets whether window should be closed
+func (platform *GLFW) SetShouldStop(v bool) {
+	platform.window.SetShouldClose(v)
+}
+
+func (platform *GLFW) WaitForEvent() {
+	if platform.imguiIO.GetConfigFlags()&ConfigFlagEnablePowerSavingMode == 0 {
+		return
+	}
+
+	windowIsHidden := platform.window.GetAttrib(glfw.Visible) == glfw.False || platform.window.GetAttrib(glfw.Iconified) == glfw.True
+
+	waitingTime := math.Inf(0)
+
+	if !windowIsHidden {
+		waitingTime = GetEventWaitingTime()
+	}
+
+	if waitingTime > 0 {
+		if math.IsInf(waitingTime, 0) {
+			glfw.WaitEvents()
+		} else {
+			glfw.WaitEventsTimeout(waitingTime)
+		}
+	}
+}
+
+// ProcessEvents handles all pending window events.
+func (platform *GLFW) ProcessEvents() {
+	platform.WaitForEvent()
+	glfw.PollEvents()
+}
+
+// DisplaySize returns the dimension of the display.
+func (platform *GLFW) DisplaySize() [2]float32 {
+	w, h := platform.window.GetSize()
+	return [2]float32{float32(w), float32(h)}
+}
+
+// FramebufferSize returns the dimension of the framebuffer.
+func (platform *GLFW) FramebufferSize() [2]float32 {
+	w, h := platform.window.GetFramebufferSize()
+	return [2]float32{float32(w), float32(h)}
+}
+
+// NewFrame marks the begin of a render pass. It forwards all current state to imgui IO.
+func (platform *GLFW) NewFrame() {
+	// Setup display size (every frame to accommodate for window resizing)
+	displaySize := platform.DisplaySize()
+	platform.imguiIO.SetDisplaySize(Vec2{X: displaySize[0], Y: displaySize[1]})
+
+	// Setup time step
+	currentTime := glfw.GetTime()
+	if platform.time > 0 {
+		platform.imguiIO.SetDeltaTime(float32(currentTime - platform.time))
+	}
+	platform.time = currentTime
+
+	// Setup inputs
+	if platform.window.GetAttrib(glfw.Focused) != 0 {
+		x, y := platform.window.GetCursorPos()
+		platform.imguiIO.SetMousePosition(Vec2{X: float32(x), Y: float32(y)})
+	} else {
+		platform.imguiIO.SetMousePosition(Vec2{X: -math.MaxFloat32, Y: -math.MaxFloat32})
+	}
+
+	for i := 0; i < len(platform.mouseJustPressed); i++ {
+		down := platform.mouseJustPressed[i] || (platform.window.GetMouseButton(glfwButtonIDByIndex[i]) == glfw.Press)
+		platform.imguiIO.SetMouseButtonDown(i, down)
+		platform.mouseJustPressed[i] = false
+	}
+
+	platform.updateMouseCursor()
+}
+
+// PostRender performs a buffer swap.
+func (platform *GLFW) PostRender() {
+	platform.window.SwapBuffers()
+}
+
+func (platform *GLFW) SetPosChangeCallback(cb func(int, int)) {
+	platform.posChangeCallback = cb
+}
+
+func (platform *GLFW) SetSizeChangeCallback(cb func(int, int)) {
+	platform.sizeChangeCallback = cb
+}
+
+func (platform *GLFW) Update() {
+	glfw.PostEmptyEvent()
+}
+
+func (platform *GLFW) SetDropCallback(cb func(names []string)) {
+	platform.dropCallback = cb
+}
+
+func (platform *GLFW) SetInputCallback(cb func(key glfw.Key, mods glfw.ModifierKey, action glfw.Action)) {
+	platform.inputCallback = cb
+}
+
+func (platform *GLFW) SetCloseCallback(cb func() bool) {
+	platform.closeCallback = cb
+}
+
+func (platform *GLFW) updateMouseCursor() {
+	io := platform.imguiIO
+	if (io.GetConfigFlags()&ConfigFlagNoMouseCursorChange) == 1 || platform.window.GetInputMode(glfw.CursorMode) == glfw.CursorDisabled {
+		return
+	}
+
+	cursor := MouseCursor()
+	if cursor == MouseCursorNone || io.GetMouseDrawCursor() {
+		platform.window.SetInputMode(glfw.CursorMode, glfw.CursorHidden)
+	} else {
+		gCursor := platform.mouseCursors[MouseCursorArrow]
+		if c, ok := platform.mouseCursors[cursor]; ok {
+			gCursor = c
+		}
+		platform.window.SetCursor(gCursor)
+		platform.window.SetInputMode(glfw.CursorMode, glfw.CursorNormal)
+	}
+}
+
+func (platform *GLFW) setKeyMapping() {
+	// Keyboard mapping. ImGui will use those indices to peek into the io.KeysDown[] array.
+	platform.imguiIO.KeyMap(KeyTab, int(glfw.KeyTab))
+	platform.imguiIO.KeyMap(KeyLeftArrow, int(glfw.KeyLeft))
+	platform.imguiIO.KeyMap(KeyRightArrow, int(glfw.KeyRight))
+	platform.imguiIO.KeyMap(KeyUpArrow, int(glfw.KeyUp))
+	platform.imguiIO.KeyMap(KeyDownArrow, int(glfw.KeyDown))
+	platform.imguiIO.KeyMap(KeyPageUp, int(glfw.KeyPageUp))
+	platform.imguiIO.KeyMap(KeyPageDown, int(glfw.KeyPageDown))
+	platform.imguiIO.KeyMap(KeyHome, int(glfw.KeyHome))
+	platform.imguiIO.KeyMap(KeyEnd, int(glfw.KeyEnd))
+	platform.imguiIO.KeyMap(KeyInsert, int(glfw.KeyInsert))
+	platform.imguiIO.KeyMap(KeyDelete, int(glfw.KeyDelete))
+	platform.imguiIO.KeyMap(KeyBackspace, int(glfw.KeyBackspace))
+	platform.imguiIO.KeyMap(KeySpace, int(glfw.KeySpace))
+	platform.imguiIO.KeyMap(KeyEnter, int(glfw.KeyEnter))
+	platform.imguiIO.KeyMap(KeyEscape, int(glfw.KeyEscape))
+	platform.imguiIO.KeyMap(KeyA, int(glfw.KeyA))
+	platform.imguiIO.KeyMap(KeyC, int(glfw.KeyC))
+	platform.imguiIO.KeyMap(KeyV, int(glfw.KeyV))
+	platform.imguiIO.KeyMap(KeyX, int(glfw.KeyX))
+	platform.imguiIO.KeyMap(KeyY, int(glfw.KeyY))
+	platform.imguiIO.KeyMap(KeyZ, int(glfw.KeyZ))
+}
+
+func (platform *GLFW) installCallbacks() {
+	platform.window.SetMouseButtonCallback(platform.mouseButtonChange)
+	platform.window.SetScrollCallback(platform.mouseScrollChange)
+	platform.window.SetKeyCallback(platform.keyChange)
+	platform.window.SetCharCallback(platform.charChange)
+	platform.window.SetSizeCallback(platform.sizeChange)
+	platform.window.SetDropCallback(platform.onDrop)
+	platform.window.SetPosCallback(platform.posChange)
+	platform.window.SetCloseCallback(platform.onClose)
+	platform.window.SetFocusCallback(platform.onFocus)
+}
+
+var glfwButtonIndexByID = map[glfw.MouseButton]int{
+	glfw.MouseButton1: 0,
+	glfw.MouseButton2: 1,
+	glfw.MouseButton3: 2,
+}
+
+var glfwButtonIDByIndex = map[int]glfw.MouseButton{
+	0: glfw.MouseButton1,
+	1: glfw.MouseButton2,
+	2: glfw.MouseButton3,
+}
+
+func (platform *GLFW) onFocus(window *glfw.Window, focused bool) {
+	platform.imguiIO.AddFocusEvent(focused)
+}
+
+func (platform *GLFW) onClose(window *glfw.Window) {
+	if platform.closeCallback != nil {
+		shouldClose := platform.closeCallback()
+		window.SetShouldClose(shouldClose)
+	}
+}
+
+func (platform *GLFW) onDrop(window *glfw.Window, names []string) {
+	window.Focus()
+
+	if platform.dropCallback != nil {
+		platform.dropCallback(names)
+	}
+}
+
+func (platform *GLFW) posChange(window *glfw.Window, x, y int) {
+	platform.imguiIO.SetFrameCountSinceLastInput(0)
+
+	// Notfy pos changed and redraw.
+	if platform.posChangeCallback != nil {
+		platform.posChangeCallback(x, y)
+	}
+}
+
+func (platform *GLFW) sizeChange(window *glfw.Window, width, height int) {
+	platform.imguiIO.SetFrameCountSinceLastInput(0)
+
+	// Notify size changed and redraw.
+	if platform.sizeChangeCallback != nil {
+		platform.sizeChangeCallback(width, height)
+	}
+}
+
+func (platform *GLFW) mouseButtonChange(window *glfw.Window, rawButton glfw.MouseButton, action glfw.Action, mods glfw.ModifierKey) {
+	platform.imguiIO.SetFrameCountSinceLastInput(0)
+
+	buttonIndex, known := glfwButtonIndexByID[rawButton]
+
+	if known && (action == glfw.Press) {
+		platform.mouseJustPressed[buttonIndex] = true
+	}
+}
+
+func (platform *GLFW) mouseScrollChange(window *glfw.Window, x, y float64) {
+	platform.imguiIO.SetFrameCountSinceLastInput(0)
+	platform.imguiIO.AddMouseWheelDelta(float32(x), float32(y))
+}
+
+func (platform *GLFW) keyChange(window *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
+	platform.imguiIO.SetFrameCountSinceLastInput(0)
+
+	if action == glfw.Press {
+		platform.imguiIO.KeyPress(int(key))
+	}
+	if action == glfw.Release {
+		platform.imguiIO.KeyRelease(int(key))
+	}
+
+	// Modifiers are not reliable across systems
+	platform.imguiIO.KeyCtrl(int(glfw.KeyLeftControl), int(glfw.KeyRightControl))
+	platform.imguiIO.KeyShift(int(glfw.KeyLeftShift), int(glfw.KeyRightShift))
+	platform.imguiIO.KeyAlt(int(glfw.KeyLeftAlt), int(glfw.KeyRightAlt))
+	platform.imguiIO.KeySuper(int(glfw.KeyLeftSuper), int(glfw.KeyRightSuper))
+
+	if platform.inputCallback != nil {
+		platform.inputCallback(key, mods, action)
+	}
+}
+
+func (platform *GLFW) charChange(window *glfw.Window, char rune) {
+	platform.imguiIO.SetFrameCountSinceLastInput(0)
+	platform.imguiIO.AddInputCharacters(string(char))
+}
+
+func (platform *GLFW) GetClipboard() string {
+	return platform.window.GetClipboardString()
+}
+
+func (platform *GLFW) SetClipboard(content string) {
+	platform.window.SetClipboardString(content)
+}
+
+func (platform *GLFW) GetTPS() int {
+	return platform.tps
+}
+
+func (platform *GLFW) SetTPS(tps int) {
+	platform.tps = tps
+}
+
+// SetIcon sets the icon of the specified window. If passed an array of candidate images,
+// those of or closest to the sizes desired by the system are selected. If no images are
+// specified, the window reverts to its default icon.
+//
+// The image is ideally provided in the form of *image.NRGBA.
+// The pixels are 32-bit, little-endian, non-premultiplied RGBA, i.e. eight
+// bits per channel with the red channel first. They are arranged canonically
+// as packed sequential rows, starting from the top-left corner. If the image
+// type is not *image.NRGBA, it will be converted to it.
+//
+// The desired image sizes varies depending on platform and system settings. The selected
+// images will be rescaled as needed. Good sizes include 16x16, 32x32 and 48x48.
+func (platform *GLFW) SetIcon(icons []image.Image) {
+	platform.window.SetIcon(icons)
+}
+
+// SetSizeLimits sets the size limits of the client area of the specified window.
+// If the window is full screen or not resizable, this function does nothing.
+//
+// The size limits are applied immediately and may cause the window to be resized.
+// To specify only a minimum size or only a maximum one, set the other pair to GLFW_DONT_CARE.
+// To disable size limits for a window, set them all to GLFW_DONT_CARE.
+func (platform *GLFW) SetSizeLimits(minw, minh, maxw, maxh int) {
+	platform.window.SetSizeLimits(minw, minh, maxw, maxh)
+}
+
+// SetTitle sets the title of window.
+func (platform *GLFW) SetTitle(title string) {
+	platform.window.SetTitle(title)
+}
+
+// IsMinimized checks whether window is minimized.
+func (platform *GLFW) IsMinimized() bool {
+	return glfw.True == platform.window.GetAttrib(glfw.Iconified)
+}
+
+// IsVisible checks whether window is visible.
+func (platform *GLFW) IsVisible() bool {
+	return glfw.True == platform.window.GetAttrib(glfw.Visible)
+}

+ 84 - 0
vendor/github.com/AllenDang/imgui-go/PlatformInterface.go

@@ -0,0 +1,84 @@
+package imgui
+
+import (
+	"image"
+
+	"github.com/go-gl/glfw/v3.3/glfw"
+)
+
+type Platform interface {
+	// ShouldStop is regularly called as the abort condition for the program loop.
+	ShouldStop() bool
+
+	// SetShouldStop sets whether window should be closed
+	SetShouldStop(bool)
+
+	// ProcessEvents is called once per render loop to dispatch any pending events.
+	ProcessEvents()
+
+	// DisplaySize returns the dimension of the display.
+	DisplaySize() [2]float32
+
+	// FramebufferSize returns the dimension of the framebuffer.
+	FramebufferSize() [2]float32
+
+	// NewFrame marks the begin of a render pass. It must update the imgui IO state according to user input (mouse, keyboard, ...)
+	NewFrame()
+
+	// PostRender marks the completion of one render pass. Typically this causes the display buffer to be swapped.
+	PostRender()
+
+	// Dispose
+	Dispose()
+
+	// Set size change callback
+	SetSizeChangeCallback(func(width, height int))
+
+	// Set pos change callback
+	SetPosChangeCallback(func(x, y int))
+
+	// Set drop callback
+	SetDropCallback(func(names []string))
+
+	// Set input callback
+	SetInputCallback(func(key glfw.Key, mods glfw.ModifierKey, action glfw.Action))
+
+	// Set close callback, returned value will be used to close or cancel the window
+	SetCloseCallback(func() bool)
+
+	// Force Update
+	Update()
+
+	// Get content from system clipboard
+	GetClipboard() string
+
+	// Set content to system clipboard
+	SetClipboard(content string)
+
+	// Get the event pulling ticks per second
+	GetTPS() int
+
+	// Set the event pulling ticks per second
+	SetTPS(tps int)
+
+	// Set icon to master window
+	SetIcon(icons []image.Image)
+
+	// SetSizeLimits sets the size limits of the client area of the specified window.
+	SetSizeLimits(minw, minh, maxw, maxh int)
+
+	// SetTitle sets the title of platform window.
+	SetTitle(title string)
+
+	// Get window position
+	GetPos() (x, y int)
+
+	// Get DPI scale factor
+	GetContentScale() float32
+
+	// Check whehter window is minimized
+	IsMinimized() bool
+
+	// Check whether window is visible
+	IsVisible() bool
+}

+ 88 - 0
vendor/github.com/AllenDang/imgui-go/README.md

@@ -0,0 +1,88 @@
+# Dear ImGui for Go
+
+[![Go Doc](https://godoc.org/github.com/inkyblackness/imgui-go?status.svg)](https://godoc.org/github.com/inkyblackness/imgui-go)
+[![Go Report Card](https://goreportcard.com/badge/github.com/inkyblackness/imgui-go)](https://goreportcard.com/report/github.com/inkyblackness/imgui-go)
+[![GolangCI](https://golangci.com/badges/github.com/inkyblackness/imgui-go.svg)](https://golangci.com)
+
+This library is a [Go](https://www.golang.org) wrapper for **[Dear ImGui](https://github.com/ocornut/imgui)**.
+
+This wrapper started as a special-purpose wrapper for use within InkyBlackness.
+However, it is self-contained and can be used for other purposes as well.
+
+This wrapper is
+* hand-crafted, for Go
+* documented
+* versioned
+* with ported examples in a separate repository (see below)
+
+![Screenshot from example](assets/screenshot.png)
+
+## API naming
+
+Names of types and functions follow closely those of **Dear ImGui**.
+
+For functions that have optional parameters, the following schema is applied:
+* There is the "verbose" variant, followed by the letter `V`, such as `ButtonV(id string, size Vec2) bool`
+* Next to it there is the "idiomatic" variant, without any optional parameter, such as `Button(id string) bool`.
+* The idiomatic variant calls the verbose variant with the default values for the optional parameters.
+Functions that don't have optional parameters don't come in a verbose variant.
+
+The **Dear ImGui** functions `IO()` and `Style()` have been renamed to be `CurrentIO()` and `CurrentStyle()`.
+This was done because their returned types have the same name, causing a name clash.
+With the `Current` prefix, they also better describe what they return.  
+
+## API philosophy
+This library does not intend to export all the functions of the wrapped **Dear ImGui**. The following filter applies as a rule of thumb:
+* Functions marked as "obsolete" are not available. (The corresponding C code isn't even compiled - disabled by define)
+* "Shortcut" Functions, which combine language features and/or other **Dear ImGui** functions, are not available. Prime example are the Text*() functions for instance: Text formatting should be done with fmt.Sprintf(), and style formatting with the corresponding Push/Pop functions.
+* Functions that are not needed by InkyBlackness are ignored. This doesn't mean that they can't be in the wrapper, they are simply not a priority. Feel free to propose an implementation or make a pull request, respecting the previous points :)
+
+## Version philosophy
+This library does not mirror the versions of the wrapped **Dear ImGui**. The semantic versioning of this wrapper is defined as:
+* Major changes: (Breaking) changes in API or behaviour. Typically done through changes in **Dear ImGui**.
+* Minor changes: Extensions in API. Typically done through small version increments of **Dear ImGui** and/or exposing further features in a compatible way.
+* Patch changes: Bug fixes - either in the wrapper or the wrapped **Dear ImGui**, given that the API & behaviour remains the same.
+
+At the moment, this library uses version [1.79](https://github.com/ocornut/imgui/releases/tag/v1.79) of **Dear ImGui**.
+
+## Examples
+A separate repository was created to host ported examples and reference implementations.
+See repository [inkyblackness/imgui-go-examples](https://github.com/inkyblackness/imgui-go-examples).
+
+It contains reference implementations for libraries such as [GLFW3](https://github.com/go-gl/glfw) and [SDL2](https://github.com/veandco/go-sdl2), using [OpenGL](https://github.com/go-gl/gl).
+
+The screenshot above was created with such an example.
+
+## Extras
+
+### FreeType font rendering
+
+If the `FreeType` library is available for your platform, you can enable using it with the build tag `imguifreetype` - as in
+```
+go build -tags="imguifreetype"
+```
+This extra is based on the reference implementation from **Dear ImGui**.
+
+This allows you to use the function `FontAtlas.BuildWithFreeType()`. If the build tag is not set, this function will always return an error. 
+
+If you set the build tag, yet the corresponding support has not been added to the library, you will receive a build error.
+Contributions to support more build environments are happily accepted. See files `FreeTypeEnabled*.go`.
+
+## Alternatives
+
+Before this project was created, the following alternatives were considered - and ignored:
+* `kdrag0n/go-imgui` (no longer available). Reasons for dismissal at time of decision:
+  * Auto-generated bloat, which doesn't help
+  * Was using old API (1.5x)
+  * Did not compile
+  * Project appeared to be abandoned
+* [Extrawurst/cimgui](https://github.com/Extrawurst/cimgui). Reasons for dismissal at time of decision:
+  * Was using old API (1.5x), 1.6x was attempted
+  * Apparently semi-exposed the C++ API, especially through the structures
+  * Adding this adds another dependency
+
+
+## License
+
+The project is available under the terms of the **New BSD License** (see LICENSE file).
+The licenses of included sources are stored in the **_licenses** folder.

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio