forked from tslocum/cview
10 changed files with 446 additions and 382 deletions
@ -1,380 +1,60 @@
@@ -1,380 +1,60 @@
|
||||
package cview |
||||
|
||||
import ( |
||||
"sync" |
||||
type page = panel |
||||
|
||||
"github.com/gdamore/tcell/v2" |
||||
) |
||||
|
||||
// page represents one page of a Pages object.
|
||||
type page struct { |
||||
Name string // The page's name.
|
||||
Item Primitive // The page's primitive.
|
||||
Resize bool // Whether or not to resize the page when it is drawn.
|
||||
Visible bool // Whether or not this page is visible.
|
||||
} |
||||
|
||||
// Pages is a container for other primitives often used as the application's
|
||||
// root primitive. It allows to easily switch the visibility of the contained
|
||||
// primitives.
|
||||
// Pages is a wrapper around Panels. It is provided for backwards compatibility.
|
||||
// Application developers should use Panels instead.
|
||||
type Pages struct { |
||||
*Box |
||||
|
||||
// The contained pages. (Visible) pages are drawn from back to front.
|
||||
pages []*page |
||||
|
||||
// We keep a reference to the function which allows us to set the focus to
|
||||
// a newly visible page.
|
||||
setFocus func(p Primitive) |
||||
|
||||
// An optional handler which is called whenever the visibility or the order of
|
||||
// pages changes.
|
||||
changed func() |
||||
|
||||
sync.RWMutex |
||||
*Panels |
||||
} |
||||
|
||||
// NewPages returns a new Pages object.
|
||||
// NewPages returns a new Panels object.
|
||||
func NewPages() *Pages { |
||||
p := &Pages{ |
||||
Box: NewBox(), |
||||
} |
||||
p.focus = p |
||||
return p |
||||
} |
||||
|
||||
// SetChangedFunc sets a handler which is called whenever the visibility or the
|
||||
// order of any visible pages changes. This can be used to redraw the pages.
|
||||
func (p *Pages) SetChangedFunc(handler func()) { |
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
p.changed = handler |
||||
return &Pages{NewPanels()} |
||||
} |
||||
|
||||
// GetPageCount returns the number of pages currently stored in this object.
|
||||
// GetPageCount returns the number of panels currently stored in this object.
|
||||
func (p *Pages) GetPageCount() int { |
||||
p.RLock() |
||||
defer p.RUnlock() |
||||
|
||||
return len(p.pages) |
||||
return p.GetPanelCount() |
||||
} |
||||
|
||||
// AddPage adds a new page with the given name and primitive. If there was
|
||||
// previously a page with the same name, it is overwritten. Leaving the name
|
||||
// empty may cause conflicts in other functions so always specify a non-empty
|
||||
// name.
|
||||
//
|
||||
// Visible pages will be drawn in the order they were added (unless that order
|
||||
// was changed in one of the other functions). If "resize" is set to true, the
|
||||
// primitive will be set to the size available to the Pages primitive whenever
|
||||
// the pages are drawn.
|
||||
// AddPage adds a new panel with the given name and primitive.
|
||||
func (p *Pages) AddPage(name string, item Primitive, resize, visible bool) { |
||||
hasFocus := p.HasFocus() |
||||
|
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
for index, pg := range p.pages { |
||||
if pg.Name == name { |
||||
p.pages = append(p.pages[:index], p.pages[index+1:]...) |
||||
break |
||||
} |
||||
} |
||||
p.pages = append(p.pages, &page{Item: item, Name: name, Resize: resize, Visible: visible}) |
||||
if p.changed != nil { |
||||
p.Unlock() |
||||
p.changed() |
||||
p.Lock() |
||||
} |
||||
if hasFocus { |
||||
p.Unlock() |
||||
p.Focus(p.setFocus) |
||||
p.Lock() |
||||
} |
||||
p.Add(name, item, resize, visible) |
||||
} |
||||
|
||||
// AddAndSwitchToPage calls AddPage(), then SwitchToPage() on that newly added
|
||||
// page.
|
||||
// AddAndSwitchToPage calls Add(), then SwitchTo() on that newly added panel.
|
||||
func (p *Pages) AddAndSwitchToPage(name string, item Primitive, resize bool) { |
||||
p.AddPage(name, item, resize, true) |
||||
p.SwitchToPage(name) |
||||
p.AddAndSwitchTo(name, item, resize) |
||||
} |
||||
|
||||
// RemovePage removes the page with the given name. If that page was the only
|
||||
// visible page, visibility is assigned to the last page.
|
||||
// RemovePage removes the panel with the given name.
|
||||
func (p *Pages) RemovePage(name string) { |
||||
hasFocus := p.HasFocus() |
||||
|
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
var isVisible bool |
||||
for index, page := range p.pages { |
||||
if page.Name == name { |
||||
isVisible = page.Visible |
||||
p.pages = append(p.pages[:index], p.pages[index+1:]...) |
||||
if page.Visible && p.changed != nil { |
||||
p.Unlock() |
||||
p.changed() |
||||
p.Lock() |
||||
} |
||||
break |
||||
} |
||||
} |
||||
if isVisible { |
||||
for index, page := range p.pages { |
||||
if index < len(p.pages)-1 { |
||||
if page.Visible { |
||||
break // There is a remaining visible page.
|
||||
} |
||||
} else { |
||||
page.Visible = true // We need at least one visible page.
|
||||
} |
||||
} |
||||
} |
||||
if hasFocus { |
||||
p.Unlock() |
||||
p.Focus(p.setFocus) |
||||
p.Lock() |
||||
} |
||||
p.Remove(name) |
||||
} |
||||
|
||||
// HasPage returns true if a page with the given name exists in this object.
|
||||
// HasPage returns true if a panel with the given name exists in this object.
|
||||
func (p *Pages) HasPage(name string) bool { |
||||
p.RLock() |
||||
defer p.RUnlock() |
||||
|
||||
for _, page := range p.pages { |
||||
if page.Name == name { |
||||
return true |
||||
} |
||||
} |
||||
return false |
||||
return p.Has(name) |
||||
} |
||||
|
||||
// ShowPage sets a page's visibility to "true" (in addition to any other pages
|
||||
// which are already visible).
|
||||
// ShowPage sets a panel's visibility to "true".
|
||||
func (p *Pages) ShowPage(name string) { |
||||
hasFocus := p.HasFocus() |
||||
|
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
for _, page := range p.pages { |
||||
if page.Name == name { |
||||
page.Visible = true |
||||
if p.changed != nil { |
||||
p.Unlock() |
||||
p.changed() |
||||
p.Lock() |
||||
} |
||||
break |
||||
} |
||||
} |
||||
if hasFocus { |
||||
p.Unlock() |
||||
p.Focus(p.setFocus) |
||||
p.Lock() |
||||
} |
||||
p.Show(name) |
||||
} |
||||
|
||||
// HidePage sets a page's visibility to "false".
|
||||
// HidePage sets a panel's visibility to "false".
|
||||
func (p *Pages) HidePage(name string) { |
||||
hasFocus := p.HasFocus() |
||||
|
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
for _, page := range p.pages { |
||||
if page.Name == name { |
||||
page.Visible = false |
||||
if p.changed != nil { |
||||
p.Unlock() |
||||
p.changed() |
||||
p.Lock() |
||||
} |
||||
break |
||||
} |
||||
} |
||||
if hasFocus { |
||||
p.Unlock() |
||||
p.Focus(p.setFocus) |
||||
p.Lock() |
||||
} |
||||
p.Hide(name) |
||||
} |
||||
|
||||
// SwitchToPage sets a page's visibility to "true" and all other pages'
|
||||
// SwitchToPage sets a panel's visibility to "true" and all other panels'
|
||||
// visibility to "false".
|
||||
func (p *Pages) SwitchToPage(name string) { |
||||
hasFocus := p.HasFocus() |
||||
|
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
for _, page := range p.pages { |
||||
if page.Name == name { |
||||
page.Visible = true |
||||
} else { |
||||
page.Visible = false |
||||
} |
||||
} |
||||
if p.changed != nil { |
||||
p.Unlock() |
||||
p.changed() |
||||
p.Lock() |
||||
} |
||||
if hasFocus { |
||||
p.Unlock() |
||||
p.Focus(p.setFocus) |
||||
p.Lock() |
||||
} |
||||
p.SwitchTo(name) |
||||
} |
||||
|
||||
// SendToFront changes the order of the pages such that the page with the given
|
||||
// name comes last, causing it to be drawn last with the next update (if
|
||||
// visible).
|
||||
func (p *Pages) SendToFront(name string) { |
||||
hasFocus := p.HasFocus() |
||||
|
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
for index, page := range p.pages { |
||||
if page.Name == name { |
||||
if index < len(p.pages)-1 { |
||||
p.pages = append(append(p.pages[:index], p.pages[index+1:]...), page) |
||||
} |
||||
if page.Visible && p.changed != nil { |
||||
p.Unlock() |
||||
p.changed() |
||||
p.Lock() |
||||
} |
||||
break |
||||
} |
||||
} |
||||
if hasFocus { |
||||
p.Unlock() |
||||
p.Focus(p.setFocus) |
||||
p.Lock() |
||||
} |
||||
} |
||||
|
||||
// SendToBack changes the order of the pages such that the page with the given
|
||||
// name comes first, causing it to be drawn first with the next update (if
|
||||
// visible).
|
||||
func (p *Pages) SendToBack(name string) { |
||||
hasFocus := p.HasFocus() |
||||
|
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
for index, pg := range p.pages { |
||||
if pg.Name == name { |
||||
if index > 0 { |
||||
p.pages = append(append([]*page{pg}, p.pages[:index]...), p.pages[index+1:]...) |
||||
} |
||||
if pg.Visible && p.changed != nil { |
||||
p.Unlock() |
||||
p.changed() |
||||
p.Lock() |
||||
} |
||||
break |
||||
} |
||||
} |
||||
if hasFocus { |
||||
p.Unlock() |
||||
p.Focus(p.setFocus) |
||||
p.Lock() |
||||
} |
||||
} |
||||
|
||||
// GetFrontPage returns the front-most visible page. If there are no visible
|
||||
// pages, ("", nil) is returned.
|
||||
// GetFrontPage returns the front-most visible panel.
|
||||
func (p *Pages) GetFrontPage() (name string, item Primitive) { |
||||
p.RLock() |
||||
defer p.RUnlock() |
||||
|
||||
for index := len(p.pages) - 1; index >= 0; index-- { |
||||
if p.pages[index].Visible { |
||||
return p.pages[index].Name, p.pages[index].Item |
||||
} |
||||
} |
||||
return |
||||
} |
||||
|
||||
// HasFocus returns whether or not this primitive has focus.
|
||||
func (p *Pages) HasFocus() bool { |
||||
p.RLock() |
||||
defer p.RUnlock() |
||||
|
||||
for _, page := range p.pages { |
||||
if page.Item.GetFocusable().HasFocus() { |
||||
return true |
||||
} |
||||
} |
||||
return false |
||||
} |
||||
|
||||
// Focus is called by the application when the primitive receives focus.
|
||||
func (p *Pages) Focus(delegate func(p Primitive)) { |
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
if delegate == nil { |
||||
return // We cannot delegate so we cannot focus.
|
||||
} |
||||
p.setFocus = delegate |
||||
var topItem Primitive |
||||
for _, page := range p.pages { |
||||
if page.Visible { |
||||
topItem = page.Item |
||||
} |
||||
} |
||||
if topItem != nil { |
||||
p.Unlock() |
||||
delegate(topItem) |
||||
p.Lock() |
||||
} |
||||
} |
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (p *Pages) Draw(screen tcell.Screen) { |
||||
p.Box.Draw(screen) |
||||
|
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
for _, page := range p.pages { |
||||
if !page.Visible { |
||||
continue |
||||
} |
||||
if page.Resize { |
||||
x, y, width, height := p.GetInnerRect() |
||||
page.Item.SetRect(x, y, width, height) |
||||
} |
||||
page.Item.Draw(screen) |
||||
} |
||||
} |
||||
|
||||
// MouseHandler returns the mouse handler for this primitive.
|
||||
func (p *Pages) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) { |
||||
return p.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) { |
||||
if !p.InRect(event.Position()) { |
||||
return false, nil |
||||
} |
||||
|
||||
// Pass mouse events along to the last visible page item that takes it.
|
||||
for index := len(p.pages) - 1; index >= 0; index-- { |
||||
page := p.pages[index] |
||||
if page.Visible { |
||||
consumed, capture = page.Item.MouseHandler()(action, event, setFocus) |
||||
if consumed { |
||||
return |
||||
} |
||||
} |
||||
} |
||||
|
||||
return |
||||
}) |
||||
return p.GetFrontPanel() |
||||
} |
||||
|
@ -0,0 +1,383 @@
@@ -0,0 +1,383 @@
|
||||
package cview |
||||
|
||||
import ( |
||||
"sync" |
||||
|
||||
"github.com/gdamore/tcell/v2" |
||||
) |
||||
|
||||
// panel represents a single panel of a Panels object.
|
||||
type panel struct { |
||||
Name string // The panel's name.
|
||||
Item Primitive // The panel's primitive.
|
||||
Resize bool // Whether or not to resize the panel when it is drawn.
|
||||
Visible bool // Whether or not this panel is visible.
|
||||
} |
||||
|
||||
// Panels is a container for other primitives often used as the application's
|
||||
// root primitive. It allows to easily switch the visibility of the contained
|
||||
// primitives.
|
||||
type Panels struct { |
||||
*Box |
||||
|
||||
// The contained panels. (Visible) panels are drawn from back to front.
|
||||
panels []*panel |
||||
|
||||
// We keep a reference to the function which allows us to set the focus to
|
||||
// a newly visible panel.
|
||||
setFocus func(p Primitive) |
||||
|
||||
// An optional handler which is called whenever the visibility or the order of
|
||||
// panels changes.
|
||||
changed func() |
||||
|
||||
// TODO enable tabs
|
||||
tabs *TextView |
||||
|
||||
sync.RWMutex |
||||
} |
||||
|
||||
// NewPanels returns a new Panels object.
|
||||
func NewPanels() *Panels { |
||||
p := &Panels{ |
||||
Box: NewBox(), |
||||
} |
||||
p.focus = p |
||||
return p |
||||
} |
||||
|
||||
// SetChangedFunc sets a handler which is called whenever the visibility or the
|
||||
// order of any visible panels changes. This can be used to redraw the panels.
|
||||
func (p *Panels) SetChangedFunc(handler func()) { |
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
p.changed = handler |
||||
} |
||||
|
||||
// GetPanelCount returns the number of panels currently stored in this object.
|
||||
func (p *Panels) GetPanelCount() int { |
||||
p.RLock() |
||||
defer p.RUnlock() |
||||
|
||||
return len(p.panels) |
||||
} |
||||
|
||||
// Add adds a new panel with the given name and primitive. If there was
|
||||
// previously a panel with the same name, it is overwritten. Leaving the name
|
||||
// empty may cause conflicts in other functions so always specify a non-empty
|
||||
// name.
|
||||
//
|
||||
// Visible panels will be drawn in the order they were added (unless that order
|
||||
// was changed in one of the other functions). If "resize" is set to true, the
|
||||
// primitive will be set to the size available to the Panels primitive whenever
|
||||
// the panels are drawn.
|
||||
func (p *Panels) Add(name string, item Primitive, resize, visible bool) { |
||||
hasFocus := p.HasFocus() |
||||
|
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
for index, pg := range p.panels { |
||||
if pg.Name == name { |
||||
p.panels = append(p.panels[:index], p.panels[index+1:]...) |
||||
break |
||||
} |
||||
} |
||||
p.panels = append(p.panels, &panel{Item: item, Name: name, Resize: resize, Visible: visible}) |
||||
if p.changed != nil { |
||||
p.Unlock() |
||||
p.changed() |
||||
p.Lock() |
||||
} |
||||
if hasFocus { |
||||
p.Unlock() |
||||
p.Focus(p.setFocus) |
||||
p.Lock() |
||||
} |
||||
} |
||||
|
||||
// AddAndSwitchTo calls Add(), then SwitchTo() on the newly added panel.
|
||||
func (p *Panels) AddAndSwitchTo(name string, item Primitive, resize bool) { |
||||
p.Add(name, item, resize, true) |
||||
p.SwitchTo(name) |
||||
} |
||||
|
||||
// Remove removes the panel with the given name. If that panel was the only
|
||||
// visible panel, visibility is assigned to the last panel.
|
||||
func (p *Panels) Remove(name string) { |
||||
hasFocus := p.HasFocus() |
||||
|
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
var isVisible bool |
||||
for index, panel := range p.panels { |
||||
if panel.Name == name { |
||||
isVisible = panel.Visible |
||||
p.panels = append(p.panels[:index], p.panels[index+1:]...) |
||||
if panel.Visible && p.changed != nil { |
||||
p.Unlock() |
||||
p.changed() |
||||
p.Lock() |
||||
} |
||||
break |
||||
} |
||||
} |
||||
if isVisible { |
||||
for index, panel := range p.panels { |
||||
if index < len(p.panels)-1 { |
||||
if panel.Visible { |
||||
break // There is a remaining visible panel.
|
||||
} |
||||
} else { |
||||
panel.Visible = true // We need at least one visible panel.
|
||||
} |
||||
} |
||||
} |
||||
if hasFocus { |
||||
p.Unlock() |
||||
p.Focus(p.setFocus) |
||||
p.Lock() |
||||
} |
||||
} |
||||
|
||||
// Has returns true if a panel with the given name exists in this object.
|
||||
func (p *Panels) Has(name string) bool { |
||||
p.RLock() |
||||
defer p.RUnlock() |
||||
|
||||
for _, panel := range p.panels { |
||||
if panel.Name == name { |
||||
return true |
||||
} |
||||
} |
||||
return false |
||||
} |
||||
|
||||
// Show sets a panel's visibility to "true" (in addition to any other panels
|
||||
// which are already visible).
|
||||
func (p *Panels) Show(name string) { |
||||
hasFocus := p.HasFocus() |
||||
|
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
for _, panel := range p.panels { |
||||
if panel.Name == name { |
||||
panel.Visible = true |
||||
if p.changed != nil { |
||||
p.Unlock() |
||||
p.changed() |
||||
p.Lock() |
||||
} |
||||
break |
||||
} |
||||
} |
||||
if hasFocus { |
||||
p.Unlock() |
||||
p.Focus(p.setFocus) |
||||
p.Lock() |
||||
} |
||||
} |
||||
|
||||
// Hide sets a panel's visibility to "false".
|
||||
func (p *Panels) Hide(name string) { |
||||
hasFocus := p.HasFocus() |
||||
|
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
for _, panel := range p.panels { |
||||
if panel.Name == name { |
||||
panel.Visible = false |
||||
if p.changed != nil { |
||||
p.Unlock() |
||||
p.changed() |
||||
p.Lock() |
||||
} |
||||
break |
||||
} |
||||
} |
||||
if hasFocus { |
||||
p.Unlock() |
||||
p.Focus(p.setFocus) |
||||
p.Lock() |
||||
} |
||||
} |
||||
|
||||
// SwitchTo sets a panel's visibility to "true" and all other panels'
|
||||
// visibility to "false".
|
||||
func (p *Panels) SwitchTo(name string) { |
||||
hasFocus := p.HasFocus() |
||||
|
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
for _, panel := range p.panels { |
||||
if panel.Name == name { |
||||
panel.Visible = true |
||||
} else { |
||||
panel.Visible = false |
||||
} |
||||
} |
||||
if p.changed != nil { |
||||
p.Unlock() |
||||
p.changed() |
||||
p.Lock() |
||||
} |
||||
if hasFocus { |
||||
p.Unlock() |
||||
p.Focus(p.setFocus) |
||||
p.Lock() |
||||
} |
||||
} |
||||
|
||||
// SendToFront changes the order of the panels such that the panel with the given
|
||||
// name comes last, causing it to be drawn last with the next update (if
|
||||
// visible).
|
||||
func (p *Panels) SendToFront(name string) { |
||||
hasFocus := p.HasFocus() |
||||
|
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
for index, panel := range p.panels { |
||||
if panel.Name == name { |
||||
if index < len(p.panels)-1 { |
||||
p.panels = append(append(p.panels[:index], p.panels[index+1:]...), panel) |
||||
} |
||||
if panel.Visible && p.changed != nil { |
||||
p.Unlock() |
||||
p.changed() |
||||
p.Lock() |
||||
} |
||||
break |
||||
} |
||||
} |
||||
if hasFocus { |
||||
p.Unlock() |
||||
p.Focus(p.setFocus) |
||||
p.Lock() |
||||
} |
||||
} |
||||
|
||||
// SendToBack changes the order of the panels such that the panel with the given
|
||||
// name comes first, causing it to be drawn first with the next update (if
|
||||
// visible).
|
||||
func (p *Panels) SendToBack(name string) { |
||||
hasFocus := p.HasFocus() |
||||
|
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
for index, pg := range p.panels { |
||||
if pg.Name == name { |
||||
if index > 0 { |
||||
p.panels = append(append([]*panel{pg}, p.panels[:index]...), p.panels[index+1:]...) |
||||
} |
||||
if pg.Visible && p.changed != nil { |
||||
p.Unlock() |
||||
p.changed() |
||||
p.Lock() |
||||
} |
||||
break |
||||
} |
||||
} |
||||
if hasFocus { |
||||
p.Unlock() |
||||
p.Focus(p.setFocus) |
||||
p.Lock() |
||||
} |
||||
} |
||||
|
||||
// GetFrontPanel returns the front-most visible panel. If there are no visible
|
||||
// panels, ("", nil) is returned.
|
||||
func (p *Panels) GetFrontPanel() (name string, item Primitive) { |
||||
p.RLock() |
||||
defer p.RUnlock() |
||||
|
||||
for index := len(p.panels) - 1; index >= 0; index-- { |
||||
if p.panels[index].Visible { |
||||
return p.panels[index].Name, p.panels[index].Item |
||||
} |
||||
} |
||||
return |
||||
} |
||||
|
||||
// HasFocus returns whether or not this primitive has focus.
|
||||
func (p *Panels) HasFocus() bool { |
||||
p.RLock() |
||||
defer p.RUnlock() |
||||
|
||||
for _, panel := range p.panels { |
||||
if panel.Item.GetFocusable().HasFocus() { |
||||
return true |
||||
} |
||||
} |
||||
return false |
||||
} |
||||
|
||||
// Focus is called by the application when the primitive receives focus.
|
||||
func (p *Panels) Focus(delegate func(p Primitive)) { |
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
if delegate == nil { |
||||
return // We cannot delegate so we cannot focus.
|
||||
} |
||||
p.setFocus = delegate |
||||
var topItem Primitive |
||||
for _, panel := range p.panels { |
||||
if panel.Visible { |
||||
topItem = panel.Item |
||||
} |
||||
} |
||||
if topItem != nil { |
||||
p.Unlock() |
||||
delegate(topItem) |
||||
p.Lock() |
||||
} |
||||
} |
||||
|
||||
// Draw draws this primitive onto the screen.
|
||||
func (p *Panels) Draw(screen tcell.Screen) { |
||||
p.Box.Draw(screen) |
||||
|
||||
p.Lock() |
||||
defer p.Unlock() |
||||
|
||||
x, y, width, height := p.GetInnerRect() |
||||
|
||||
for _, panel := range p.panels { |
||||
if !panel.Visible { |
||||
continue |
||||
} |
||||
if panel.Resize { |
||||
panel.Item.SetRect(x, y, width, height) |
||||
} |
||||
panel.Item.Draw(screen) |
||||
} |
||||
} |
||||
|
||||
// MouseHandler returns the mouse handler for this primitive.
|
||||
func (p *Panels) MouseHandler() func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) { |
||||
return p.WrapMouseHandler(func(action MouseAction, event *tcell.EventMouse, setFocus func(p Primitive)) (consumed bool, capture Primitive) { |
||||
if !p.InRect(event.Position()) { |
||||
return false, nil |
||||
} |
||||
|
||||
// Pass mouse events along to the last visible panel item that takes it.
|
||||
for index := len(p.panels) - 1; index >= 0; index-- { |
||||
panel := p.panels[index] |
||||
if panel.Visible { |
||||
consumed, capture = panel.Item.MouseHandler()(action, event, setFocus) |
||||
if consumed { |
||||
return |
||||
} |
||||
} |
||||
} |
||||
|
||||
return |
||||
}) |
||||
} |
Loading…
Reference in new issue