textinput.go raw

   1  package gel
   2  
   3  import (
   4  	"image/color"
   5  
   6  	l "github.com/p9c/gio/layout"
   7  	"github.com/p9c/gio/op"
   8  	"github.com/p9c/gio/op/paint"
   9  	"github.com/p9c/gio/text"
  10  	"github.com/p9c/gio/unit"
  11  
  12  	"github.com/p9c/gel/f32color"
  13  )
  14  
  15  // TextInput is a simple text input widget
  16  type TextInput struct {
  17  	*Window
  18  	font     text.Font
  19  	textSize unit.Value
  20  	// Color is the text color.
  21  	color color.NRGBA
  22  	// Hint contains the text displayed when the editor is empty.
  23  	hint string
  24  	// HintColor is the color of hint text.
  25  	hintColor color.NRGBA
  26  	// SelectionColor is the color of the background for selected text.
  27  	selectionColor color.NRGBA
  28  	editor         *Editor
  29  	shaper         text.Shaper
  30  }
  31  
  32  // TextInput creates a simple text input widget
  33  func (w *Window) TextInput(editor *Editor, hint string) *TextInput {
  34  	var fon text.Font
  35  	var e error
  36  	if fon, e = w.collection.Font("bariol regular"); E.Chk(e) {
  37  		panic(e)
  38  	}
  39  	ti := &TextInput{
  40  		Window:         w,
  41  		editor:         editor,
  42  		textSize:       w.TextSize,
  43  		font:           fon,
  44  		color:          w.Colors.GetNRGBAFromName("DocText"),
  45  		shaper:         w.shaper,
  46  		hint:           hint,
  47  		hintColor:      w.Colors.GetNRGBAFromName("Hint"),
  48  		selectionColor: w.Colors.GetNRGBAFromName("scrim"),
  49  	}
  50  	ti.Font("bariol regular")
  51  	return ti
  52  }
  53  
  54  // Font sets the font for the text input widget
  55  func (ti *TextInput) Font(font string) *TextInput {
  56  	var fon text.Font
  57  	var e error
  58  	if fon, e = ti.Theme.collection.Font(font); !E.Chk(e) {
  59  		ti.editor.font = fon
  60  	}
  61  	return ti
  62  }
  63  
  64  // TextScale sets the size of the text relative to the base font size
  65  func (ti *TextInput) TextScale(scale float32) *TextInput {
  66  	ti.textSize = ti.Theme.TextSize.Scale(scale)
  67  	return ti
  68  }
  69  
  70  // Color sets the color to render the text
  71  func (ti *TextInput) Color(color string) *TextInput {
  72  	ti.color = ti.Theme.Colors.GetNRGBAFromName(color)
  73  	return ti
  74  }
  75  
  76  // SelectionColor sets the color to render the text
  77  func (ti *TextInput) SelectionColor(color string) *TextInput {
  78  	ti.selectionColor = ti.Theme.Colors.GetNRGBAFromName(color)
  79  	return ti
  80  }
  81  
  82  // Hint sets the text to show when the box is empty
  83  func (ti *TextInput) Hint(hint string) *TextInput {
  84  	ti.hint = hint
  85  	return ti
  86  }
  87  
  88  // HintColor sets the color of the hint text
  89  func (ti *TextInput) HintColor(color string) *TextInput {
  90  	ti.hintColor = ti.Theme.Colors.GetNRGBAFromName(color)
  91  	return ti
  92  }
  93  
  94  // Fn renders the text input widget
  95  func (ti *TextInput) Fn(gtx l.Context) l.Dimensions {
  96  	defer op.Save(gtx.Ops).Load()
  97  	macro := op.Record(gtx.Ops)
  98  	paint.ColorOp{Color: ti.hintColor}.Add(gtx.Ops)
  99  	var maxlines int
 100  	if ti.editor.singleLine {
 101  		maxlines = 1
 102  	}
 103  	tl := Label{
 104  		Window:    ti.Window,
 105  		font:      ti.font,
 106  		color:     ti.hintColor,
 107  		alignment: ti.editor.alignment,
 108  		maxLines:  maxlines,
 109  		text:      ti.hint,
 110  		textSize:  ti.textSize,
 111  		shaper:    ti.shaper,
 112  	}
 113  	dims := tl.Fn(gtx)
 114  	call := macro.Stop()
 115  	if w := dims.Size.X; gtx.Constraints.Min.X < w {
 116  		gtx.Constraints.Min.X = w
 117  	}
 118  	if h := dims.Size.Y; gtx.Constraints.Min.Y < h {
 119  		gtx.Constraints.Min.Y = h
 120  	}
 121  	dims = ti.editor.Layout(gtx, ti.shaper, ti.font, ti.textSize)
 122  	disabled := gtx.Queue == nil
 123  	if ti.editor.Len() > 0 {
 124  		paint.ColorOp{Color: blendDisabledColor(disabled, ti.selectionColor)}.Add(gtx.Ops)
 125  		ti.editor.PaintSelection(gtx)
 126  		paint.ColorOp{Color: blendDisabledColor(disabled, ti.color)}.Add(gtx.Ops)
 127  		ti.editor.PaintText(gtx)
 128  	} else {
 129  		call.Add(gtx.Ops)
 130  	}
 131  	if !disabled {
 132  		paint.ColorOp{Color: ti.color}.Add(gtx.Ops)
 133  		ti.editor.PaintCaret(gtx)
 134  	}
 135  	return dims
 136  }
 137  
 138  func blendDisabledColor(disabled bool, c color.NRGBA) color.NRGBA {
 139  	if disabled {
 140  		return f32color.Disabled(c)
 141  	}
 142  	return c
 143  }
 144