1// Copyright 2019 Graham Clark. All rights reserved.  Use of this source
2// code is governed by the MIT license that can be found in the LICENSE
3// file.
4
5// Package divider provides a widget that draws a dividing line between other widgets.
6package divider
7
8import (
9	"fmt"
10	"runtime"
11
12	"github.com/gcla/gowid"
13)
14
15//======================================================================
16
17var (
18	HorizontalLine    = '━'
19	AltHorizontalLine = '▀'
20)
21
22func init() {
23	switch runtime.GOOS {
24	case "windows":
25		HorizontalLine = '─'
26		AltHorizontalLine = HorizontalLine
27	case "darwin":
28		AltHorizontalLine = HorizontalLine
29	}
30}
31
32type IDivider interface {
33	Opts() Options
34}
35
36type IWidget interface {
37	gowid.IWidget
38	IDivider
39}
40
41type Widget struct {
42	opts Options
43	gowid.RejectUserInput
44	gowid.NotSelectable
45}
46
47type Options struct {
48	Chr          rune
49	Above, Below int
50}
51
52func New(opts ...Options) *Widget {
53	var opt Options
54	if len(opts) == 0 {
55		opt = Options{
56			Chr: '-',
57		}
58	} else {
59		opt = opts[0]
60	}
61	res := &Widget{
62		opts: opt,
63	}
64	var _ IWidget = res
65	return res
66}
67
68func NewAscii() *Widget {
69	return New(Options{
70		Chr: '-',
71	})
72}
73
74func NewBlank() *Widget {
75	return New(Options{
76		Chr: ' ',
77	})
78}
79
80func NewUnicode() *Widget {
81	return New(Options{
82		Chr: HorizontalLine,
83	})
84}
85
86func NewUnicodeAlt() *Widget {
87	return New(Options{
88		Chr: AltHorizontalLine,
89	})
90}
91
92func (w *Widget) String() string {
93	return fmt.Sprintf("div[%c]", w.Opts().Chr)
94}
95
96func (w *Widget) Opts() Options {
97	return w.opts
98}
99
100func (w *Widget) RenderSize(size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.IRenderBox {
101	return RenderSize(w, size, focus, app)
102}
103
104func (w *Widget) Render(size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.ICanvas {
105	return Render(w, size, focus, app)
106}
107
108//''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
109
110func RenderSize(w IDivider, size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.IRenderBox {
111	if flow, ok := size.(gowid.IRenderFlowWith); !ok {
112		panic(gowid.WidgetSizeError{Widget: w, Size: size, Required: "gowid.IRenderFlowWith"})
113	} else {
114		return gowid.RenderBox{C: flow.FlowColumns(), R: w.Opts().Above + w.Opts().Below + 1}
115	}
116}
117
118func Render(w IDivider, size gowid.IRenderSize, focus gowid.Selector, app gowid.IApp) gowid.ICanvas {
119	flow, ok := size.(gowid.IRenderFlowWith)
120	if !ok {
121		panic(gowid.WidgetSizeError{Widget: w, Size: size, Required: "gowid.IRenderFlowWith"})
122	}
123
124	div := gowid.CellFromRune(w.Opts().Chr)
125	divArr := make([]gowid.Cell, flow.FlowColumns())
126	for i := 0; i < flow.FlowColumns(); i++ {
127		divArr[i] = div
128	}
129
130	res := gowid.NewCanvas()
131	for i := 0; i < w.Opts().Above; i++ {
132		res.AppendLine([]gowid.Cell{}, false)
133	}
134	res.AppendLine(divArr, false)
135	for i := 0; i < w.Opts().Below; i++ {
136		res.AppendLine([]gowid.Cell{}, false)
137	}
138	res.AlignRight()
139
140	return res
141}
142
143//======================================================================
144// Local Variables:
145// mode: Go
146// fill-column: 110
147// End:
148