cchat-gtk/internal/ui/primitives/completion/utils.go

126 lines
2.7 KiB
Go

package completion
import (
"github.com/diamondburned/cchat-gtk/internal/ui/primitives"
"github.com/gotk3/gotk3/gdk"
"github.com/gotk3/gotk3/gtk"
)
var popoverCSS = primitives.PrepareCSS(`
popover {
border-radius: 0;
}
`)
const (
MinPopoverWidth = 250
)
func NewPopover(relto gtk.IWidget) *gtk.Popover {
p, _ := gtk.PopoverNew(relto)
p.SetSizeRequest(MinPopoverWidth, -1)
p.SetModal(false)
p.SetPosition(gtk.POS_TOP)
primitives.AttachCSS(p, popoverCSS)
return p
}
type KeyDownHandlerFn = func(gtk.IWidget, *gdk.Event) bool
func KeyDownHandler(l *gtk.ListBox, focus func()) KeyDownHandlerFn {
return func(w gtk.IWidget, ev *gdk.Event) bool {
// Do we have any entries? If not, don't bother.
var length = int(l.GetChildren().Length())
if length == 0 {
// passthrough.
return false
}
var evKey = gdk.EventKeyNewFromEvent(ev)
var key = evKey.KeyVal()
switch key {
// Did we press an arrow key?
case gdk.KEY_Up, gdk.KEY_Down:
// Yes, start moving the list up and down.
i := l.GetSelectedRow().GetIndex()
switch key {
case gdk.KEY_Up:
if i--; i < 0 {
i = length - 1
}
case gdk.KEY_Down:
if i++; i >= length {
i = 0
}
}
row := l.GetRowAtIndex(i)
row.GrabFocus() // scroll
l.SelectRow(row) // select
focus() // unfocus
// Did we press the Enter or Tab key?
case gdk.KEY_Return, gdk.KEY_Tab:
// Activate the current row.
l.GetSelectedRow().Activate()
focus()
default:
// passthrough events if none matches.
return false
}
return true
}
}
func SwapWord(b *gtk.TextBuffer, word string, offset int) {
// Get iter for word replacing.
start, end := GetWordIters(b, offset)
b.Delete(start, end)
b.Insert(start, word+" ")
}
func CursorRect(i *gtk.TextView) gdk.Rectangle {
r, _ := i.GetCursorLocations(nil)
x, _ := i.BufferToWindowCoords(gtk.TEXT_WINDOW_WIDGET, r.GetX(), r.GetY())
r.SetX(x)
r.SetY(0)
return *r
}
func State(buf *gtk.TextBuffer) (string, int) {
// obtain current state
mark := buf.GetInsert()
iter := buf.GetIterAtMark(mark)
// obtain the input string and the current cursor position
start, end := buf.GetBounds()
text, _ := buf.GetText(start, end, true)
offset := iter.GetOffset()
return text, offset
}
func GetWordIters(buf *gtk.TextBuffer, offset int) (start, end *gtk.TextIter) {
iter := buf.GetIterAtOffset(offset)
var ok bool
// Seek backwards for space or start-of-line:
_, start, ok = iter.BackwardSearch(" ", gtk.TEXT_SEARCH_TEXT_ONLY, nil)
if !ok {
start = buf.GetStartIter()
}
// Seek forwards for space or end-of-line:
_, end, ok = iter.ForwardSearch(" ", gtk.TEXT_SEARCH_TEXT_ONLY, nil)
if !ok {
end = buf.GetEndIter()
}
return
}