Main: more robust error handling.
Previously, the editor would panic at any error. After I recently implemented dialogs, I changed all panics to create error dialogs, instead. This will make the editor more stable.
This commit is contained in:
parent
f64af6fa29
commit
d1dd389dba
210
main.go
210
main.go
@ -25,6 +25,8 @@ var theme = ui.Theme{
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
screen tcell.Screen
|
||||||
|
|
||||||
menuBar *ui.MenuBar
|
menuBar *ui.MenuBar
|
||||||
tabContainer *ui.TabContainer
|
tabContainer *ui.TabContainer
|
||||||
dialog ui.Component // nil if not present (has exclusive focus)
|
dialog ui.Component // nil if not present (has exclusive focus)
|
||||||
@ -40,6 +42,58 @@ func changeFocus(to ui.Component) {
|
|||||||
to.SetFocused(true)
|
to.SetFocused(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func showErrorDialog(title string, message string, callback func()) {
|
||||||
|
dialog = ui.NewMessageDialog(title, message, ui.MessageKindError, nil, &theme, func(string) {
|
||||||
|
if callback != nil {
|
||||||
|
callback()
|
||||||
|
} else {
|
||||||
|
dialog = nil
|
||||||
|
changeFocus(tabContainer) // Default behavior: focus tabContainer
|
||||||
|
}
|
||||||
|
})
|
||||||
|
changeFocus(dialog)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shows the Save As... dialog for saving unnamed files
|
||||||
|
func saveAs() {
|
||||||
|
callback := func(filePaths []string) {
|
||||||
|
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
||||||
|
te := tab.Child.(*ui.TextEdit)
|
||||||
|
|
||||||
|
// If we got the callback, it is safe to assume there are one or more files
|
||||||
|
f, err := os.OpenFile(filePaths[0], os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fs.ModePerm)
|
||||||
|
if err != nil {
|
||||||
|
showErrorDialog("Could not open file for writing", fmt.Sprintf("File at %#v could not be opened with write permissions. Maybe another program has it open? %v", filePaths[0], err), nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
_, err = te.Buffer.WriteTo(f)
|
||||||
|
if err != nil {
|
||||||
|
showErrorDialog("Failed to write to file", fmt.Sprintf("File at %#v was opened for writing, but an error occurred while writing the buffer. %v", filePaths[0], err), nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
te.Dirty = false
|
||||||
|
|
||||||
|
dialog = nil // Hide the file selector
|
||||||
|
changeFocus(tabContainer)
|
||||||
|
tab.Name = filePaths[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog = ui.NewFileSelectorDialog(
|
||||||
|
&screen,
|
||||||
|
"Select a file to overwrite",
|
||||||
|
false,
|
||||||
|
&theme,
|
||||||
|
callback,
|
||||||
|
func() { // Dialog canceled
|
||||||
|
dialog = nil
|
||||||
|
changeFocus(tabContainer)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
changeFocus(dialog)
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if *cpuprofile != "" {
|
if *cpuprofile != "" {
|
||||||
@ -54,38 +108,31 @@ func main() {
|
|||||||
defer pprof.StopCPUProfile()
|
defer pprof.StopCPUProfile()
|
||||||
}
|
}
|
||||||
|
|
||||||
s, e := tcell.NewScreen()
|
screen, err := tcell.NewScreen()
|
||||||
if e != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "%v\n", e)
|
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
if e := s.Init(); e != nil {
|
if err := screen.Init(); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "%v\n", e)
|
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
defer s.Fini() // Useful for handling panics
|
defer screen.Fini() // Useful for handling panics
|
||||||
|
|
||||||
var closing bool
|
var closing bool
|
||||||
sizex, sizey := s.Size()
|
sizex, sizey := screen.Size()
|
||||||
|
|
||||||
tabContainer = ui.NewTabContainer(&theme)
|
tabContainer = ui.NewTabContainer(&theme)
|
||||||
tabContainer.SetPos(0, 1)
|
tabContainer.SetPos(0, 1)
|
||||||
tabContainer.SetSize(sizex, sizey-2)
|
tabContainer.SetSize(sizex, sizey-2)
|
||||||
|
|
||||||
_, err := ClipInitialize(ClipExternal)
|
changeFocus(tabContainer) // tabContainer focused by default
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Open files from command-line arguments
|
// Open files from command-line arguments
|
||||||
if len(os.Args) > 1 {
|
if flag.NArg() > 0 {
|
||||||
for i := 1; i < len(os.Args); i++ {
|
for i := 0; i < flag.NArg(); i++ {
|
||||||
if os.Args[i] == "-cpuprofile" || os.Args[i] == "-memprofile" {
|
arg := flag.Arg(i)
|
||||||
i++
|
_, err := os.Stat(arg)
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := os.Stat(os.Args[i])
|
|
||||||
|
|
||||||
var dirty bool
|
var dirty bool
|
||||||
var bytes []byte
|
var bytes []byte
|
||||||
@ -93,59 +140,30 @@ func main() {
|
|||||||
if errors.Is(err, os.ErrNotExist) { // If the file does not exist...
|
if errors.Is(err, os.ErrNotExist) { // If the file does not exist...
|
||||||
dirty = true
|
dirty = true
|
||||||
} else { // If the file exists...
|
} else { // If the file exists...
|
||||||
file, err := os.Open(os.Args[i])
|
file, err := os.Open(arg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("File could not be opened at path " + os.Args[i])
|
showErrorDialog("File could not be opened", fmt.Sprintf("File at %#v could not be opened. %v", arg, err), nil)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
bytes, err = ioutil.ReadAll(file)
|
bytes, err = ioutil.ReadAll(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("Could not read all of " + os.Args[i])
|
showErrorDialog("Could not read file", fmt.Sprintf("File at %#v was opened, but could not be read. %v", arg, err), nil)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
textEdit := ui.NewTextEdit(&s, os.Args[i], bytes, &theme)
|
textEdit := ui.NewTextEdit(&screen, arg, bytes, &theme)
|
||||||
textEdit.Dirty = dirty
|
textEdit.Dirty = dirty
|
||||||
tabContainer.AddTab(os.Args[i], textEdit)
|
tabContainer.AddTab(arg, textEdit)
|
||||||
}
|
}
|
||||||
|
tabContainer.SetFocused(true) // Lets any opened TextEdit component know to be focused
|
||||||
}
|
}
|
||||||
|
|
||||||
saveAs := func() {
|
_, err = ClipInitialize(ClipExternal)
|
||||||
callback := func(filePaths []string) {
|
|
||||||
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
|
||||||
te := tab.Child.(*ui.TextEdit)
|
|
||||||
|
|
||||||
// If we got the callback, it is safe to assume there are one or more files
|
|
||||||
f, err := os.OpenFile(filePaths[0], os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fs.ModePerm)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
showErrorDialog("Error Initializing Clipboard", fmt.Sprintf("%v\n\nAn internal clipboard will be used, instead.", err), nil)
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
_, err = te.Buffer.WriteTo(f)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprint("Error occurred while writing buffer to file: ", err))
|
|
||||||
}
|
|
||||||
te.Dirty = false
|
|
||||||
|
|
||||||
dialog = nil // Hide the file selector
|
|
||||||
changeFocus(tabContainer)
|
|
||||||
tab.Name = filePaths[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
dialog = ui.NewFileSelectorDialog(
|
|
||||||
&s,
|
|
||||||
"Select a file to overwrite",
|
|
||||||
false,
|
|
||||||
&theme,
|
|
||||||
callback,
|
|
||||||
func() { // Dialog canceled
|
|
||||||
dialog = nil
|
|
||||||
changeFocus(tabContainer)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
changeFocus(dialog)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
menuBar = ui.NewMenuBar(&theme)
|
menuBar = ui.NewMenuBar(&theme)
|
||||||
@ -153,35 +171,44 @@ func main() {
|
|||||||
fileMenu := ui.NewMenu("File", 0, &theme)
|
fileMenu := ui.NewMenu("File", 0, &theme)
|
||||||
|
|
||||||
fileMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "New File", Shortcut: "Ctrl+N", Callback: func() {
|
fileMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "New File", Shortcut: "Ctrl+N", Callback: func() {
|
||||||
textEdit := ui.NewTextEdit(&s, "", []byte{}, &theme) // No file path, no contents
|
textEdit := ui.NewTextEdit(&screen, "", []byte{}, &theme) // No file path, no contents
|
||||||
tabContainer.AddTab("noname", textEdit)
|
tabContainer.AddTab("noname", textEdit)
|
||||||
|
|
||||||
changeFocus(tabContainer)
|
changeFocus(tabContainer)
|
||||||
tabContainer.FocusTab(tabContainer.GetTabCount()-1)
|
tabContainer.FocusTab(tabContainer.GetTabCount()-1)
|
||||||
}}, &ui.ItemEntry{Name: "Open...", Shortcut: "Ctrl+O", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Open...", Shortcut: "Ctrl+O", Callback: func() {
|
||||||
callback := func(filePaths []string) {
|
callback := func(filePaths []string) {
|
||||||
|
var errOccurred bool
|
||||||
for _, path := range filePaths {
|
for _, path := range filePaths {
|
||||||
file, err := os.Open(path)
|
file, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("Could not open file at path " + path)
|
showErrorDialog("File could not be opened", fmt.Sprintf("File at %#v could not be opened. %v", path, err), nil)
|
||||||
|
errOccurred = true
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
bytes, err := ioutil.ReadAll(file)
|
bytes, err := ioutil.ReadAll(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("Could not read all of file")
|
showErrorDialog("Could not read file", fmt.Sprintf("File at %#v was opened, but could not be read. %v", path, err), nil)
|
||||||
|
errOccurred = true
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
textEdit := ui.NewTextEdit(&s, path, bytes, &theme)
|
textEdit := ui.NewTextEdit(&screen, path, bytes, &theme)
|
||||||
tabContainer.AddTab(path, textEdit)
|
tabContainer.AddTab(path, textEdit)
|
||||||
}
|
}
|
||||||
dialog = nil // Hide the file selector
|
|
||||||
|
|
||||||
|
if !errOccurred { // Prevent hiding the error dialog
|
||||||
|
dialog = nil // Hide the file selector
|
||||||
changeFocus(tabContainer)
|
changeFocus(tabContainer)
|
||||||
|
if tabContainer.GetTabCount() > 0 {
|
||||||
tabContainer.FocusTab(tabContainer.GetTabCount()-1)
|
tabContainer.FocusTab(tabContainer.GetTabCount()-1)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
dialog = ui.NewFileSelectorDialog(
|
dialog = ui.NewFileSelectorDialog(
|
||||||
&s,
|
&screen,
|
||||||
"Comma-separated files or a directory",
|
"Comma-separated files or a directory",
|
||||||
true,
|
true,
|
||||||
&theme,
|
&theme,
|
||||||
@ -199,13 +226,15 @@ func main() {
|
|||||||
if te.FilePath != "" {
|
if te.FilePath != "" {
|
||||||
f, err := os.OpenFile(te.FilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fs.ModePerm)
|
f, err := os.OpenFile(te.FilePath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, fs.ModePerm)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
showErrorDialog("Could not open file for writing", fmt.Sprintf("File at %#v could not be opened with write permissions. Maybe another program has it open? %v", te.FilePath, err), nil)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
_, err = te.Buffer.WriteTo(f) // TODO: check count
|
_, err = te.Buffer.WriteTo(f) // TODO: check count
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprint("Error occurred while writing buffer to file: ", err))
|
showErrorDialog("Failed to write to file", fmt.Sprintf("File at %#v was opened for writing, but an error occurred while writing the buffer. %v", te.FilePath, err), nil)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
te.Dirty = false
|
te.Dirty = false
|
||||||
|
|
||||||
@ -256,23 +285,34 @@ func main() {
|
|||||||
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
||||||
te := tab.Child.(*ui.TextEdit)
|
te := tab.Child.(*ui.TextEdit)
|
||||||
bytes := te.GetSelectedBytes()
|
bytes := te.GetSelectedBytes()
|
||||||
|
var err error
|
||||||
if len(bytes) > 0 { // If something is selected...
|
if len(bytes) > 0 { // If something is selected...
|
||||||
te.Delete(false) // Delete the selection
|
te.Delete(false) // Delete the selection
|
||||||
// TODO: better error handling within editor
|
err = ClipWrite(string(bytes)) // Add the selectedStr to clipboard
|
||||||
_ = ClipWrite(string(bytes)) // Add the selectedStr to clipboard
|
if err != nil {
|
||||||
|
showErrorDialog("Clipboard Failure", fmt.Sprintf("%v", err), nil)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if err == nil { // Prevent hiding error dialog
|
||||||
changeFocus(tabContainer)
|
changeFocus(tabContainer)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}}, &ui.ItemEntry{Name: "Copy", Shortcut: "Ctrl+C", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Copy", Shortcut: "Ctrl+C", Callback: func() {
|
||||||
if tabContainer.GetTabCount() > 0 {
|
if tabContainer.GetTabCount() > 0 {
|
||||||
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
||||||
te := tab.Child.(*ui.TextEdit)
|
te := tab.Child.(*ui.TextEdit)
|
||||||
bytes := te.GetSelectedBytes()
|
bytes := te.GetSelectedBytes()
|
||||||
|
var err error
|
||||||
if len(bytes) > 0 { // If there is something selected...
|
if len(bytes) > 0 { // If there is something selected...
|
||||||
_ = ClipWrite(string(bytes)) // Add selectedStr to clipboard
|
err = ClipWrite(string(bytes)) // Add selectedStr to clipboard
|
||||||
|
if err != nil {
|
||||||
|
showErrorDialog("Clipboard Failure", fmt.Sprintf("%v", err), nil)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
changeFocus(tabContainer)
|
changeFocus(tabContainer)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}}, &ui.ItemEntry{Name: "Paste", Shortcut: "Ctrl+V", Callback: func() {
|
}}, &ui.ItemEntry{Name: "Paste", Shortcut: "Ctrl+V", Callback: func() {
|
||||||
if tabContainer.GetTabCount() > 0 {
|
if tabContainer.GetTabCount() > 0 {
|
||||||
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
tab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
||||||
@ -280,12 +320,12 @@ func main() {
|
|||||||
|
|
||||||
contents, err := ClipRead()
|
contents, err := ClipRead()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
showErrorDialog("Clipboard Failure", fmt.Sprintf("%v", err), nil)
|
||||||
}
|
} else {
|
||||||
te.Insert(contents)
|
te.Insert(contents)
|
||||||
|
|
||||||
changeFocus(tabContainer)
|
changeFocus(tabContainer)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "Select All", QuickChar: 7, Shortcut: "Ctrl+A", Callback: func() {
|
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "Select All", QuickChar: 7, Shortcut: "Ctrl+A", Callback: func() {
|
||||||
|
|
||||||
}}, &ui.ItemEntry{Name: "Select Line", QuickChar: 7, Callback: func() {
|
}}, &ui.ItemEntry{Name: "Select Line", QuickChar: 7, Callback: func() {
|
||||||
@ -295,7 +335,7 @@ func main() {
|
|||||||
searchMenu := ui.NewMenu("Search", 0, &theme)
|
searchMenu := ui.NewMenu("Search", 0, &theme)
|
||||||
|
|
||||||
searchMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "Find and Replace...", Shortcut: "Ctrl+F", Callback: func() {
|
searchMenu.AddItems([]ui.Item{&ui.ItemEntry{Name: "Find and Replace...", Shortcut: "Ctrl+F", Callback: func() {
|
||||||
s.Beep()
|
screen.Beep()
|
||||||
}}, &ui.ItemEntry{Name: "Find in Directory...", QuickChar: 8, Callback: func() {
|
}}, &ui.ItemEntry{Name: "Find in Directory...", QuickChar: 8, Callback: func() {
|
||||||
|
|
||||||
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "Go to line...", Shortcut: "Ctrl+G", Callback: func() {
|
}}, &ui.ItemSeparator{}, &ui.ItemEntry{Name: "Go to line...", Shortcut: "Ctrl+G", Callback: func() {
|
||||||
@ -307,18 +347,16 @@ func main() {
|
|||||||
menuBar.AddMenu(editMenu)
|
menuBar.AddMenu(editMenu)
|
||||||
menuBar.AddMenu(searchMenu)
|
menuBar.AddMenu(searchMenu)
|
||||||
|
|
||||||
changeFocus(tabContainer) // TabContainer is focused by default
|
|
||||||
|
|
||||||
for !closing {
|
for !closing {
|
||||||
s.Clear()
|
screen.Clear()
|
||||||
|
|
||||||
// Draw background (grey and black checkerboard)
|
// Draw background (grey and black checkerboard)
|
||||||
ui.DrawRect(s, 0, 0, sizex, sizey, '▚', tcell.Style{}.Foreground(tcell.ColorGrey).Background(tcell.ColorBlack))
|
ui.DrawRect(screen, 0, 0, sizex, sizey, '▚', tcell.Style{}.Foreground(tcell.ColorGrey).Background(tcell.ColorBlack))
|
||||||
|
|
||||||
if tabContainer.GetTabCount() > 0 { // Draw the tab container only if a tab is open
|
if tabContainer.GetTabCount() > 0 { // Draw the tab container only if a tab is open
|
||||||
tabContainer.Draw(s)
|
tabContainer.Draw(screen)
|
||||||
}
|
}
|
||||||
menuBar.Draw(s) // Always draw the menu bar
|
menuBar.Draw(screen) // Always draw the menu bar
|
||||||
|
|
||||||
if dialog != nil {
|
if dialog != nil {
|
||||||
// Update fileSelector dialog pos and size
|
// Update fileSelector dialog pos and size
|
||||||
@ -326,11 +364,11 @@ func main() {
|
|||||||
dialog.SetSize(diagMinX, diagMinY)
|
dialog.SetSize(diagMinX, diagMinY)
|
||||||
dialog.SetPos(sizex/2-diagMinX/2, sizey/2-diagMinY/2) // Center
|
dialog.SetPos(sizex/2-diagMinX/2, sizey/2-diagMinY/2) // Center
|
||||||
|
|
||||||
dialog.Draw(s)
|
dialog.Draw(screen)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw statusbar
|
// Draw statusbar
|
||||||
ui.DrawRect(s, 0, sizey-1, sizex, 1, ' ', theme["StatusBar"])
|
ui.DrawRect(screen, 0, sizey-1, sizex, 1, ' ', theme["StatusBar"])
|
||||||
if tabContainer.GetTabCount() > 0 {
|
if tabContainer.GetTabCount() > 0 {
|
||||||
focusedTab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
focusedTab := tabContainer.GetTab(tabContainer.GetSelectedTabIdx())
|
||||||
te := focusedTab.Child.(*ui.TextEdit)
|
te := focusedTab.Child.(*ui.TextEdit)
|
||||||
@ -352,19 +390,19 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
str := fmt.Sprintf(" Filetype: %s %d, %d %s %s", "None", line+1, col+1, delim, tabs)
|
str := fmt.Sprintf(" Filetype: %s %d, %d %s %s", "None", line+1, col+1, delim, tabs)
|
||||||
ui.DrawStr(s, 0, sizey-1, str, theme["StatusBar"])
|
ui.DrawStr(screen, 0, sizey-1, str, theme["StatusBar"])
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Show()
|
screen.Show()
|
||||||
|
|
||||||
switch ev := s.PollEvent().(type) {
|
switch ev := screen.PollEvent().(type) {
|
||||||
case *tcell.EventResize:
|
case *tcell.EventResize:
|
||||||
sizex, sizey = s.Size()
|
sizex, sizey = screen.Size()
|
||||||
|
|
||||||
menuBar.SetSize(sizex, 1)
|
menuBar.SetSize(sizex, 1)
|
||||||
tabContainer.SetSize(sizex, sizey-2)
|
tabContainer.SetSize(sizex, sizey-2)
|
||||||
|
|
||||||
s.Sync() // Redraw everything
|
screen.Sync() // Redraw everything
|
||||||
case *tcell.EventKey:
|
case *tcell.EventKey:
|
||||||
// On Escape, we change focus between editor and the MenuBar.
|
// On Escape, we change focus between editor and the MenuBar.
|
||||||
if dialog == nil {
|
if dialog == nil {
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
//
|
//
|
||||||
// Many components implement their own `New...()` function. In those constructor
|
// Many components implement their own `New...()` function. In those constructor
|
||||||
// functions, it is good practice for that component to set its size to be its
|
// functions, it is good practice for that component to set its size to be its
|
||||||
// minimum size. TODO: implement that behavior
|
// minimum size.
|
||||||
type Component interface {
|
type Component interface {
|
||||||
// A component knows its position and size, which is used to draw itself in
|
// A component knows its position and size, which is used to draw itself in
|
||||||
// its bounding rectangle.
|
// its bounding rectangle.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user