Fixed some TabContainer and TextEdit bugs
This commit is contained in:
parent
03d0932b1a
commit
d7a5309e80
10
main.go
10
main.go
@ -68,12 +68,12 @@ func main() {
|
||||
|
||||
var fileSelector *ui.FileSelectorDialog // if nil, we don't draw it
|
||||
|
||||
bar := ui.NewMenuBar(nil, &theme)
|
||||
bar := ui.NewMenuBar(&theme)
|
||||
|
||||
barFocused := false
|
||||
|
||||
// TODO: load menus in another function
|
||||
bar.Menus = append(bar.Menus, ui.NewMenu("File", &theme, []ui.Item{&ui.ItemEntry{Name: "New File", Callback: func() {
|
||||
bar.AddMenu(ui.NewMenu("File", &theme, []ui.Item{&ui.ItemEntry{Name: "New File", Callback: func() {
|
||||
textEdit := ui.NewTextEdit(&s, "", "", &theme) // No file path, no contents
|
||||
tabContainer.AddTab("noname", textEdit)
|
||||
}}, &ui.ItemEntry{Name: "Open...", Callback: func() {
|
||||
@ -112,7 +112,7 @@ func main() {
|
||||
changeFocus(fileSelector)
|
||||
}}, &ui.ItemEntry{Name: "Save", Callback: func() {
|
||||
if tabContainer.GetTabCount() > 0 {
|
||||
tab := tabContainer.GetTab(tabContainer.Selected)
|
||||
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
||||
te := tab.Child.(*ui.TextEdit)
|
||||
if len(te.FilePath) > 0 {
|
||||
contents := te.String()
|
||||
@ -148,11 +148,11 @@ func main() {
|
||||
os.Exit(0)
|
||||
}}}))
|
||||
|
||||
bar.Menus = append(bar.Menus, ui.NewMenu("Edit", &theme, []ui.Item{&ui.ItemEntry{Name: "New", Callback: func() {
|
||||
bar.AddMenu(ui.NewMenu("Edit", &theme, []ui.Item{&ui.ItemEntry{Name: "New", Callback: func() {
|
||||
s.Beep()
|
||||
}}}))
|
||||
|
||||
bar.Menus = append(bar.Menus, ui.NewMenu("Search", &theme, []ui.Item{&ui.ItemEntry{Name: "New", Callback: func() {
|
||||
bar.AddMenu(ui.NewMenu("Search", &theme, []ui.Item{&ui.ItemEntry{Name: "New", Callback: func() {
|
||||
s.Beep()
|
||||
}}}))
|
||||
|
||||
|
@ -107,12 +107,11 @@ type Tab struct {
|
||||
|
||||
// A TabContainer organizes children by showing only one of them at a time.
|
||||
type TabContainer struct {
|
||||
Selected int
|
||||
|
||||
children []Tab
|
||||
x, y int
|
||||
width, height int
|
||||
focused bool
|
||||
selected int
|
||||
|
||||
Theme *Theme
|
||||
}
|
||||
@ -143,6 +142,28 @@ func (c *TabContainer) RemoveTab(idx int) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// FocusTab sets the visible tab to the one at `idx`. FocusTab clamps `idx`
|
||||
// between 0 and tab_count - 1. If no tabs are present, the function does nothing.
|
||||
func (c *TabContainer) FocusTab(idx int) {
|
||||
if len(c.children) < 1 {
|
||||
return
|
||||
}
|
||||
|
||||
if idx < 0 {
|
||||
idx = 0
|
||||
} else if idx >= len(c.children) {
|
||||
idx = len(c.children)-1
|
||||
}
|
||||
|
||||
c.children[c.selected].Child.SetFocused(false) // Unfocus old tab
|
||||
c.children[idx].Child.SetFocused(true) // Focus new tab
|
||||
c.selected = idx
|
||||
}
|
||||
|
||||
func (c *TabContainer) GetSelectedTabIdx() int {
|
||||
return c.selected
|
||||
}
|
||||
|
||||
func (c *TabContainer) GetTabCount() int {
|
||||
return len(c.children)
|
||||
}
|
||||
@ -166,7 +187,7 @@ func (c *TabContainer) Draw(s tcell.Screen) {
|
||||
col := c.x + c.width/2 - combinedTabLength/2 // Starting column
|
||||
for i, tab := range c.children {
|
||||
var sty tcell.Style
|
||||
if c.Selected == i {
|
||||
if c.selected == i {
|
||||
sty = c.Theme.GetOrDefault("TabSelected")
|
||||
} else {
|
||||
sty = c.Theme.GetOrDefault("Tab")
|
||||
@ -178,16 +199,16 @@ func (c *TabContainer) Draw(s tcell.Screen) {
|
||||
}
|
||||
|
||||
// Draw selected child in center
|
||||
if c.Selected < len(c.children) {
|
||||
c.children[c.Selected].Child.Draw(s)
|
||||
if c.selected < len(c.children) {
|
||||
c.children[c.selected].Child.Draw(s)
|
||||
}
|
||||
}
|
||||
|
||||
// SetFocused calls SetFocused on the visible child Component.
|
||||
func (c *TabContainer) SetFocused(v bool) {
|
||||
c.focused = v
|
||||
if c.Selected < len(c.children) {
|
||||
c.children[c.Selected].Child.SetFocused(v)
|
||||
if c.selected < len(c.children) {
|
||||
c.children[c.selected].Child.SetFocused(v)
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,8 +232,8 @@ func (c *TabContainer) GetPos() (int, int) {
|
||||
// SetPos sets the position of the container and updates the child Component.
|
||||
func (c *TabContainer) SetPos(x, y int) {
|
||||
c.x, c.y = x, y
|
||||
if c.Selected < len(c.children) {
|
||||
c.children[c.Selected].Child.SetPos(x+1, y+1)
|
||||
if c.selected < len(c.children) {
|
||||
c.children[c.selected].Child.SetPos(x+1, y+1)
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,8 +245,8 @@ func (c *TabContainer) GetSize() (int, int) {
|
||||
// SetSize sets the size of the container and updates the size of the child Component.
|
||||
func (c *TabContainer) SetSize(width, height int) {
|
||||
c.width, c.height = width, height
|
||||
if c.Selected < len(c.children) {
|
||||
c.children[c.Selected].Child.SetSize(width-2, height-2)
|
||||
if c.selected < len(c.children) {
|
||||
c.children[c.selected].Child.SetSize(width-2, height-2)
|
||||
}
|
||||
}
|
||||
|
||||
@ -233,24 +254,27 @@ func (c *TabContainer) SetSize(width, height int) {
|
||||
func (c *TabContainer) HandleEvent(event tcell.Event) bool {
|
||||
switch ev := event.(type) {
|
||||
case *tcell.EventKey:
|
||||
if ev.Key() == tcell.KeyTab { // Ctrl + Tab was pressed
|
||||
if ev.Modifiers() == tcell.ModCtrl {
|
||||
c.Selected++
|
||||
if c.Selected >= len(c.children) {
|
||||
c.Selected = 0
|
||||
}
|
||||
} else if ev.Modifiers() == tcell.ModCtrl&tcell.ModShift { // Ctrl + Shift + Tab was pressed
|
||||
c.Selected--
|
||||
if c.Selected < 0 {
|
||||
c.Selected = len(c.children) - 1
|
||||
}
|
||||
if ev.Key() == tcell.KeyCtrlE {
|
||||
newIdx := c.selected + 1
|
||||
if newIdx >= len(c.children) {
|
||||
newIdx = 0
|
||||
}
|
||||
c.FocusTab(newIdx)
|
||||
return true
|
||||
} else if ev.Key() == tcell.KeyCtrlW {
|
||||
newIdx := c.selected - 1
|
||||
if newIdx < 0 {
|
||||
newIdx = len(c.children) - 1
|
||||
}
|
||||
c.FocusTab(newIdx)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if c.Selected < len(c.children) {
|
||||
return c.children[c.Selected].Child.HandleEvent(event)
|
||||
if c.selected < len(c.children) {
|
||||
return c.children[c.selected].Child.HandleEvent(event)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
|
32
ui/menu.go
32
ui/menu.go
@ -45,7 +45,7 @@ func (m *Menu) GetName() string {
|
||||
|
||||
// A MenuBar is a horizontal list of menus.
|
||||
type MenuBar struct {
|
||||
Menus []Menu
|
||||
Menus []*Menu
|
||||
|
||||
x, y int
|
||||
width, height int
|
||||
@ -55,17 +55,20 @@ type MenuBar struct {
|
||||
Theme *Theme
|
||||
}
|
||||
|
||||
func NewMenuBar(menus []Menu, theme *Theme) *MenuBar {
|
||||
if menus == nil {
|
||||
menus = make([]Menu, 0, 6)
|
||||
}
|
||||
|
||||
func NewMenuBar(theme *Theme) *MenuBar {
|
||||
return &MenuBar{
|
||||
Menus: menus,
|
||||
Menus: make([]*Menu, 0, 6),
|
||||
Theme: theme,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *MenuBar) AddMenu(menu *Menu) {
|
||||
menu.itemSelectedCallback = func() {
|
||||
|
||||
}
|
||||
b.Menus = append(b.Menus, menu)
|
||||
}
|
||||
|
||||
// GetMenuXPos returns the X position of the name of Menu at `idx` visually.
|
||||
func (b *MenuBar) GetMenuXPos(idx int) int {
|
||||
x := 1
|
||||
@ -143,8 +146,8 @@ func (b *MenuBar) HandleEvent(event tcell.Event) bool {
|
||||
case *tcell.EventKey:
|
||||
if ev.Key() == tcell.KeyEnter && !b.Menus[b.selected].Visible {
|
||||
menu := &b.Menus[b.selected]
|
||||
menu.SetPos(b.GetMenuXPos(b.selected), b.y+1)
|
||||
menu.SetFocused(true) // Makes .Visible true for the Menu
|
||||
(*menu).SetPos(b.GetMenuXPos(b.selected), b.y+1)
|
||||
(*menu).SetFocused(true) // Makes .Visible true for the Menu
|
||||
} else if ev.Key() == tcell.KeyLeft {
|
||||
if b.selected <= 0 {
|
||||
b.selected = len(b.Menus) - 1 // Wrap to end
|
||||
@ -179,20 +182,21 @@ type Menu struct {
|
||||
Items []Item
|
||||
Visible bool // True when focused
|
||||
|
||||
x, y int
|
||||
width, height int // Size may not be settable
|
||||
selected int // Index of selected Item
|
||||
x, y int
|
||||
width, height int // Size may not be settable
|
||||
selected int // Index of selected Item
|
||||
itemSelectedCallback func() // Used internally to hide menus on selection
|
||||
|
||||
Theme *Theme
|
||||
}
|
||||
|
||||
// New creates a new Menu. `items` can be `nil`.
|
||||
func NewMenu(name string, theme *Theme, items []Item) Menu {
|
||||
func NewMenu(name string, theme *Theme, items []Item) *Menu {
|
||||
if items == nil {
|
||||
items = make([]Item, 0, 6)
|
||||
}
|
||||
|
||||
return Menu{
|
||||
return &Menu{
|
||||
Name: name,
|
||||
Items: items,
|
||||
Theme: theme,
|
||||
|
@ -334,7 +334,7 @@ func (t *TextEdit) Draw(s tcell.Screen) {
|
||||
func (t *TextEdit) SetFocused(v bool) {
|
||||
t.focused = v
|
||||
if v {
|
||||
t.SetLineCol(t.curx, t.cury)
|
||||
t.SetLineCol(t.cury, t.curx)
|
||||
} else {
|
||||
(*t.screen).HideCursor()
|
||||
}
|
||||
@ -387,6 +387,10 @@ func (t *TextEdit) HandleEvent(event tcell.Event) bool {
|
||||
t.SetLineCol(t.cury, 0)
|
||||
case tcell.KeyEnd:
|
||||
t.SetLineCol(t.cury, len(t.buffer[t.cury]))
|
||||
case tcell.KeyPgUp:
|
||||
t.SetLineCol(t.scrolly - t.height, t.curx) // Go a page up
|
||||
case tcell.KeyPgDn:
|
||||
t.SetLineCol(t.scrolly + t.height*2 - 1, t.curx) // Go a page down
|
||||
|
||||
// Deleting
|
||||
case tcell.KeyBackspace:
|
||||
|
Loading…
x
Reference in New Issue
Block a user