editor.go raw

   1  // SPDX-License-Identifier: Unlicense OR MIT
   2  
   3  package material
   4  
   5  import (
   6  	"image/color"
   7  
   8  	"github.com/p9c/p9/pkg/gel/gio/internal/f32color"
   9  	"github.com/p9c/p9/pkg/gel/gio/layout"
  10  	"github.com/p9c/p9/pkg/gel/gio/op"
  11  	"github.com/p9c/p9/pkg/gel/gio/op/paint"
  12  	"github.com/p9c/p9/pkg/gel/gio/text"
  13  	"github.com/p9c/p9/pkg/gel/gio/unit"
  14  	"github.com/p9c/p9/pkg/gel/gio/widget"
  15  )
  16  
  17  type EditorStyle struct {
  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         *widget.Editor
  29  
  30  	shaper text.Shaper
  31  }
  32  
  33  func Editor(th *Theme, editor *widget.Editor, hint string) EditorStyle {
  34  	return EditorStyle{
  35  		Editor:         editor,
  36  		TextSize:       th.TextSize,
  37  		Color:          th.Palette.Fg,
  38  		shaper:         th.Shaper,
  39  		Hint:           hint,
  40  		HintColor:      f32color.MulAlpha(th.Palette.Fg, 0xbb),
  41  		SelectionColor: f32color.MulAlpha(th.Palette.ContrastBg, 0x60),
  42  	}
  43  }
  44  
  45  func (e EditorStyle) Layout(gtx layout.Context) layout.Dimensions {
  46  	defer op.Save(gtx.Ops).Load()
  47  	macro := op.Record(gtx.Ops)
  48  	paint.ColorOp{Color: e.HintColor}.Add(gtx.Ops)
  49  	var maxlines int
  50  	if e.Editor.SingleLine {
  51  		maxlines = 1
  52  	}
  53  	tl := widget.Label{Alignment: e.Editor.Alignment, MaxLines: maxlines}
  54  	dims := tl.Layout(gtx, e.shaper, e.Font, e.TextSize, e.Hint)
  55  	call := macro.Stop()
  56  	if w := dims.Size.X; gtx.Constraints.Min.X < w {
  57  		gtx.Constraints.Min.X = w
  58  	}
  59  	if h := dims.Size.Y; gtx.Constraints.Min.Y < h {
  60  		gtx.Constraints.Min.Y = h
  61  	}
  62  	dims = e.Editor.Layout(gtx, e.shaper, e.Font, e.TextSize)
  63  	disabled := gtx.Queue == nil
  64  	if e.Editor.Len() > 0 {
  65  		paint.ColorOp{Color: blendDisabledColor(disabled, e.SelectionColor)}.Add(gtx.Ops)
  66  		e.Editor.PaintSelection(gtx)
  67  		paint.ColorOp{Color: blendDisabledColor(disabled, e.Color)}.Add(gtx.Ops)
  68  		e.Editor.PaintText(gtx)
  69  	} else {
  70  		call.Add(gtx.Ops)
  71  	}
  72  	if !disabled {
  73  		paint.ColorOp{Color: e.Color}.Add(gtx.Ops)
  74  		e.Editor.PaintCaret(gtx)
  75  	}
  76  	return dims
  77  }
  78  
  79  func blendDisabledColor(disabled bool, c color.NRGBA) color.NRGBA {
  80  	if disabled {
  81  		return f32color.Disabled(c)
  82  	}
  83  	return c
  84  }
  85