...

Source file src/code.rocket9labs.com/tslocum/etk/input.go

Documentation: code.rocket9labs.com/tslocum/etk

     1  package etk
     2  
     3  import (
     4  	"image"
     5  	"image/color"
     6  
     7  	"code.rocket9labs.com/tslocum/etk/messeji"
     8  	"github.com/hajimehoshi/ebiten/v2"
     9  	"golang.org/x/image/font/sfnt"
    10  )
    11  
    12  // Input is a text input widget. The Input widget is simply a Text widget that
    13  // also accepts user input.
    14  type Input struct {
    15  	*Box
    16  	field           *messeji.InputField
    17  	cursor          string
    18  	borderSize      int
    19  	borderFocused   color.RGBA
    20  	borderUnfocused color.RGBA
    21  	focus           bool
    22  }
    23  
    24  // NewInput returns a new Input widget.
    25  func NewInput(text string, onSelected func(text string) (handled bool)) *Input {
    26  	textColor := Style.TextColorDark
    27  	/*if TextColor == nil {
    28  		textColor = Style.InputColor
    29  	}*/
    30  
    31  	f := messeji.NewInputField(FontFace(Style.TextFont, Scale(Style.TextSize)), fontMutex)
    32  	f.SetForegroundColor(textColor)
    33  	f.SetBackgroundColor(transparent)
    34  	f.SetScrollBarColors(Style.ScrollAreaColor, Style.ScrollHandleColor)
    35  	f.SetScrollBorderSize(Scale(Style.ScrollBorderSize))
    36  	f.SetScrollBorderColors(Style.ScrollBorderTop, Style.ScrollBorderRight, Style.ScrollBorderBottom, Style.ScrollBorderLeft)
    37  	f.SetPrefix("")
    38  	f.SetSuffix("")
    39  	f.SetText(text)
    40  	f.SetHandleKeyboard(true)
    41  	f.SetSelectedFunc(func() (accept bool) {
    42  		return onSelected(f.Text())
    43  	})
    44  
    45  	i := &Input{
    46  		Box:             NewBox(),
    47  		field:           f,
    48  		cursor:          "_",
    49  		borderSize:      Scale(Style.InputBorderSize),
    50  		borderFocused:   Style.InputBorderFocused,
    51  		borderUnfocused: Style.InputBorderUnfocused,
    52  	}
    53  	i.SetBackground(Style.InputBgColor)
    54  	return i
    55  }
    56  
    57  // SetRect sets the position and size of the widget.
    58  func (i *Input) SetRect(r image.Rectangle) {
    59  	i.Box.rect = r
    60  
    61  	i.field.SetRect(r)
    62  
    63  	for _, w := range i.children {
    64  		w.SetRect(r)
    65  	}
    66  }
    67  
    68  // SetBorderSize sets the size of the border around the field.
    69  func (i *Input) SetBorderSize(size int) {
    70  	i.Lock()
    71  	defer i.Unlock()
    72  
    73  	i.borderSize = size
    74  }
    75  
    76  // SetBorderColors sets the border colors of the field when focused and unfocused.
    77  func (i *Input) SetBorderColors(focused color.RGBA, unfocused color.RGBA) {
    78  	i.Lock()
    79  	defer i.Unlock()
    80  
    81  	i.borderFocused = focused
    82  	i.borderUnfocused = unfocused
    83  }
    84  
    85  // Foreground return the color of the text within the field.
    86  func (i *Input) Foreground() color.RGBA {
    87  	i.Lock()
    88  	defer i.Unlock()
    89  
    90  	return i.field.ForegroundColor()
    91  }
    92  
    93  // SetForegroundColor sets the color of the text within the field.
    94  func (i *Input) SetForeground(c color.RGBA) {
    95  	i.Lock()
    96  	defer i.Unlock()
    97  
    98  	i.field.SetForegroundColor(c)
    99  }
   100  
   101  // SetPrefix sets the text shown before the input text.
   102  func (i *Input) SetPrefix(prefix string) {
   103  	i.Lock()
   104  	defer i.Unlock()
   105  
   106  	i.field.SetPrefix(prefix)
   107  }
   108  
   109  // SetSuffix sets the text shown after the input text.
   110  func (i *Input) SetSuffix(suffix string) {
   111  	i.Lock()
   112  	defer i.Unlock()
   113  
   114  	i.field.SetSuffix(suffix)
   115  }
   116  
   117  // SetCursor sets the cursor appended to the text buffer when focused.
   118  func (i *Input) SetCursor(cursor string) {
   119  	i.Lock()
   120  	defer i.Unlock()
   121  
   122  	i.cursor = cursor
   123  	if i.focus {
   124  		i.field.SetSuffix(cursor)
   125  	}
   126  }
   127  
   128  // Focus returns the focus state of the widget.
   129  func (i *Input) Focus() bool {
   130  	return i.focus
   131  }
   132  
   133  // SetFocus sets the focus state of the widget.
   134  func (i *Input) SetFocus(focus bool) bool {
   135  	i.focus = focus
   136  
   137  	var cursor string
   138  	if focus {
   139  		cursor = i.cursor
   140  	}
   141  	i.field.SetSuffix(cursor)
   142  	return true
   143  }
   144  
   145  // Text returns the content of the text buffer.
   146  func (i *Input) Text() string {
   147  	i.Lock()
   148  	defer i.Unlock()
   149  
   150  	return i.field.Text()
   151  }
   152  
   153  // SetText sets the text in the field.
   154  func (i *Input) SetText(text string) {
   155  	i.Lock()
   156  	defer i.Unlock()
   157  
   158  	i.field.SetText(text)
   159  }
   160  
   161  // SetScrollBarWidth sets the width of the scroll bar.
   162  func (i *Input) SetScrollBarWidth(width int) {
   163  	i.Lock()
   164  	defer i.Unlock()
   165  
   166  	i.field.SetScrollBarWidth(width)
   167  }
   168  
   169  // SetScrollBarColors sets the color of the scroll bar area and handle.
   170  func (i *Input) SetScrollBarColors(area color.RGBA, handle color.RGBA) {
   171  	i.Lock()
   172  	defer i.Unlock()
   173  
   174  	i.field.SetScrollBarColors(Style.ScrollAreaColor, Style.ScrollHandleColor)
   175  }
   176  
   177  // SetScrollBarVisible sets whether the scroll bar is visible on the screen.
   178  func (i *Input) SetScrollBarVisible(scrollVisible bool) {
   179  	i.Lock()
   180  	defer i.Unlock()
   181  
   182  	i.field.SetScrollBarVisible(scrollVisible)
   183  }
   184  
   185  // SetAutoHideScrollBar sets whether the scroll bar is automatically hidden
   186  // when the entire text buffer is visible.
   187  func (i *Input) SetAutoHideScrollBar(autoHide bool) {
   188  	i.Lock()
   189  	defer i.Unlock()
   190  
   191  	i.field.SetAutoHideScrollBar(autoHide)
   192  }
   193  
   194  // SetFont sets the font and text size of the field. Scaling is not applied.
   195  func (t *Input) SetFont(fnt *sfnt.Font, size int) {
   196  	t.Lock()
   197  	defer t.Unlock()
   198  
   199  	t.field.SetFont(FontFace(fnt, size), fontMutex)
   200  }
   201  
   202  // Padding returns the amount of padding around the text within the field.
   203  func (i *Input) Padding() int {
   204  	i.Lock()
   205  	defer i.Unlock()
   206  
   207  	return i.field.Padding()
   208  }
   209  
   210  // SetPadding sets the amount of padding around the text within the field.
   211  func (i *Input) SetPadding(padding int) {
   212  	i.Lock()
   213  	defer i.Unlock()
   214  
   215  	i.field.SetPadding(padding)
   216  }
   217  
   218  // SetWordWrap sets a flag which, when enabled, causes text to wrap without breaking words.
   219  func (i *Input) SetWordWrap(wrap bool) {
   220  	i.Lock()
   221  	defer i.Unlock()
   222  
   223  	i.field.SetWordWrap(wrap)
   224  }
   225  
   226  // SetHorizontal sets the horizontal alignment of the text within the field.
   227  func (i *Input) SetHorizontal(h Alignment) {
   228  	i.Lock()
   229  	defer i.Unlock()
   230  
   231  	i.field.SetHorizontal(messeji.Alignment(h))
   232  }
   233  
   234  // SetVertical sets the vertical alignment of the text within the field.
   235  func (i *Input) SetVertical(v Alignment) {
   236  	i.Lock()
   237  	defer i.Unlock()
   238  
   239  	i.field.SetVertical(messeji.Alignment(v))
   240  }
   241  
   242  // SetMask sets the rune used to mask the text buffer contents. Set to 0 to disable.
   243  func (i *Input) SetMask(r rune) {
   244  	i.Lock()
   245  	defer i.Unlock()
   246  
   247  	i.field.SetMask(r)
   248  }
   249  
   250  // Cursor returns the cursor shape shown when a mouse cursor hovers over the
   251  // widget, or -1 to let widgets beneath determine the cursor shape.
   252  func (i *Input) Cursor() ebiten.CursorShapeType {
   253  	return ebiten.CursorShapeText
   254  }
   255  
   256  // Write writes to the text buffer.
   257  func (i *Input) Write(p []byte) (n int, err error) {
   258  	return i.field.Write(p)
   259  }
   260  
   261  // HandleKeyboard is called when a keyboard event occurs.
   262  func (i *Input) HandleKeyboard(key ebiten.Key, r rune) (handled bool, err error) {
   263  	if !i.focus {
   264  		return false, nil
   265  	}
   266  
   267  	return i.field.HandleKeyboardEvent(key, r)
   268  }
   269  
   270  // HandleMouse is called when a mouse event occurs.
   271  func (i *Input) HandleMouse(cursor image.Point, pressed bool, clicked bool) (handled bool, err error) {
   272  	return i.field.HandleMouseEvent(cursor, pressed, clicked)
   273  }
   274  
   275  // Draw draws the widget on the screen.
   276  func (i *Input) Draw(screen *ebiten.Image) error {
   277  	i.field.Draw(screen)
   278  
   279  	// Draw border.
   280  	if i.borderSize == 0 {
   281  		return nil
   282  	}
   283  	r := i.rect
   284  	c := i.borderUnfocused
   285  	if i.focus {
   286  		c = i.borderFocused
   287  	}
   288  	screen.SubImage(image.Rect(r.Min.X, r.Min.Y, r.Min.X+i.borderSize, r.Max.Y)).(*ebiten.Image).Fill(c)
   289  	screen.SubImage(image.Rect(r.Min.X, r.Min.Y, r.Max.X, r.Min.Y+i.borderSize)).(*ebiten.Image).Fill(c)
   290  	screen.SubImage(image.Rect(r.Max.X-i.borderSize, r.Min.Y, r.Max.X, r.Max.Y)).(*ebiten.Image).Fill(c)
   291  	screen.SubImage(image.Rect(r.Min.X, r.Max.Y-i.borderSize, r.Max.X, r.Max.Y)).(*ebiten.Image).Fill(c)
   292  	return nil
   293  }
   294  

View as plain text