2015-10-31 00:33:45 +08:00
|
|
|
// Copyright 2015 The Tcell Authors
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the license at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package views
|
|
|
|
|
|
|
|
import (
|
2015-11-05 03:22:38 +08:00
|
|
|
"sync"
|
|
|
|
|
2020-08-26 07:20:58 +08:00
|
|
|
"github.com/gdamore/tcell/v2"
|
2015-10-31 00:33:45 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
// TextBar is a Widget that provides a single line of text, but with
|
|
|
|
// distinct left, center, and right areas. Each of the areas can be styled
|
|
|
|
// differently, and they align to the left, center, and right respectively.
|
|
|
|
// This is basically a convenience type on top Text and BoxLayout.
|
|
|
|
type TextBar struct {
|
|
|
|
changed bool
|
|
|
|
style tcell.Style
|
|
|
|
left Text
|
|
|
|
right Text
|
|
|
|
center Text
|
|
|
|
view View
|
|
|
|
lview ViewPort
|
|
|
|
rview ViewPort
|
|
|
|
cview ViewPort
|
2015-11-05 03:22:38 +08:00
|
|
|
once sync.Once
|
2015-10-31 00:33:45 +08:00
|
|
|
|
|
|
|
WidgetWatchers
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetCenter sets the center text for the textbar. The text is
|
|
|
|
// always center aligned.
|
|
|
|
func (t *TextBar) SetCenter(s string, style tcell.Style) {
|
2015-11-05 03:22:38 +08:00
|
|
|
t.initialize()
|
2015-10-31 00:33:45 +08:00
|
|
|
if style == tcell.StyleDefault {
|
|
|
|
style = t.style
|
|
|
|
}
|
|
|
|
t.center.SetText(s)
|
|
|
|
t.center.SetStyle(style)
|
|
|
|
}
|
|
|
|
|
2015-11-05 03:22:38 +08:00
|
|
|
// SetLeft sets the left text for the textbar. It is always left-aligned.
|
2015-10-31 00:33:45 +08:00
|
|
|
func (t *TextBar) SetLeft(s string, style tcell.Style) {
|
2015-11-05 03:22:38 +08:00
|
|
|
t.initialize()
|
2015-10-31 00:33:45 +08:00
|
|
|
if style == tcell.StyleDefault {
|
|
|
|
style = t.style
|
|
|
|
}
|
|
|
|
t.left.SetText(s)
|
|
|
|
t.left.SetStyle(style)
|
|
|
|
}
|
|
|
|
|
2015-11-05 03:22:38 +08:00
|
|
|
// SetRight sets the right text for the textbar. It is always right-aligned.
|
2015-10-31 00:33:45 +08:00
|
|
|
func (t *TextBar) SetRight(s string, style tcell.Style) {
|
2015-11-05 03:22:38 +08:00
|
|
|
t.initialize()
|
2015-10-31 00:33:45 +08:00
|
|
|
if style == tcell.StyleDefault {
|
|
|
|
style = t.style
|
|
|
|
}
|
|
|
|
t.right.SetText(s)
|
|
|
|
t.right.SetStyle(style)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SetStyle is used to set a default style to use for the textbar, including
|
|
|
|
// areas where no text is present. Note that this will not change the text
|
2015-11-05 03:22:38 +08:00
|
|
|
// already displayed, so call this before changing or setting text.
|
2015-10-31 00:33:45 +08:00
|
|
|
func (t *TextBar) SetStyle(style tcell.Style) {
|
2015-11-05 03:22:38 +08:00
|
|
|
t.initialize()
|
2015-10-31 00:33:45 +08:00
|
|
|
t.style = style
|
|
|
|
}
|
|
|
|
|
2015-11-05 03:22:38 +08:00
|
|
|
func (t *TextBar) initialize() {
|
|
|
|
t.once.Do(func() {
|
|
|
|
t.center.SetView(&t.cview)
|
|
|
|
t.left.SetView(&t.lview)
|
|
|
|
t.right.SetView(&t.rview)
|
|
|
|
t.center.SetAlignment(VAlignTop | HAlignCenter)
|
|
|
|
t.left.SetAlignment(VAlignTop | HAlignLeft)
|
|
|
|
t.right.SetAlignment(VAlignTop | HAlignRight)
|
|
|
|
t.center.Watch(t)
|
|
|
|
t.left.Watch(t)
|
|
|
|
t.right.Watch(t)
|
|
|
|
})
|
2015-10-31 00:33:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (t *TextBar) layout() {
|
|
|
|
w, _ := t.view.Size()
|
|
|
|
ww, wh := t.left.Size()
|
|
|
|
t.lview.Resize(0, 0, ww, wh)
|
|
|
|
|
|
|
|
ww, wh = t.center.Size()
|
|
|
|
t.cview.Resize((w-ww)/2, 0, ww, wh)
|
|
|
|
|
|
|
|
ww, wh = t.right.Size()
|
|
|
|
t.rview.Resize(w-ww, 0, ww, wh)
|
|
|
|
|
|
|
|
t.changed = false
|
|
|
|
}
|
|
|
|
|
2015-11-05 03:22:38 +08:00
|
|
|
// SetView sets the View drawing context for this TextBar.
|
2015-10-31 00:33:45 +08:00
|
|
|
func (t *TextBar) SetView(view View) {
|
2015-11-05 03:22:38 +08:00
|
|
|
t.initialize()
|
2015-10-31 00:33:45 +08:00
|
|
|
t.view = view
|
|
|
|
t.lview.SetView(view)
|
|
|
|
t.rview.SetView(view)
|
|
|
|
t.cview.SetView(view)
|
|
|
|
t.changed = true
|
|
|
|
}
|
|
|
|
|
2015-11-05 03:22:38 +08:00
|
|
|
// Draw draws the TextBar into its View context.
|
2015-10-31 00:33:45 +08:00
|
|
|
func (t *TextBar) Draw() {
|
|
|
|
|
2015-11-05 03:22:38 +08:00
|
|
|
t.initialize()
|
2015-10-31 00:33:45 +08:00
|
|
|
if t.changed {
|
|
|
|
t.layout()
|
|
|
|
}
|
|
|
|
w, h := t.view.Size()
|
|
|
|
for y := 0; y < h; y++ {
|
|
|
|
for x := 0; x < w; x++ {
|
|
|
|
t.view.SetContent(x, y, ' ', nil, t.style)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Draw in reverse order -- if we clip, we will clip at the
|
|
|
|
// right side.
|
|
|
|
t.right.Draw()
|
|
|
|
t.center.Draw()
|
|
|
|
t.left.Draw()
|
|
|
|
}
|
|
|
|
|
2015-11-05 03:22:38 +08:00
|
|
|
// Resize is called when the TextBar's View changes size, and
|
|
|
|
// updates the layout.
|
2015-10-31 00:33:45 +08:00
|
|
|
func (t *TextBar) Resize() {
|
2015-11-05 03:22:38 +08:00
|
|
|
t.initialize()
|
2015-10-31 00:33:45 +08:00
|
|
|
t.layout()
|
|
|
|
|
|
|
|
t.left.Resize()
|
|
|
|
t.center.Resize()
|
|
|
|
t.right.Resize()
|
|
|
|
|
|
|
|
t.PostEventWidgetResize(t)
|
|
|
|
}
|
|
|
|
|
2015-11-05 03:22:38 +08:00
|
|
|
// Size implements the Size method for Widget, returning the width
|
|
|
|
// and height in character cells.
|
2015-10-31 00:33:45 +08:00
|
|
|
func (t *TextBar) Size() (int, int) {
|
|
|
|
w, h := 0, 0
|
|
|
|
|
|
|
|
ww, wh := t.left.Size()
|
|
|
|
w += ww
|
|
|
|
if wh > h {
|
|
|
|
h = wh
|
|
|
|
}
|
|
|
|
ww, wh = t.center.Size()
|
|
|
|
w += ww
|
|
|
|
if wh > h {
|
|
|
|
h = wh
|
|
|
|
}
|
|
|
|
ww, wh = t.right.Size()
|
|
|
|
w += ww
|
|
|
|
if wh > h {
|
|
|
|
h = wh
|
|
|
|
}
|
|
|
|
return w, h
|
|
|
|
}
|
|
|
|
|
2015-11-05 03:22:38 +08:00
|
|
|
// HandleEvent handles incoming events. The only events handled are
|
|
|
|
// those for the Text objects; when those change, the TextBar adjusts
|
|
|
|
// the layout to accommodate.
|
2015-10-31 00:33:45 +08:00
|
|
|
func (t *TextBar) HandleEvent(ev tcell.Event) bool {
|
|
|
|
switch ev.(type) {
|
|
|
|
case *EventWidgetContent:
|
|
|
|
t.changed = true
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2015-11-05 03:22:38 +08:00
|
|
|
// NewTextBar creates an empty, initialized TextBar.
|
2015-10-31 00:33:45 +08:00
|
|
|
func NewTextBar() *TextBar {
|
|
|
|
t := &TextBar{}
|
2015-11-05 03:22:38 +08:00
|
|
|
t.initialize()
|
2015-10-31 00:33:45 +08:00
|
|
|
return t
|
|
|
|
}
|