mirror of
https://github.com/VladimirMarkelov/clui.git
synced 2025-04-26 13:49:01 +08:00
add a way to hide a window instead of destroying it
This commit is contained in:
parent
b1dea556bb
commit
dbc2b92312
16
changelog
16
changelog
@ -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
|
||||
|
56
composer.go
56
composer.go
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
|
47
window.go
47
window.go
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user