package gel import ( "image" "image/color" "gioui.org/font" l "gioui.org/layout" "gioui.org/op" "gioui.org/op/paint" "gioui.org/text" "gioui.org/unit" "git.mleku.dev/mleku/prevara/f32color" ) // TextInput is a simple text input widget type TextInput struct { *Window font font.Font textSize unit.Sp // Color is the text color. color color.NRGBA // Hint contains the text displayed when the editor is empty. hint string // HintColor is the color of hint text. hintColor color.NRGBA // SelectionColor is the color of the background for selected text. selectionColor color.NRGBA editor *Editor shaper *text.Shaper } // TextInput creates a simple text input widget func (w *Window) TextInput(editor *Editor, hint string) *TextInput { var fon font.Font if f, e := w.collection.Font("bariol regular"); e == nil { fon = f } ti := &TextInput{ Window: w, editor: editor, textSize: w.TextSize, font: fon, color: w.Colors.GetNRGBAFromName("DocText"), shaper: w.shaper, hint: hint, hintColor: w.Colors.GetNRGBAFromName("Hint"), selectionColor: w.Colors.GetNRGBAFromName("scrim"), } return ti } // Font sets the font for the text input widget func (ti *TextInput) Font(fontName string) *TextInput { var fon font.Font var e error if fon, e = ti.Theme.collection.Font(fontName); !E.Chk(e) { ti.editor.font = fon } return ti } // TextScale sets the size of the text relative to the base font size func (ti *TextInput) TextScale(scale float32) *TextInput { ti.textSize = unit.Sp(float32(ti.Theme.TextSize) * scale) return ti } // Color sets the color to render the text func (ti *TextInput) Color(color string) *TextInput { ti.color = ti.Theme.Colors.GetNRGBAFromName(color) return ti } // SelectionColor sets the color to render the text func (ti *TextInput) SelectionColor(color string) *TextInput { ti.selectionColor = ti.Theme.Colors.GetNRGBAFromName(color) return ti } // Hint sets the text to show when the box is empty func (ti *TextInput) Hint(hint string) *TextInput { ti.hint = hint return ti } // HintColor sets the color of the hint text func (ti *TextInput) HintColor(color string) *TextInput { ti.hintColor = ti.Theme.Colors.GetNRGBAFromName(color) return ti } // Fn renders the text input widget func (ti *TextInput) Fn(gtx l.Context) l.Dimensions { // Save state using the new Push/Pop pattern stack := op.Offset(image.Point{}).Push(gtx.Ops) defer stack.Pop() disabled := !gtx.Source.Enabled() textColor := blendDisabledColor(disabled, ti.color) selectionColor := blendDisabledColor(disabled, ti.selectionColor) // If editor is empty, show hint first to determine minimum size if ti.editor.Len() == 0 { macro := op.Record(gtx.Ops) paint.ColorOp{Color: ti.hintColor}.Add(gtx.Ops) var maxlines int if ti.editor.singleLine { maxlines = 1 } tl := Label{ Window: ti.Window, font: ti.font, color: ti.hintColor, alignment: ti.editor.alignment, maxLines: maxlines, text: ti.hint, textSize: ti.textSize, shaper: ti.shaper, } dims := tl.Fn(gtx) call := macro.Stop() if w := dims.Size.X; gtx.Constraints.Min.X < w { gtx.Constraints.Min.X = w } if h := dims.Size.Y; gtx.Constraints.Min.Y < h { gtx.Constraints.Min.Y = h } // Layout the editor (even if empty, to handle input) editorDims := ti.editor.Layout(gtx, ti.shaper, ti.font, ti.textSize, textColor, selectionColor) // Draw the hint since editor is empty call.Add(gtx.Ops) return editorDims } // Layout the editor with text and selection colors return ti.editor.Layout(gtx, ti.shaper, ti.font, ti.textSize, textColor, selectionColor) } func blendDisabledColor(disabled bool, c color.NRGBA) color.NRGBA { if disabled { return f32color.Disabled(c) } return c }