diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 716a1d41..32446199 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,7 +19,7 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] steps: - name: Checkout out source code - uses: actions/checkout@v2.3.5 + uses: actions/checkout@v3 with: fetch-depth: 0 submodules: 'true' @@ -30,13 +30,13 @@ jobs: sudo apt-get --allow-releaseinfo-change update sudo apt-get install -y libgtk-3-dev libasound2-dev libxxf86vm-dev - name: Set up Go environment - uses: actions/setup-go@v2.2.0 + uses: actions/setup-go@v3 with: - go-version: 1.17.x + go-version: 1.18.x id: go - name: Cache Go modules - uses: actions/cache@v2.1.7 + uses: actions/cache@v3 with: path: ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} diff --git a/.github/workflows/coverage.yaml b/.github/workflows/coverage.yaml index cf9b44e0..2844aeb7 100644 --- a/.github/workflows/coverage.yaml +++ b/.github/workflows/coverage.yaml @@ -10,12 +10,12 @@ jobs: run: | sudo apt-get --allow-releaseinfo-change update sudo apt-get install -y libgtk-3-dev libasound2-dev libxxf86vm-dev - - uses: actions/checkout@v2.3.5 + - uses: actions/checkout@v3 with: fetch-depth: 2 - - uses: actions/setup-go@v2.2.0 + - uses: actions/setup-go@v3 with: - go-version: '1.16' + go-version: '1.18.x' - name: Run coverage run: go test -race -coverprofile=coverage.txt -covermode=atomic - name: Upload coverage to Codecov diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index cff6ac64..19d41cfb 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -13,16 +13,19 @@ jobs: name: lint runs-on: ubuntu-latest steps: + - uses: actions/setup-go@v3 + with: + go-version: '1.18.x' - name: Set up LibGL, Mesa & X11 libraries run: | sudo apt-get --allow-releaseinfo-change update sudo apt-get install -y libgtk-3-dev libasound2-dev libxxf86vm-dev - - uses: actions/checkout@v2.3.5 + - uses: actions/checkout@v3 - name: golangci-lint - uses: golangci/golangci-lint-action@v2.5.2 + uses: golangci/golangci-lint-action@v3 with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version - version: v1.44.0 + version: v1.45 # Optional: working directory, useful for monorepos # working-directory: somedir @@ -33,11 +36,9 @@ jobs: # Optional: show only new issues if it's a pull request. The default value is `false`. # only-new-issues: true - # Optional: if set to true then the action will use pre-installed Go. - # skip-go-installation: true - # Optional: if set to true then the action don't cache or restore ~/go/pkg. # skip-pkg-cache: true # Optional: if set to true then the action don't cache or restore ~/.cache/go-build. + # skip-build-cache: true diff --git a/.gitignore b/.gitignore index 2c148ca8..16914be1 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,9 @@ # vim cache files *.swp +# JetBrains idea configuration +.idea + # Test binary, built with `go test -c` *.test diff --git a/ClickableWidgets.go b/ClickableWidgets.go index ce7c81ca..9fe611aa 100644 --- a/ClickableWidgets.go +++ b/ClickableWidgets.go @@ -32,7 +32,7 @@ func Button(label string) *ButtonWidget { // Buttonf creates button with formated label // NOTE: works like fmt.Sprintf (see `go doc fmt`). -func Buttonf(format string, args ...interface{}) *ButtonWidget { +func Buttonf(format string, args ...any) *ButtonWidget { return Button(fmt.Sprintf(format, args...)) } @@ -123,7 +123,7 @@ func SmallButton(id string) *SmallButtonWidget { // SmallButtonf allows to set formated label for small button. // It calls SmallButton(fmt.Sprintf(label, args...)). -func SmallButtonf(format string, args ...interface{}) *SmallButtonWidget { +func SmallButtonf(format string, args ...any) *SmallButtonWidget { return SmallButton(fmt.Sprintf(format, args...)) } @@ -436,7 +436,7 @@ func Selectable(label string) *SelectableWidget { } // Selectablef creates a selectable widget with formated label. -func Selectablef(format string, args ...interface{}) *SelectableWidget { +func Selectablef(format string, args ...any) *SelectableWidget { return Selectable(fmt.Sprintf(format, args...)) } @@ -511,7 +511,7 @@ func TreeNode(label string) *TreeNodeWidget { } // TreeNodef adds TreeNode with formatted label. -func TreeNodef(format string, args ...interface{}) *TreeNodeWidget { +func TreeNodef(format string, args ...any) *TreeNodeWidget { return TreeNode(fmt.Sprintf(format, args...)) } diff --git a/Context.go b/Context.go index 0d8a3d6f..7880e946 100644 --- a/Context.go +++ b/Context.go @@ -55,7 +55,7 @@ func (c *context) IO() imgui.IO { } func (c *context) invalidAllState() { - c.state.Range(func(k, v interface{}) bool { + c.state.Range(func(k, v any) bool { if s, ok := v.(*state); ok { s.valid = false } @@ -64,7 +64,7 @@ func (c *context) invalidAllState() { } func (c *context) cleanState() { - c.state.Range(func(k, v interface{}) bool { + c.state.Range(func(k, v any) bool { if s, ok := v.(*state); ok { if !s.valid { c.state.Delete(k) @@ -82,7 +82,7 @@ func (c *context) SetState(id string, data Disposable) { c.state.Store(id, &state{valid: true, data: data}) } -func (c *context) GetState(id string) interface{} { +func (c *context) GetState(id string) any { if v, ok := c.state.Load(id); ok { if s, ok := v.(*state); ok { s.valid = true diff --git a/ExtraWidgets.go b/ExtraWidgets.go index eab9075a..03ff248b 100644 --- a/ExtraWidgets.go +++ b/ExtraWidgets.go @@ -347,7 +347,7 @@ func (c *ConditionWidget) Build() { } // RangeBuilder batch create widgets and render only which is visible. -func RangeBuilder(id string, values []interface{}, builder func(int, interface{}) Widget) Layout { +func RangeBuilder(id string, values []any, builder func(int, any) Widget) Layout { var layout Layout layout = append(layout, Custom(func() { imgui.PushID(id) })) diff --git a/FontAtlasProsessor.go b/FontAtlasProsessor.go index 86e8adae..8d05bccb 100644 --- a/FontAtlasProsessor.go +++ b/FontAtlasProsessor.go @@ -40,7 +40,15 @@ func (f *FontInfo) String() string { 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 } @@ -219,7 +227,7 @@ func rebuildFontAtlas() { var sb strings.Builder - stringMap.Range(func(k, v interface{}) bool { + stringMap.Range(func(k, v any) bool { stringMap.Store(k, true) if ks, ok := k.(rune); ok { sb.WriteRune(ks) @@ -285,6 +293,7 @@ func rebuildFontAtlas() { } else { f = fonts.AddFontFromMemoryTTFV(fontInfo.fontByte, fontInfo.size, imgui.DefaultFontConfig, ranges.Data()) } + extraFontMap[fontInfo.String()] = &f } diff --git a/README.md b/README.md index ffef0d46..5e0eadcf 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ Here is the result: ### 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("ID", &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. +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. @@ -144,19 +144,26 @@ Or, install [TDM-GCC](https://jmeubank.github.io/tdm-gcc/). First you need to install the required dependencies: ```bash -# apt install libx11-dev libxcursor-dev libxrandr-dev libxinerama-dev libxi-dev libglx-dev libgl1-mesa-dev libxxf86vm-dev +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 -# dpkg --add-architecture arm64 -# apt update -# apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu \ +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 +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 @@ -173,14 +180,21 @@ go build -ldflags "-s -w" . go build -ldflags "-s -w -H=windowsgui -extldflags=-static" . ``` -### Build Windows version on MacOS. +### 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 diff --git a/SliderWidgets.go b/SliderWidgets.go index 70465a9a..109d5c6a 100644 --- a/SliderWidgets.go +++ b/SliderWidgets.go @@ -60,7 +60,7 @@ func (s *SliderIntWidget) Label(label string) *SliderIntWidget { } // Labelf sets formated label. -func (s *SliderIntWidget) Labelf(format string, args ...interface{}) *SliderIntWidget { +func (s *SliderIntWidget) Labelf(format string, args ...any) *SliderIntWidget { return s.Label(fmt.Sprintf(format, args...)) } @@ -136,7 +136,7 @@ func (vs *VSliderIntWidget) Label(label string) *VSliderIntWidget { } // Labelf sets formated label. -func (vs *VSliderIntWidget) Labelf(format string, args ...interface{}) *VSliderIntWidget { +func (vs *VSliderIntWidget) Labelf(format string, args ...any) *VSliderIntWidget { return vs.Label(fmt.Sprintf(format, args...)) } @@ -209,7 +209,7 @@ func (sf *SliderFloatWidget) Label(label string) *SliderFloatWidget { } // Labelf sets formated label. -func (sf *SliderFloatWidget) Labelf(format string, args ...interface{}) *SliderFloatWidget { +func (sf *SliderFloatWidget) Labelf(format string, args ...any) *SliderFloatWidget { return sf.Label(fmt.Sprintf(format, args...)) } diff --git a/Style.go b/Style.go index 97fd32f4..7423f6af 100644 --- a/Style.go +++ b/Style.go @@ -359,7 +359,7 @@ var _ Widget = &StyleSetter{} // StyleSetter is a user-friendly way to manage imgui styles. type StyleSetter struct { colors map[StyleColorID]color.Color - styles map[StyleVarID]interface{} + styles map[StyleVarID]any font *FontInfo disabled bool layout Layout @@ -369,7 +369,7 @@ type StyleSetter struct { func Style() *StyleSetter { var ss StyleSetter ss.colors = make(map[StyleColorID]color.Color) - ss.styles = make(map[StyleVarID]interface{}) + ss.styles = make(map[StyleVarID]any) return &ss } @@ -411,11 +411,7 @@ func (ss *StyleSetter) SetFontSize(size float32) *StyleSetter { font = defaultFonts[0] } - font.size = size - - extraFonts = append(extraFonts, font) - - ss.font = &font + ss.font = font.SetSize(size) return ss } @@ -466,9 +462,10 @@ func (ss *StyleSetter) Build() { } } - isFontPushed := false if ss.font != nil { - isFontPushed = PushFont(ss.font) + if PushFont(ss.font) { + defer PopFont() + } } imgui.BeginDisabled(ss.disabled) @@ -477,10 +474,6 @@ func (ss *StyleSetter) Build() { imgui.EndDisabled() - if isFontPushed { - PopFont() - } - imgui.PopStyleColorV(len(ss.colors)) imgui.PopStyleVarV(len(ss.styles)) } diff --git a/TextWidgets.go b/TextWidgets.go index b279f583..7179ca24 100644 --- a/TextWidgets.go +++ b/TextWidgets.go @@ -41,7 +41,7 @@ func (i *InputTextMultilineWidget) Label(label string) *InputTextMultilineWidget } // Labelf is formatting version of Label. -func (i *InputTextMultilineWidget) Labelf(format string, args ...interface{}) *InputTextMultilineWidget { +func (i *InputTextMultilineWidget) Labelf(format string, args ...any) *InputTextMultilineWidget { return i.Label(fmt.Sprintf(format, args...)) } @@ -116,7 +116,7 @@ func BulletText(text string) *BulletTextWidget { } // BulletTextf is a formatting version of BulletText. -func BulletTextf(format string, args ...interface{}) *BulletTextWidget { +func BulletTextf(format string, args ...any) *BulletTextWidget { return BulletText(fmt.Sprintf(format, args...)) } @@ -170,7 +170,7 @@ func (i *InputTextWidget) Label(label string) *InputTextWidget { } // Labelf adds formatted label. -func (i *InputTextWidget) Labelf(format string, args ...interface{}) *InputTextWidget { +func (i *InputTextWidget) Labelf(format string, args ...any) *InputTextWidget { return i.Label(fmt.Sprintf(format, args...)) } @@ -300,7 +300,7 @@ func (i *InputIntWidget) Label(label string) *InputIntWidget { } // Labelf sets formatted label. -func (i *InputIntWidget) Labelf(format string, args ...interface{}) *InputIntWidget { +func (i *InputIntWidget) Labelf(format string, args ...any) *InputIntWidget { return i.Label(fmt.Sprintf(format, args...)) } @@ -365,7 +365,7 @@ func (i *InputFloatWidget) Label(label string) *InputFloatWidget { } // Labelf sets formatted label. -func (i *InputFloatWidget) Labelf(format string, args ...interface{}) *InputFloatWidget { +func (i *InputFloatWidget) Labelf(format string, args ...any) *InputFloatWidget { return i.Label(fmt.Sprintf(format, args...)) } @@ -423,7 +423,7 @@ func Label(label string) *LabelWidget { } // Labelf allows to add formatted label. -func Labelf(format string, args ...interface{}) *LabelWidget { +func Labelf(format string, args ...any) *LabelWidget { return Label(fmt.Sprintf(format, args...)) } diff --git a/Texture.go b/Texture.go index fbfa665c..48dc6b64 100644 --- a/Texture.go +++ b/Texture.go @@ -42,7 +42,7 @@ func NewTextureFromRgba(rgba image.Image, loadCallback func(*Texture)) { func loadTexture(rgba image.Image, loadCallback func(*Texture)) { go func() { Update() - result := mainthread.CallVal(func() interface{} { + result := mainthread.CallVal(func() any { texID, err := Context.renderer.LoadImage(ImageToRgba(rgba)) return &loadImageResult{id: texID, err: err} }) diff --git a/Utils.go b/Utils.go index 787230e8..b5c14b02 100644 --- a/Utils.go +++ b/Utils.go @@ -194,13 +194,13 @@ func PopClipRect() { } // Assert checks if cond. If not cond, it alls golang panic. -func Assert(cond bool, t, method, msg string, args ...interface{}) { +func Assert(cond bool, t, method, msg string, args ...any) { if !cond { fatal(t, method, msg, args...) } } -func fatal(widgetName, method, message string, args ...interface{}) { +func fatal(widgetName, method, message string, args ...any) { if widgetName != "" { widgetName = fmt.Sprintf("(*%s)", widgetName) } diff --git a/Widgets.go b/Widgets.go index 917eda3d..50ef53ae 100644 --- a/Widgets.go +++ b/Widgets.go @@ -401,7 +401,7 @@ func MenuItem(label string) *MenuItemWidget { } } -func MenuItemf(format string, args ...interface{}) *MenuItemWidget { +func MenuItemf(format string, args ...any) *MenuItemWidget { return MenuItem(fmt.Sprintf(format, args...)) } @@ -443,7 +443,7 @@ func Menu(label string) *MenuWidget { } } -func Menuf(format string, args ...interface{}) *MenuWidget { +func Menuf(format string, args ...any) *MenuWidget { return Menu(fmt.Sprintf(format, args...)) } @@ -493,7 +493,7 @@ func (p *ProgressBarWidget) Overlay(overlay string) *ProgressBarWidget { return p } -func (p *ProgressBarWidget) Overlayf(format string, args ...interface{}) *ProgressBarWidget { +func (p *ProgressBarWidget) Overlayf(format string, args ...any) *ProgressBarWidget { return p.Overlay(fmt.Sprintf(format, args...)) } @@ -560,7 +560,7 @@ func TabItem(label string) *TabItemWidget { } } -func TabItemf(format string, args ...interface{}) *TabItemWidget { +func TabItemf(format string, args ...any) *TabItemWidget { return TabItem(fmt.Sprintf(format, args...)) } @@ -654,7 +654,7 @@ func Tooltip(tip string) *TooltipWidget { } } -func Tooltipf(format string, args ...interface{}) *TooltipWidget { +func Tooltipf(format string, args ...any) *TooltipWidget { return Tooltip(fmt.Sprintf(format, args...)) } diff --git a/go.mod b/go.mod index a549c81b..9cce27fa 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/AllenDang/giu -go 1.17 +go 1.18 require ( github.com/AllenDang/go-findfont v0.0.0-20200702051237-9f180485aeb8 @@ -9,8 +9,8 @@ require ( github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220320163800-277f93cfa958 github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 github.com/sahilm/fuzzy v0.1.0 - github.com/stretchr/testify v1.7.0 - golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d + github.com/stretchr/testify v1.7.1 + golang.org/x/image v0.0.0-20220302094943-723b81ca9867 gopkg.in/eapache/queue.v1 v1.1.0 ) @@ -19,6 +19,6 @@ require ( github.com/go-gl/gl v0.0.0-20211210172815-726fda9656d6 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71 // indirect + golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) diff --git a/go.sum b/go.sum index 5ab3b02b..a0cb4d63 100644 --- a/go.sum +++ b/go.sum @@ -20,12 +20,14 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI= github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d h1:RNPAfi2nHY7C2srAV8A49jpsYr0ADedCk1wq6fTMTvs= -golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= -golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71 h1:X/2sJAybVknnUnV7AD2HdT6rm2p5BP6eH2j+igduWgk= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +golang.org/x/image v0.0.0-20220302094943-723b81ca9867 h1:TcHcE0vrmgzNH1v3ppjcMGbhG5+9fMuvOmUYwNEF4q4= +golang.org/x/image v0.0.0-20220302094943-723b81ca9867/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 h1:A9i04dxx7Cribqbs8jf3FQLogkL/CV2YN7hj9KWJCkc= +golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=