package cviewimport ()// 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.typePanelsstruct { *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()sync.RWMutex}// NewPanels returns a new Panels object.func () *Panels { := &Panels{Box: NewBox(), } .focus = return}// 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 ( *Panels) ( func()) { .Lock()defer .Unlock() .changed = }// GetPanelCount returns the number of panels currently stored in this object.func ( *Panels) () int { .RLock()defer .RUnlock()returnlen(.panels)}// AddPanel 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 ( *Panels) ( string, Primitive, , bool) { := .HasFocus() .Lock()defer .Unlock()varboolfor , := range .panels {if .Name == { .panels[] = &panel{Item: , Name: , Resize: , Visible: } = truebreak } }if ! { .panels = append(.panels, &panel{Item: , Name: , Resize: , Visible: }) }if .changed != nil { .Unlock() .changed() .Lock() }if { .Unlock() .Focus(.setFocus) .Lock() }}// RemovePanel removes the panel with the given name. If that panel was the only// visible panel, visibility is assigned to the last panel.func ( *Panels) ( string) { := .HasFocus() .Lock()defer .Unlock()varboolfor , := range .panels {if .Name == { = .Visible .panels = append(.panels[:], .panels[+1:]...)if .Visible && .changed != nil { .Unlock() .changed() .Lock() }break } }if {for , := range .panels {if < len(.panels)-1 {if .Visible {break// There is a remaining visible panel. } } else { .Visible = true// We need at least one visible panel. } } }if { .Unlock() .Focus(.setFocus) .Lock() }}// HasPanel returns true if a panel with the given name exists in this object.func ( *Panels) ( string) bool { .RLock()defer .RUnlock()for , := range .panels {if .Name == {returntrue } }returnfalse}// ShowPanel sets a panel's visibility to "true" (in addition to any other panels// which are already visible).func ( *Panels) ( string) { := .HasFocus() .Lock()defer .Unlock()for , := range .panels {if .Name == { .Visible = trueif .changed != nil { .Unlock() .changed() .Lock() }break } }if { .Unlock() .Focus(.setFocus) .Lock() }}// HidePanel sets a panel's visibility to "false".func ( *Panels) ( string) { := .HasFocus() .Lock()defer .Unlock()for , := range .panels {if .Name == { .Visible = falseif .changed != nil { .Unlock() .changed() .Lock() }break } }if { .Unlock() .Focus(.setFocus) .Lock() }}// SetCurrentPanel sets a panel's visibility to "true" and all other panels'// visibility to "false".func ( *Panels) ( string) { := .HasFocus() .Lock()defer .Unlock()for , := range .panels {if .Name == { .Visible = true } else { .Visible = false } }if .changed != nil { .Unlock() .changed() .Lock() }if { .Unlock() .Focus(.setFocus) .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 ( *Panels) ( string) { := .HasFocus() .Lock()defer .Unlock()for , := range .panels {if .Name == {if < len(.panels)-1 { .panels = append(append(.panels[:], .panels[+1:]...), ) }if .Visible && .changed != nil { .Unlock() .changed() .Lock() }break } }if { .Unlock() .Focus(.setFocus) .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 ( *Panels) ( string) { := .HasFocus() .Lock()defer .Unlock()for , := range .panels {if .Name == {if > 0 { .panels = append(append([]*panel{}, .panels[:]...), .panels[+1:]...) }if .Visible && .changed != nil { .Unlock() .changed() .Lock() }break } }if { .Unlock() .Focus(.setFocus) .Lock() }}// GetFrontPanel returns the front-most visible panel. If there are no visible// panels, ("", nil) is returned.func ( *Panels) () ( string, Primitive) { .RLock()defer .RUnlock()for := len(.panels) - 1; >= 0; -- {if .panels[].Visible {return .panels[].Name, .panels[].Item } }return}// HasFocus returns whether or not this primitive has focus.func ( *Panels) () bool { .RLock()defer .RUnlock()for , := range .panels {if .Item.GetFocusable().HasFocus() {returntrue } }returnfalse}// Focus is called by the application when the primitive receives focus.func ( *Panels) ( func( Primitive)) { .Lock()defer .Unlock()if == nil {return// We cannot delegate so we cannot focus. } .setFocus = varPrimitivefor , := range .panels {if .Visible { = .Item } }if != nil { .Unlock() () .Lock() }}// Draw draws this primitive onto the screen.func ( *Panels) ( tcell.Screen) {if !.GetVisible() {return } .Box.Draw() .Lock()defer .Unlock() , , , := .GetInnerRect()for , := range .panels {if !.Visible {continue }if .Resize { .Item.SetRect(, , , ) } .Item.Draw() }}// MouseHandler returns the mouse handler for this primitive.func ( *Panels) () func( MouseAction, *tcell.EventMouse, func( Primitive)) ( bool, Primitive) {return .WrapMouseHandler(func( MouseAction, *tcell.EventMouse, func( Primitive)) ( bool, Primitive) {if !.InRect(.Position()) {returnfalse, nil } := make([]*panel, 0, len(.panels))// Pass mouse events along to the last visible panel item that takes it. .RLock()for := len(.panels) - 1; >= 0; -- { := .panels[]if .Visible { = append(, ) } } .RUnlock()// iterate outside the lockfor , := range {// TODO panel lock , = .Item.MouseHandler()(, , )if {return } }return })}// Support backwards compatibility with Pages.type page = panel// Pages is a wrapper around Panels.//// Deprecated: This type is provided for backwards compatibility.// Developers should use Panels instead.typePagesstruct { *Panels}// NewPages returns a new Panels object.//// Deprecated: This function is provided for backwards compatibility.// Developers should use NewPanels instead.func () *Pages {return &Pages{NewPanels()}}// GetPageCount returns the number of panels currently stored in this object.func ( *Pages) () int {return .GetPanelCount()}// AddPage adds a new panel with the given name and primitive.func ( *Pages) ( string, Primitive, , bool) { .AddPanel(, , , )}// AddAndSwitchToPage calls Add(), then SwitchTo() on that newly added panel.func ( *Pages) ( string, Primitive, bool) { .AddPanel(, , , true) .SetCurrentPanel()}// RemovePage removes the panel with the given name.func ( *Pages) ( string) { .RemovePanel()}// HasPage returns true if a panel with the given name exists in this object.func ( *Pages) ( string) bool {return .HasPanel()}// ShowPage sets a panel's visibility to "true".func ( *Pages) ( string) { .ShowPanel()}// HidePage sets a panel's visibility to "false".func ( *Pages) ( string) { .HidePanel()}// SwitchToPage sets a panel's visibility to "true" and all other panels'// visibility to "false".func ( *Pages) ( string) { .SetCurrentPanel()}// GetFrontPage returns the front-most visible panel.func ( *Pages) () ( string, Primitive) {return .GetFrontPanel()}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.