add a way to hide a window instead of destroying it

This commit is contained in:
Vladimir Markelov 2017-07-04 18:04:58 -07:00
parent b1dea556bb
commit dbc2b92312
5 changed files with 96 additions and 32 deletions

View File

@ -1,4 +1,18 @@
2017-06-30 - Version 0.6.0
2017-07-04 - Version 0.6.1
[*] Fix selection Window with mouse: clicking non-active Window makes the
Window active (unless the top Window is modal one)
[*] TableView does not fire OnSelectionChange event if a user clicked outside
the table. Before the fix a callback got selected index greater than
the total number of rows and might crash a callback
[+] Add a new feature to Windows: to keep all changes the Windows can be
hidden instead of destroying when a user clicks window close button. It
can be done with overriding OnClose and returning 'true' if Windows must
be kept. To remove the Window from screen use SetVisible(false)
[*] Window OnClose callback event now must return boolean. See change above
[*] Fix typo: TableView did not send TableDelete event if the selected Row
was Row number 1
2017-06-30 - Version 0.6.0
[+] Added new control TextReader - a virtual text view control with
built-in support of some hots keys to list the text
[+] Added a new global event to close active view

View File

@ -65,7 +65,10 @@ func RefreshScreen() {
term.Clear(ColorWhite, ColorBlack)
for _, wnd := range comp.windows {
wnd.Draw()
v := comp.topWindow().(*Window)
if v.Visible() {
wnd.Draw()
}
}
term.Flush()
@ -144,18 +147,36 @@ func (c *Composer) moveActiveWindowToBottom() bool {
return false
}
anyVisible := false
for _, w := range c.windows {
v := w.(*Window)
if v.Visible() {
anyVisible = true
break
}
}
if !anyVisible {
return false
}
event := Event{Type: EventActivate, X: 0} // send deactivated
c.sendEventToActiveWindow(event)
last := c.topWindow()
for {
last := c.topWindow()
for i := len(c.windows) - 1; i > 0; i-- {
c.windows[i] = c.windows[i-1]
}
c.windows[0] = last
for i := len(c.windows) - 1; i > 0; i-- {
c.windows[i] = c.windows[i-1]
}
v := c.topWindow().(*Window)
if v.Visible() {
if !c.activateWindow(c.topWindow()) {
return false
}
c.windows[0] = last
if !c.activateWindow(c.topWindow()) {
return false
break
}
}
event = Event{Type: EventActivate, X: 1} // send 'activated'
@ -246,13 +267,14 @@ func (c *Composer) closeTopWindow() {
if len(c.windows) > 1 {
view := c.topWindow()
event := Event{Type: EventClose, X: 1}
c.sendEventToActiveWindow(event)
c.DestroyWindow(view)
activate := c.topWindow()
c.activateWindow(activate)
event = Event{Type: EventActivate, X: 1} // send 'activated'
c.sendEventToActiveWindow(event)
if c.sendEventToActiveWindow(event) {
c.DestroyWindow(view)
activate := c.topWindow()
c.activateWindow(activate)
event = Event{Type: EventActivate, X: 1} // send 'activated'
c.sendEventToActiveWindow(event)
}
RefreshScreen()
} else {
@ -451,9 +473,9 @@ func (c *Composer) processMouse(ev Event) {
return
}
} else if !c.topWindow().Modal() {
c.activateWindow(view)
return
}
c.activateWindow(view)
return
}
if ev.Key == term.MouseLeft {
c.lastX = ev.X

View File

@ -111,7 +111,7 @@ func CreateConfirmationDialog(title, question string, buttons []string, defaultB
CreateFrame(frm1, 1, 1, BorderNone, 1)
dlg.view.OnClose(func(ev Event) {
dlg.view.OnClose(func(ev Event) bool {
if dlg.result == DialogAlive {
dlg.result = DialogClosed
if ev.X != 1 {
@ -121,6 +121,7 @@ func CreateConfirmationDialog(title, question string, buttons []string, defaultB
go dlg.onClose()
}
}
return true
})
return dlg
@ -220,7 +221,7 @@ func CreateSelectDialog(title string, items []string, selectedItem int, typ Sele
ActivateControl(dlg.view, btn2)
CreateFrame(frm1, 1, 1, BorderNone, 1)
dlg.view.OnClose(func(ev Event) {
dlg.view.OnClose(func(ev Event) bool {
if dlg.result == DialogAlive {
dlg.result = DialogClosed
if ev.X != 1 {
@ -230,6 +231,8 @@ func CreateSelectDialog(title string, items []string, selectedItem int, typ Sele
go dlg.onClose()
}
}
return true
})
return dlg

View File

@ -793,7 +793,7 @@ func (l *TableView) ProcessEvent(event Event) bool {
go l.onAction(ev)
}
case term.KeyDelete:
if l.selectedRow != 1 && l.onAction != nil {
if l.selectedRow != -1 && l.onAction != nil {
ev := TableEvent{Action: TableActionDelete, Col: l.selectedCol, Row: l.selectedRow}
go l.onAction(ev)
}

View File

@ -16,9 +16,10 @@ type Window struct {
origHeight int
origX int
origY int
hidden bool
onClose func(Event)
onKeyDown func(Event) bool
onClose func(Event) bool
onKeyDown func(Event) bool
}
func CreateWindow(x, y, w, h int, title string) *Window {
@ -211,8 +212,11 @@ func (c *Window) ProcessEvent(ev Event) bool {
c.PlaceChildren()
case EventClose:
if c.onClose != nil {
c.onClose(ev)
if !c.onClose(ev) {
return false
}
}
return true
case EventKey:
if ev.Key == term.KeyTab {
aC := ActiveControl(c)
@ -229,13 +233,13 @@ func (c *Window) ProcessEvent(ev Event) bool {
}
return true
} else {
if SendEventToChild(c, ev) {
return true
}
if c.onKeyDown != nil {
return c.onKeyDown(ev)
}
return false
if SendEventToChild(c, ev) {
return true
}
if c.onKeyDown != nil {
return c.onKeyDown(ev)
}
return false
}
default:
if ev.Type == EventMouse && ev.Key == term.MouseLeft {
@ -247,7 +251,7 @@ func (c *Window) ProcessEvent(ev Event) bool {
return false
}
func (w *Window) OnClose(fn func(Event)) {
func (w *Window) OnClose(fn func(Event) bool) {
w.onClose = fn
}
@ -282,3 +286,24 @@ func (w *Window) SetMaximized(maximize bool) {
func (w *Window) Maximized() bool {
return w.maximized
}
// Visible returns if the window must be drawn on the screen
func (w *Window) Visible() bool {
return !w.hidden
}
// SetVisible allows to temporarily remove the window from screen
// and show it later without reconstruction
func (w *Window) SetVisible(visible bool) {
if w.hidden == visible {
w.hidden = !visible
if w.hidden {
w.SetModal(false)
if composer().topWindow() == w {
composer().moveActiveWindowToBottom()
}
} else {
composer().activateWindow(w)
}
}
}