From 1b44dcda982065cec552794ff6b66e05a789ae17 Mon Sep 17 00:00:00 2001 From: Trevor Slocum Date: Wed, 9 Mar 2022 21:19:04 -0800 Subject: [PATCH] Initial commit --- LICENSE | 21 + README.md | 25 + doc.go | 4 + examples/messeji/game/game.go | 148 ++++++ examples/messeji/game/mobile/mobile.go | 19 + examples/messeji/main.go | 24 + go.mod | 18 + go.sum | 456 ++++++++++++++++++ inputfield.go | 123 +++++ screenshot.png | Bin 0 -> 77425 bytes textfield.go | 643 +++++++++++++++++++++++++ 11 files changed, 1481 insertions(+) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 doc.go create mode 100644 examples/messeji/game/game.go create mode 100644 examples/messeji/game/mobile/mobile.go create mode 100644 examples/messeji/main.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 inputfield.go create mode 100644 screenshot.png create mode 100644 textfield.go diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2d09248 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Trevor Slocum + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..052144f --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# messeji +[![GoDoc](https://code.rocketnine.space/tslocum/godoc-static/raw/branch/master/badge.svg)](https://docs.rocketnine.space/code.rocketnine.space/tslocum/messeji) +[![Donate](https://img.shields.io/liberapay/receives/rocketnine.space.svg?logo=liberapay)](https://liberapay.com/rocketnine.space) + +Text widgets for [Ebiten](https://github.com/hajimehoshi/ebiten) + +**Note:** [IME](https://en.wikipedia.org/wiki/Input_method) is not yet supported. + +## Demo + +[**Try messeji**](https://messeji.rocketnine.space) + +The code for this demo is located in `examples/messeji`. + +## Documentation + +Documentation is available via [godoc](https://docs.rocketnine.space/code.rocketnine.space/tslocum/messeji). + +## Support + +Please share issues and suggestions [here](https://code.rocketnine.space/tslocum/messeji/issues). + +## Screenshot + +[![Screenshot](https://code.rocketnine.space/tslocum/messeji/raw/branch/main/screenshot.png)](https://code.rocketnine.space/tslocum/messeji/raw/branch/main/screenshot.png) diff --git a/doc.go b/doc.go new file mode 100644 index 0000000..ddddba1 --- /dev/null +++ b/doc.go @@ -0,0 +1,4 @@ +/* +Package messeji provides text widgets for Ebiten. +*/ +package messeji diff --git a/examples/messeji/game/game.go b/examples/messeji/game/game.go new file mode 100644 index 0000000..407f201 --- /dev/null +++ b/examples/messeji/game/game.go @@ -0,0 +1,148 @@ +//go:build example +// +build example + +package game + +import ( + "fmt" + "image" + "log" + "strings" + + "code.rocketnine.space/tslocum/messeji" + "github.com/hajimehoshi/ebiten/v2" + "github.com/hajimehoshi/ebiten/v2/examples/resources/fonts" + "github.com/hajimehoshi/ebiten/v2/inpututil" + "golang.org/x/image/font" + "golang.org/x/image/font/opentype" +) + +const initialText = ` +Welcome to the メッセージ (messeji) text widgets demo. +This is a TextField, which can be used to display text. +Below is an InputField, which accepts keyboard input. +Press to toggle word wrap. +Press to append input text. +Press to toggle multi-line. +` + +var mplusNormalFont font.Face + +func init() { + tt, err := opentype.Parse(fonts.MPlus1pRegular_ttf) + if err != nil { + log.Fatal(err) + } + + const dpi = 72 + mplusNormalFont, err = opentype.NewFace(tt, &opentype.FaceOptions{ + Size: 32, + DPI: dpi, + Hinting: font.HintingFull, + }) + if err != nil { + log.Fatal(err) + } +} + +type game struct { + w, h int + + buffer *messeji.TextField + + input *messeji.InputField + + singleLine bool + + op *ebiten.DrawImageOptions + + spinnerIndex int +} + +// NewDemoGame returns a new messeji demo game. +func NewDemoGame() *game { + g := &game{ + buffer: messeji.NewTextField(mplusNormalFont), + input: messeji.NewInputField(mplusNormalFont), + op: &ebiten.DrawImageOptions{ + Filter: ebiten.FilterNearest, + }, + } + + g.buffer.SetText(strings.TrimSpace(initialText) + "\n") + + g.input.SetHandleKeyboard(true) + g.input.SetSelectedFunc(func() (skipNewline bool) { + log.Printf("Input: %s", g.input.Text()) + + g.buffer.Write([]byte(fmt.Sprintf("Input: %s\n", g.input.Text()))) + + // Clear the input field. + g.input.SetText("") + + return true + }) + + return g +} + +func (g *game) Layout(outsideWidth, outsideHeight int) (int, int) { + if outsideWidth == g.w && outsideHeight == g.h { + return outsideWidth, outsideHeight + } + + padding := 10 + + w, h := outsideWidth-padding*2, g.input.LineHeight()*3+g.input.Padding()*2 + if h > outsideHeight-padding { + h = outsideHeight - padding + } + + x, y := outsideWidth/2-w/2, outsideHeight-h-padding + + g.buffer.SetRect(image.Rect(padding, padding, outsideWidth-padding, y-padding)) + + g.input.SetRect(image.Rect(x, y, x+w, y+h)) + + g.w, g.h = outsideWidth, outsideHeight + return outsideWidth, outsideHeight +} + +func (g *game) Update() error { + if inpututil.IsKeyJustPressed(ebiten.KeyEnter) && !g.input.Visible() { + g.input.SetVisible(true) + return nil + } + + if inpututil.IsKeyJustPressed(ebiten.KeyTab) { + wrap := g.buffer.WordWrap() + g.buffer.SetWordWrap(!wrap) + g.input.SetWordWrap(!wrap) + return nil + } + + if inpututil.IsKeyJustPressed(ebiten.KeyM) && ebiten.IsKeyPressed(ebiten.KeyControl) { + g.singleLine = !g.singleLine + g.input.SetSingleLine(g.singleLine) + return nil + } + + err := g.buffer.Update() + if err != nil { + return fmt.Errorf("failed to update buffer: %s", err) + } + + err = g.input.Update() + if err != nil { + return fmt.Errorf("failed to update input field: %s", err) + } + return nil +} + +func (g *game) Draw(screen *ebiten.Image) { + // Draw display field. + g.buffer.Draw(screen) + + // Draw input field. + g.input.Draw(screen) +} diff --git a/examples/messeji/game/mobile/mobile.go b/examples/messeji/game/mobile/mobile.go new file mode 100644 index 0000000..1dc9dc7 --- /dev/null +++ b/examples/messeji/game/mobile/mobile.go @@ -0,0 +1,19 @@ +//go:build example +// +build example + +package mobile + +import ( + "code.rocketnine.space/tslocum/messeji/examples/messeji/game" + "github.com/hajimehoshi/ebiten/v2/mobile" +) + +func init() { + mobile.SetGame(game.NewDemoGame()) +} + +// Dummy is a dummy exported function. +// +// gomobile will only compile packages that include at least one exported function. +// Dummy forces gomobile to compile this package. +func Dummy() {} diff --git a/examples/messeji/main.go b/examples/messeji/main.go new file mode 100644 index 0000000..e470733 --- /dev/null +++ b/examples/messeji/main.go @@ -0,0 +1,24 @@ +//go:build example +// +build example + +package main + +import ( + "log" + + "code.rocketnine.space/tslocum/messeji/examples/messeji/game" + "github.com/hajimehoshi/ebiten/v2" +) + +func main() { + ebiten.SetWindowTitle("メッセージ") + ebiten.SetWindowResizable(true) + ebiten.SetWindowSize(640, 480) + ebiten.SetMaxTPS(144) + ebiten.SetFPSMode(ebiten.FPSModeVsyncOffMinimum) + + g := game.NewDemoGame() + if err := ebiten.RunGame(g); err != nil { + log.Fatal(err) + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..49f852e --- /dev/null +++ b/go.mod @@ -0,0 +1,18 @@ +module code.rocketnine.space/tslocum/messeji + +go 1.17 + +require ( + github.com/hajimehoshi/ebiten/v2 v2.2.5 + golang.org/x/image v0.0.0-20220302094943-723b81ca9867 +) + +require ( + github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211213063430-748e38ca8aec // indirect + github.com/jezek/xgb v1.0.0 // indirect + golang.org/x/exp/shiny v0.0.0-20220310221936-9d5fb453b98c // indirect + golang.org/x/mobile v0.0.0-20220307220422-55113b94f09c // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect + golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect + golang.org/x/text v0.3.7 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..8c567d6 --- /dev/null +++ b/go.sum @@ -0,0 +1,456 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210727001814-0db043d8d5be h1:vEIVIuBApEBQTEJt19GfhoU+zFSV+sNTa9E9FdnRYfk= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210727001814-0db043d8d5be/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211213063430-748e38ca8aec h1:3FLiRYO6PlQFDpUU7OEFlWgjGD1jnBIVSJ5SYRWk+9c= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211213063430-748e38ca8aec/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hajimehoshi/bitmapfont/v2 v2.1.3 h1:JefUkL0M4nrdVwVq7MMZxSTh6mSxOylm+C4Anoucbb0= +github.com/hajimehoshi/bitmapfont/v2 v2.1.3/go.mod h1:2BnYrkTQGThpr/CY6LorYtt/zEPNzvE/ND69CRTaHMs= +github.com/hajimehoshi/ebiten/v2 v2.2.5 h1:i6NdS6pEi5kgfTh+4XAVCVtCXxjTyxzU1cj1oqHWkZQ= +github.com/hajimehoshi/ebiten/v2 v2.2.5/go.mod h1:olKl/qqhMBBAm2oI7Zy292nCtE+nitlmYKNF3UpbFn0= +github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41/go.mod h1:CqqAHp7Dk/AqQiwuhV1yT2334qbA/tFWQW0MD2dGqUE= +github.com/hajimehoshi/go-mp3 v0.3.2/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM= +github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI= +github.com/hajimehoshi/oto/v2 v2.1.0-alpha.2/go.mod h1:rUKQmwMkqmRxe+IAof9+tuYA2ofm8cAWXFmSfzDN8vQ= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jakecoffman/cp v1.1.0/go.mod h1:JjY/Fp6d8E1CHnu74gWNnU0+b9VzEdUVPoJxg2PsTQg= +github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 h1:dy+DS31tGEGCsZzB45HmJJNHjur8GDgtRNX9U7HnSX4= +github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240/go.mod h1:3P4UH/k22rXyHIJD2w4h2XMqPX4Of/eySEZq9L6wqc4= +github.com/jezek/xgb v1.0.0 h1:s2rRzAV8KQRlpsYA7Uyxoidv1nodMF0m6dIG6FhhVLQ= +github.com/jezek/xgb v1.0.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= +github.com/jfreymuth/oggvorbis v1.0.3/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII= +github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3TWXyuzrqQ= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/zerolog v1.21.0/go.mod h1:ZPhntP/xmq1nnND05hhpAh2QMhSsA4UN3MGZ6O2J3hM= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo= +go.opentelemetry.io/otel/metric v0.20.0/go.mod h1:598I5tYlH1vzBjn+BTuhzTCSb/9debfNp6R3s7Pr1eU= +go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa9FqQ2IQ8LoxiGnw= +go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc= +go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= +golang.org/x/exp v0.0.0-20211012155715-ffe10e552389 h1:qFfBYVpJAdBCk6Nmd7ZbcyhGmKmv8fps+OyoOfpjvu8= +golang.org/x/exp v0.0.0-20211012155715-ffe10e552389/go.mod h1:a3o/VtDNHN+dCVLEpzjjUHOzR+Ln3DHX056ZPzoZGGA= +golang.org/x/exp/shiny v0.0.0-20220309201404-e19e41d68951 h1:nS57kBQYHwQLjlkIOP3a7N1gMUoA+cpQGRTVq+cPLNo= +golang.org/x/exp/shiny v0.0.0-20220309201404-e19e41d68951/go.mod h1:NtXcNtv5Wu0zUbBl574y/D5MMZvnQnV3sgjZxbs64Jo= +golang.org/x/exp/shiny v0.0.0-20220310221936-9d5fb453b98c h1:a4GcifVO45IVJuHv+44xd3AMV4xer4tBjm9fQb3HGco= +golang.org/x/exp/shiny v0.0.0-20220310221936-9d5fb453b98c/go.mod h1:NtXcNtv5Wu0zUbBl574y/D5MMZvnQnV3sgjZxbs64Jo= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190703141733-d6a02ce849c9/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +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/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= +golang.org/x/mobile v0.0.0-20210902104108-5d9a33257ab5/go.mod h1:c4YKU3ZylDmvbw+H/PSvm42vhdWbuxCzbonauEAP9B8= +golang.org/x/mobile v0.0.0-20210924032853-1c027f395ef7 h1:CyFUjc175y/mbMjxe+WdqI72jguLyjQChKCDe9mfTvg= +golang.org/x/mobile v0.0.0-20210924032853-1c027f395ef7/go.mod h1:c4YKU3ZylDmvbw+H/PSvm42vhdWbuxCzbonauEAP9B8= +golang.org/x/mobile v0.0.0-20220307220422-55113b94f09c h1:9J0m/JcA5YXYbamDhF5I3T7cJnR7V75OCLnMCPb5gl4= +golang.org/x/mobile v0.0.0-20220307220422-55113b94f09c/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.1-0.20210830214625-1b1db11ec8f4/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= +golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/inputfield.go b/inputfield.go new file mode 100644 index 0000000..215057b --- /dev/null +++ b/inputfield.go @@ -0,0 +1,123 @@ +package messeji + +import ( + "github.com/hajimehoshi/ebiten/v2" + "github.com/hajimehoshi/ebiten/v2/inpututil" + "golang.org/x/image/font" +) + +// InputField is a text input field. Call Update and Draw when your Game's +// Update and Draw methods are called. +// +// Note: A position and size must be set via SetRect before the field will appear. +// Keyboard events are not handled by default, and may be enabled via SetHandleKeyboard. +type InputField struct { + *TextField + + // changedFunc is a function which is called when the text buffer is changed. + // The function may return false to skip adding the rune to the text buffer. + changedFunc func(r rune) (accept bool) + + // selectedFunc is a function which is called when the enter key is pressed. The + // function may return true to skip adding a newline to text. + selectedFunc func() (accept bool) + + // readBuffer is where incoming runes are stored before being added to the input buffer. + readBuffer []rune +} + +// NewInputField returns a new InputField. See type documentation for more info. +func NewInputField(face font.Face) *InputField { + f := &InputField{ + TextField: NewTextField(face), + } + f.TextField.suffix = "_" + return f +} + +// SetHandleKeyboard sets a flag controlling whether keyboard input should be handled +// by the field. This can be used to facilitate focus changes between multiple inputs. +func (f *InputField) SetHandleKeyboard(handle bool) { + f.Lock() + defer f.Unlock() + + f.handleKeyboard = handle + + // Show or hide cursor. + if f.handleKeyboard { + f.TextField.suffix = "_" + } else { + f.TextField.suffix = "" + } +} + +// SetChangedFunc sets a handler which is called when the text buffer is changed. +// The handler may return true to add the rune to the text buffer. +func (f *InputField) SetChangedFunc(changedFunc func(r rune) (accept bool)) { + f.changedFunc = changedFunc +} + +// SetSelectedFunc sets a handler which is called when the enter key is pressed. +// Providing a nil function value will remove the existing handler (if set). +// The handler may return true to skip adding a newline to the text. +func (f *InputField) SetSelectedFunc(selectedFunc func() (accept bool)) { + f.selectedFunc = selectedFunc +} + +// Update updates the input field. This function should be called when +// Game.Update is called. +func (f *InputField) Update() error { + f.Lock() + + if !f.visible || rectIsZero(f.r) { + return nil + } + + if !f.handleKeyboard { + f.Unlock() + return f.TextField.Update() + } + + var redraw bool + + f.readBuffer = ebiten.AppendInputChars(f.readBuffer[:0]) + for _, r := range f.readBuffer { + if f.changedFunc != nil { + f.Unlock() + accept := f.changedFunc(r) + f.Lock() + + if !accept { + continue + } + } + + f.buffer += string(r) + redraw = true + } + + if inpututil.IsKeyJustPressed(ebiten.KeyBackspace) && len(f.buffer) > 0 { + f.buffer = f.buffer[:len(f.buffer)-1] + redraw = true + } + + if inpututil.IsKeyJustPressed(ebiten.KeyEnter) { + var skipNewline bool + if f.selectedFunc != nil { + f.Unlock() + skipNewline = f.selectedFunc() + f.Lock() + } + if !skipNewline { + f.buffer += "\n" + redraw = true + } + } + + if redraw { + f.bufferModified() + } + + f.Unlock() + return f.TextField.Update() +} diff --git a/screenshot.png b/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..c135cfeec595e686de02600122cd209fac67d9bc GIT binary patch literal 77425 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%0D5hG~bDZlW3Qd)2#s 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

)6!ml;EMze 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 D^g$75 literal 0 HcmV?d00001 diff --git a/textfield.go b/textfield.go new file mode 100644 index 0000000..c00147b --- /dev/null +++ b/textfield.go @@ -0,0 +1,643 @@ +package messeji + +import ( + "image" + "image/color" + "strings" + "sync" + "unicode" + + "github.com/hajimehoshi/ebiten/v2" + "github.com/hajimehoshi/ebiten/v2/inpututil" + "github.com/hajimehoshi/ebiten/v2/text" + "golang.org/x/image/font" +) + +const ( + initialPadding = 2 + initialScrollWidth = 32 +) + +var ( + initialForeground = color.RGBA{0, 0, 0, 255} + initialBackground = color.RGBA{255, 255, 255, 255} +) + +// TextField is a text display field. Call Update and Draw when your Game's +// Update and Draw methods are called. +// +// Note: A position and size must be set via SetRect before the field will appear. +// Keyboard events are not handled by default, and may be enabled via SetHandleKeyboard. +type TextField struct { + // r specifies the position and size of the field. + r image.Rectangle + + // buffer is the actual content of the field. + buffer string + + // prefix is the text shown before the content of the field. + prefix string + + // suffix is the text shown after the content of the field. + suffix string + + // wordWrap determines whether content is wrapped at word boundaries. + wordWrap bool + + // bufferWrapped is the content of the field as it appears on the screen. + bufferWrapped []string + + // bufferSize is the size (in pixels) of the entire text buffer. When single + // line mode is enabled, + bufferSize int + + // singleLine is whether the field displays all text on a single line. + singleLine bool + + // face is the font face of the text within the field. + face font.Face + + // lineHeight is the height of a single line of text. + lineHeight int + + // overrideLineHeight is the custom height for a line of text, or 0 to disable. + overrideLineHeight int + + // textColor is the color of the text within the field. + textColor color.Color + + // backgroundColor is the color of the background of the field. + backgroundColor color.Color + + // padding is the amount of padding around the text within the field. + padding int + + // follow determines whether the field should automatically scroll to the + // end when content is added to the buffer. + follow bool + + // overflow is whether the content of the field is currently larger than the field. + overflow bool + + // offset is the current view offset of the text within the field. + offset int + + // handleKeyboard is a flag which, when enabled, causes keyboard input to be handled. + handleKeyboard bool + + // modified is a flag which, when enabled, causes bufferModified to be called + // during the next Draw call. + modified bool + + // scrollRect specifies the position and size of the scrolling area. + scrollRect image.Rectangle + + // scrollWidth is the width of the scroll bar. + scrollWidth int + + // scrollVisible is whether the scroll bar is visible on the screen. + scrollVisible bool + + // scrollAutoHide is whether the scroll bar should be automatically hidden + // when the entire text buffer fits within the screen. + scrollAutoHide bool + + // scrollDrag is whether the scroll bar is currently being dragged. + scrollDrag bool + + // img is the image of the field. + img *ebiten.Image + + // visible is whether the field is visible on the screen. + visible bool + + sync.Mutex +} + +// NewTextField returns a new TextField. See type documentation for more info. +func NewTextField(face font.Face) *TextField { + f := &TextField{ + face: face, + textColor: initialForeground, + backgroundColor: initialBackground, + padding: initialPadding, + scrollWidth: initialScrollWidth, + follow: true, + wordWrap: true, + scrollVisible: true, + scrollAutoHide: true, + visible: true, + } + f.setDefaultLineHeight() + return f +} + +// Rect returns the position and size of the field. +func (f *TextField) Rect() image.Rectangle { + f.Lock() + defer f.Unlock() + + return f.r +} + +// SetRect sets the position and size of the field. +func (f *TextField) SetRect(r image.Rectangle) { + f.Lock() + defer f.Unlock() + + f.r = r + f.drawImage() +} + +// Text returns the text in the field. +func (f *TextField) Text() string { + f.Lock() + defer f.Unlock() + + return f.buffer +} + +// SetText sets the text in the field. +func (f *TextField) SetText(text string) { + f.Lock() + defer f.Unlock() + + f.buffer = text + f.modified = true +} + +// SetPrefix sets the text shown before the content of the field. +func (f *TextField) SetPrefix(text string) { + f.Lock() + defer f.Unlock() + + f.prefix = text + f.drawImage() +} + +// SetSuffix sets the text shown before the content of the field. +func (f *TextField) SetSuffix(text string) { + f.Lock() + defer f.Unlock() + + f.suffix = text + f.drawImage() +} + +// SetFollow sets whether the field should automatically scroll to the end when +// content is added to the buffer. +func (f *TextField) SetFollow(follow bool) { + f.Lock() + defer f.Unlock() + + f.follow = follow +} + +// SetSingleLine sets whether the field displays all text on a single line. +// When enabled, the field scrolls horizontally. Otherwise, it scrolls vertically. +func (f *TextField) SetSingleLine(single bool) { + f.Lock() + defer f.Unlock() + + if f.singleLine == single { + return + } + + f.singleLine = single + f.bufferModified() +} + +// LineHeight returns the line height for the field. +func (f *TextField) LineHeight() int { + f.Lock() + defer f.Unlock() + + if f.overrideLineHeight != 0 { + return f.overrideLineHeight + } + return f.lineHeight +} + +// SetLineHeight sets a custom line height for the field. Setting a line +// height of 0 restores the automatic line height detection based on the font. +func (f *TextField) SetLineHeight(height int) { + f.Lock() + defer f.Unlock() + + f.overrideLineHeight = height +} + +// SetForegroundColor sets the color of the text within the field. +func (f *TextField) SetForegroundColor(c color.Color) { + f.Lock() + defer f.Unlock() + + f.textColor = c +} + +// SetBackgroundColor sets the color of the background of the field. +func (f *TextField) SetBackgroundColor(c color.Color) { + f.Lock() + defer f.Unlock() + + f.textColor = c +} + +// SetFont sets the font face of the text within the field. +func (f *TextField) SetFont(face font.Face) { + f.Lock() + defer f.Unlock() + + f.face = face + f.setDefaultLineHeight() +} + +// Padding returns the amount of padding around the text within the field. +func (f *TextField) Padding() int { + f.Lock() + defer f.Unlock() + + return f.padding +} + +// SetPadding sets the amount of padding around the text within the field. +func (f *TextField) SetPadding(padding int) { + f.Lock() + defer f.Unlock() + + f.padding = padding +} + +// Visible returns whether the field is currently visible on the screen. +func (f *TextField) Visible() bool { + return f.visible +} + +// SetVisible sets whether the field is visible on the screen. +func (f *TextField) SetVisible(visible bool) { + f.Lock() + defer f.Unlock() + + if f.visible == visible { + return + } + + f.visible = visible + if visible { + f.drawImage() + } +} + +// SetScrollBarWidth sets the width of the scroll bar. +func (f *TextField) SetScrollBarWidth(width int) { + f.Lock() + defer f.Unlock() + + if f.scrollWidth == width { + return + } + + f.scrollWidth = width + f.drawImage() +} + +// SetScrollBarVisible sets whether the scroll bar is visible on the screen. +func (f *TextField) SetScrollBarVisible(scrollVisible bool) { + f.Lock() + defer f.Unlock() + + if f.scrollVisible == scrollVisible { + return + } + + f.scrollVisible = scrollVisible + f.drawImage() +} + +// SetAutoHideScrollBar sets whether the scroll bar is automatically hidden +// when the entire text buffer is visible. +func (f *TextField) SetAutoHideScrollBar(autoHide bool) { + f.Lock() + defer f.Unlock() + + if f.scrollAutoHide == autoHide { + return + } + + f.scrollAutoHide = autoHide + f.drawImage() +} + +// WordWrap returns the current text wrap mode. +func (f *TextField) WordWrap() bool { + f.Lock() + defer f.Unlock() + + return f.wordWrap +} + +// SetWordWrap sets a flag which, when enabled, causes text to wrap without breaking words. +func (f *TextField) SetWordWrap(wrap bool) { + f.Lock() + defer f.Unlock() + + if f.wordWrap == wrap { + return + } + + f.wordWrap = wrap + f.drawImage() +} + +// SetHandleKeyboard sets a flag controlling whether keyboard input should be handled +// by the field. This can be used to facilitate focus changes between multiple inputs. +func (f *TextField) SetHandleKeyboard(handle bool) { + f.Lock() + defer f.Unlock() + + f.handleKeyboard = handle +} + +// Write writes to the field's buffer. +func (f *TextField) Write(p []byte) (n int, err error) { + f.Lock() + defer f.Unlock() + + f.buffer += string(p) + f.modified = true + return len(p), nil +} + +// Update updates the field. This function should be called when +// Game.Update is called. +func (f *TextField) Update() error { + f.Lock() + defer f.Unlock() + + if !f.visible || rectIsZero(f.r) { + return nil + } + + var redraw bool + + // Handle keyboard PageUp/PageDown. + if f.handleKeyboard { + offsetAmount := 0 + if inpututil.IsKeyJustPressed(ebiten.KeyPageUp) { + offsetAmount = -100 + } else if inpututil.IsKeyJustPressed(ebiten.KeyPageDown) { + offsetAmount = 100 + } + if offsetAmount != 0 { + f.offset += offsetAmount + f.clampOffset() + redraw = true + } + } + + // Handle mouse wheel. + _, scrollY := ebiten.Wheel() + if scrollY != 0 { + x, y := ebiten.CursorPosition() + p := image.Point{x, y} + if p.In(f.r) { + const offsetAmount = 25 + f.offset -= int(scrollY * offsetAmount) + f.clampOffset() + redraw = true + } + } + + // Handle scroll bar click (and drag). + if f.showScrollBar() { + if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) || f.scrollDrag { + x, y := ebiten.CursorPosition() + p := image.Point{x - f.r.Min.X, y - f.r.Min.Y} + if f.scrollDrag || p.In(f.scrollRect) { + dragY := y - f.r.Min.Y - f.scrollWidth/4 + if dragY < 0 { + dragY = 0 + } else if dragY > f.scrollRect.Dy() { + dragY = f.scrollRect.Dy() + } + pct := float64(dragY) / float64(f.scrollRect.Dy()-f.scrollWidth/2) + if pct > 1 { + pct = 1 + } + h := f.r.Dy() + f.offset = int(float64(f.bufferSize-h) * pct) + redraw = true + f.scrollDrag = true + } + if !ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) { + f.scrollDrag = false + } + } + } + + if redraw { + f.drawImage() + } + return nil +} + +// Draw draws the field on the screen. This function should be called +// when Game.Draw is called. +func (f *TextField) Draw(screen *ebiten.Image) { + f.Lock() + defer f.Unlock() + + if f.modified { + f.bufferModified() + f.modified = false + } + + if !f.visible || rectIsZero(f.r) || f.img == nil { + return + } + + op := &ebiten.DrawImageOptions{} + op.GeoM.Translate(float64(f.r.Min.X), float64(f.r.Min.Y)) + screen.DrawImage(f.img, op) +} + +func (f *TextField) setDefaultLineHeight() { + lineBounds := text.BoundString(f.face, "ATZgpq.") + f.lineHeight = lineBounds.Dy() + 5 +} + +func (f *TextField) wrapContent(withScrollBar bool) { + buffer := f.prefix + f.buffer + f.suffix + + if f.singleLine { + f.bufferWrapped = []string{strings.ReplaceAll(buffer, "\n", "")} + return + } + + w := f.r.Dx() + if withScrollBar { + w -= f.scrollWidth + } + f.bufferWrapped = f.bufferWrapped[:0] + for _, line := range strings.Split(buffer, "\n") { + l := len(line) + var start int + var end int + for start < l { + for end = l; end > start; end-- { + bounds := text.BoundString(f.face, line[start:end]) + if bounds.Dx() < w-(f.padding*2)-2 { + if f.wordWrap { + if end < l && !unicode.IsSpace(rune(line[end])) { + for endOffset := 0; endOffset < end-start; endOffset++ { + if unicode.IsSpace(rune(line[end-endOffset])) { + end = end - endOffset + break + } + } + } + } + f.bufferWrapped = append(f.bufferWrapped, line[start:end]) + break + } + } + start = end + } + } +} + +// drawContent draws the text buffer to img. +func (f *TextField) drawContent() (overflow bool) { + f.img.Fill(f.backgroundColor) + + h := f.r.Dy() + lineHeight := f.overrideLineHeight + if lineHeight == 0 { + lineHeight = f.lineHeight + } + lineOffset := 7 + f.bufferSize = 0 + for i, line := range f.bufferWrapped { + lineX := f.padding + lineY := f.padding + + lineY += lineHeight*(i+1) - lineOffset + + if f.singleLine { + bounds := text.BoundString(f.face, line) + f.bufferSize = bounds.Dx() + f.padding*4 + } else { + f.bufferSize = lineY + lineOffset + f.padding + } + + if lineY < 0 || lineY >= h-(f.padding*2) { + overflow = true + } + + // Skip drawing off-screen lines. + if lineY < 0 || lineY-lineHeight > f.offset+h { + continue + } + + if f.singleLine { + lineX -= f.offset + } else { + lineY -= f.offset + } + + text.Draw(f.img, line, f.face, lineX, lineY, f.textColor) + } + + return overflow +} + +func (f *TextField) clampOffset() { + fieldSize := f.r.Dy() + if f.singleLine { + fieldSize = f.r.Dx() + } + + if f.offset > f.bufferSize-fieldSize { + f.offset = f.bufferSize - fieldSize + } + if f.offset < 0 { + f.offset = 0 + } +} + +func (f *TextField) showScrollBar() bool { + return !f.singleLine && f.scrollVisible && (f.overflow || !f.scrollAutoHide) +} + +// drawImage draws the field to img (caching it for future draws). +func (f *TextField) drawImage() { + if rectIsZero(f.r) { + f.img = nil + return + } + + w, h := f.r.Dx(), f.r.Dy() + var newImage bool + if f.img == nil { + newImage = true + } else { + imgRect := f.img.Bounds() + imgW, imgH := imgRect.Dx(), imgRect.Dy() + newImage = imgW != w || imgH != h + } + if newImage { + f.img = ebiten.NewImage(w, h) + } + + f.wrapContent(false) + f.overflow = f.drawContent() + if f.showScrollBar() { + f.wrapContent(true) + f.drawContent() + } + + scrollBarW := 32 + + // Draw scrollbar. + if f.showScrollBar() { + scrollAreaX, scrollAreaY := w-scrollBarW, 0 + f.scrollRect = image.Rect(scrollAreaX, scrollAreaY, scrollAreaX+scrollBarW, h) + + scrollBarH := f.scrollWidth / 2 + if scrollBarH < 4 { + scrollBarH = 4 + } + + scrollX, scrollY := w-scrollBarW, 0 + pct := float64(f.offset) / float64(f.bufferSize-h) + scrollY += int(float64(h-scrollBarH) * pct) + scrollBarRect := image.Rect(scrollX, scrollY, scrollX+scrollBarW, scrollY+scrollBarH) + + f.img.SubImage(f.scrollRect).(*ebiten.Image).Fill(color.RGBA{200, 200, 200, 255}) + f.img.SubImage(scrollBarRect).(*ebiten.Image).Fill(color.RGBA{108, 108, 108, 255}) + } +} + +func (f *TextField) bufferModified() { + f.drawImage() + + if !f.follow { + return + } + fieldSize := f.r.Dy() + if f.singleLine { + fieldSize = f.r.Dx() + } + offset := f.bufferSize - fieldSize + if offset < 0 { + offset = 0 + } + if offset != f.offset { + f.offset = offset + f.drawImage() + } +} + +func rectIsZero(r image.Rectangle) bool { + return r == image.Rectangle{} +}