diff --git a/views/boxlayout.go b/views/boxlayout.go index 7ee335c..5e8f7f2 100644 --- a/views/boxlayout.go +++ b/views/boxlayout.go @@ -1,4 +1,4 @@ -// Copyright 2015 The Tcell Authors +// Copyright 2016 The Tcell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. @@ -202,7 +202,6 @@ func (b *BoxLayout) Draw() { if b.changed { b.layout() } -// b.view.Clear() b.view.Fill('*', b.style) w, h := b.view.Size() for y := 0; y < h; y++ { @@ -238,6 +237,7 @@ func (b *BoxLayout) HandleEvent(ev tcell.Event) bool { case *EventWidgetContent: // This can only have come from one of our children. b.changed = true + b.PostEventWidgetContent(b) return true } for _, c := range b.cells { @@ -255,7 +255,7 @@ func (b *BoxLayout) AddWidget(widget Widget, fill float64) { fill: fill, view: NewViewPort(b.view, 0, 0, 0, 0), } - c.widget.SetView(c.view) + widget.SetView(c.view) b.cells = append(b.cells, c) b.changed = true widget.Watch(b) diff --git a/views/cellarea.go b/views/cellarea.go index 26f4305..72a33d6 100644 --- a/views/cellarea.go +++ b/views/cellarea.go @@ -1,4 +1,4 @@ -// Copyright 2015 The Tcell Authors +// Copyright 2016 The Tcell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. @@ -15,6 +15,8 @@ package views import ( + "sync" + "github.com/gdamore/tcell" ) @@ -40,6 +42,7 @@ type CellView struct { style tcell.Style lines []string model CellModel + once sync.Once WidgetWatchers } @@ -49,7 +52,7 @@ func (a *CellView) Draw() { port := a.port model := a.model - port.Clear() + port.Fill(' ', a.style) if a.view == nil { return @@ -185,6 +188,7 @@ func (a *CellView) SetModel(model CellModel) { a.model = model a.port.SetContentSize(w, h, true) a.port.ValidateView() + a.PostEventWidgetContent(a) } // SetView sets the View context. @@ -242,10 +246,17 @@ func (a *CellView) SetStyle(s tcell.Style) { a.style = s } +// Init initializes a new CellView for use. +func (a *CellView) Init() { + a.once.Do(func() { + a.port = NewViewPort(nil, 0, 0, 0, 0) + a.style = tcell.StyleDefault + }) +} + // NewCellView creates a CellView. func NewCellView() *CellView { - return &CellView{ - port: NewViewPort(nil, 0, 0, 0, 0), - style: tcell.StyleDefault, - } + cv := &CellView{} + cv.Init() + return cv } diff --git a/views/sstext.go b/views/sstext.go index 93d04c1..3d316fe 100644 --- a/views/sstext.go +++ b/views/sstext.go @@ -15,8 +15,8 @@ package views import ( - "unicode" "github.com/gdamore/tcell" + "unicode" ) // SimpleStyledText is a form of Text that offers highlighting of the text diff --git a/views/sstextbar.go b/views/sstextbar.go index 47c5e98..6bb13e0 100644 --- a/views/sstextbar.go +++ b/views/sstextbar.go @@ -26,10 +26,10 @@ import ( // They align to the left, center, and right respectively. // This is basically a convenience type on top SimpleStyledText and BoxLayout. type SimpleStyledTextBar struct { - left *SimpleStyledText - right *SimpleStyledText - center *SimpleStyledText - once sync.Once + left *SimpleStyledText + right *SimpleStyledText + center *SimpleStyledText + once sync.Once BoxLayout } @@ -37,35 +37,56 @@ type SimpleStyledTextBar struct { // SetRight sets the right text for the textbar. // It is always right-aligned. func (s *SimpleStyledTextBar) SetRight(m string) { + s.initialize() s.right.SetMarkup(m) } // SetLeft sets the left text for the textbar. // It is always left-aligned. func (s *SimpleStyledTextBar) SetLeft(m string) { + s.initialize() s.left.SetMarkup(m) } // SetCenter sets the center text for the textbar. // It is always centered. func (s *SimpleStyledTextBar) SetCenter(m string) { + s.initialize() s.center.SetMarkup(m) } func (s *SimpleStyledTextBar) RegisterRightStyle(r rune, style tcell.Style) { + s.initialize() s.right.RegisterStyle(r, style) } func (s *SimpleStyledTextBar) RegisterLeftStyle(r rune, style tcell.Style) { + s.initialize() s.left.RegisterStyle(r, style) } func (s *SimpleStyledTextBar) RegisterCenterStyle(r rune, style tcell.Style) { + s.initialize() s.center.RegisterStyle(r, style) } +func (s *SimpleStyledTextBar) Size() (int, int) { + s.initialize() + w, h := s.BoxLayout.Size() + if h < 1 { + h = 1 + } + if w < 1 { + w = 1 + } + return w, h +} + func (s *SimpleStyledTextBar) initialize() { s.once.Do(func() { + s.center = NewSimpleStyledText() + s.left = NewSimpleStyledText() + s.right = NewSimpleStyledText() s.center.SetAlignment(VAlignTop | HAlignCenter) s.left.SetAlignment(VAlignTop | HAlignLeft) s.right.SetAlignment(VAlignTop | HAlignRight) @@ -78,13 +99,15 @@ func (s *SimpleStyledTextBar) initialize() { }) } +// Init prepares the widget for use, ensuring resources needed are +// allocated, etc. +func (s *SimpleStyledTextBar) Init() { + s.initialize() +} + // NewSimpleStyledTextBar creates an empty, initialized TextBar. func NewSimpleStyledTextBar() *SimpleStyledTextBar { - s := &SimpleStyledTextBar{ - center: NewSimpleStyledText(), - left: NewSimpleStyledText(), - right: NewSimpleStyledText(), - } + s := &SimpleStyledTextBar{} s.initialize() return s } diff --git a/views/textarea.go b/views/textarea.go index a872360..40b9707 100644 --- a/views/textarea.go +++ b/views/textarea.go @@ -1,4 +1,4 @@ -// Copyright 2015 The Tcell Authors +// Copyright 2016 The Tcell Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use file except in compliance with the License. @@ -16,6 +16,7 @@ package views import ( "strings" + "sync" "github.com/gdamore/tcell" ) @@ -26,8 +27,9 @@ import ( // a single line to display. All text in the TextArea has the same // style. An optional soft cursor is available. type TextArea struct { - view *CellView model *linesModel + once sync.Once + CellView } type linesModel struct { @@ -38,15 +40,16 @@ type linesModel struct { y int hide bool cursor bool + style tcell.Style } func (m *linesModel) GetCell(x, y int) (rune, tcell.Style, []rune, int) { var ch rune if x < 0 || y < 0 || y >= len(m.lines) || x >= len(m.lines[y]) { - return ch, tcell.StyleDefault, nil, 1 + return ch, m.style, nil, 1 } // XXX: extend this to support combining and full width chars - return rune(m.lines[y][x]), tcell.StyleDefault, nil, 1 + return rune(m.lines[y][x]), m.style, nil, 1 } func (m *linesModel) GetBounds() (int, int) { @@ -85,6 +88,7 @@ func (m *linesModel) GetCursor() (int, int, bool, bool) { // SetLines sets the content text to display. func (ta *TextArea) SetLines(lines []string) { + ta.Init() m := ta.model m.width = 0 m.height = len(lines) @@ -94,11 +98,17 @@ func (ta *TextArea) SetLines(lines []string) { m.width = len(l) } } - ta.view.SetModel(m) + ta.CellView.SetModel(m) +} + +func (ta *TextArea) SetStyle(style tcell.Style) { + ta.model.style = style + ta.CellView.SetStyle(style) } // EnableCursor enables a soft cursor in the TextArea. func (ta *TextArea) EnableCursor(on bool) { + ta.Init() ta.model.cursor = on } @@ -106,41 +116,31 @@ func (ta *TextArea) EnableCursor(on bool) { // If on is true, the cursor is hidden. Note that a cursor is only // shown if it is enabled. func (ta *TextArea) HideCursor(on bool) { + ta.Init() ta.model.hide = on } -// Draw draws the TextArea. -func (ta *TextArea) Draw() { - ta.view.Draw() -} - -// HandleEvent handles any events. -func (ta *TextArea) HandleEvent(ev tcell.Event) bool { - return ta.view.HandleEvent(ev) -} - -// Resize is called when the drawing context (View) changes size. -func (ta *TextArea) Resize() { - ta.view.Resize() -} - -// SetView sets the drawing context. -func (ta *TextArea) SetView(view View) { - ta.view.SetView(view) -} - // SetContent is used to set the textual content, passed as a // single string. Lines within the string are delimited by newlines. func (ta *TextArea) SetContent(text string) { + ta.Init() lines := strings.Split(strings.Trim(text, "\n"), "\n") ta.SetLines(lines) } +// Init initializes the TextArea. +func (ta *TextArea) Init() { + ta.once.Do(func() { + lm := &linesModel{lines: []string{}, width: 0} + ta.model = lm + ta.CellView.Init() + ta.CellView.SetModel(lm) + }) +} + // NewTextArea creates a blank TextArea. func NewTextArea() *TextArea { - lm := &linesModel{lines: []string{}, width: 0} - ta := &TextArea{model: lm} - ta.view = NewCellView() - ta.view.SetModel(lm) + ta := &TextArea{} + ta.Init() return ta }