1package main
2
3import (
4	"fmt"
5	"strings"
6
7	"github.com/gdamore/tcell"
8	"github.com/rivo/tview"
9)
10
11const tableData = `OrderDate|Region|Rep|Item|Units|UnitCost|Total
121/6/2017|East|Jones|Pencil|95|1.99|189.05
131/23/2017|Central|Kivell|Binder|50|19.99|999.50
142/9/2017|Central|Jardine|Pencil|36|4.99|179.64
152/26/2017|Central|Gill|Pen|27|19.99|539.73
163/15/2017|West|Sorvino|Pencil|56|2.99|167.44
174/1/2017|East|Jones|Binder|60|4.99|299.40
184/18/2017|Central|Andrews|Pencil|75|1.99|149.25
195/5/2017|Central|Jardine|Pencil|90|4.99|449.10
205/22/2017|West|Thompson|Pencil|32|1.99|63.68
216/8/2017|East|Jones|Binder|60|8.99|539.40
226/25/2017|Central|Morgan|Pencil|90|4.99|449.10
237/12/2017|East|Howard|Binder|29|1.99|57.71
247/29/2017|East|Parent|Binder|81|19.99|1,619.19
258/15/2017|East|Jones|Pencil|35|4.99|174.65
269/1/2017|Central|Smith|Desk|2|125.00|250.00
279/18/2017|East|Jones|Pen Set|16|15.99|255.84
2810/5/2017|Central|Morgan|Binder|28|8.99|251.72
2910/22/2017|East|Jones|Pen|64|8.99|575.36
3011/8/2017|East|Parent|Pen|15|19.99|299.85
3111/25/2017|Central|Kivell|Pen Set|96|4.99|479.04
3212/12/2017|Central|Smith|Pencil|67|1.29|86.43
3312/29/2017|East|Parent|Pen Set|74|15.99|1,183.26
341/15/2018|Central|Gill|Binder|46|8.99|413.54
352/1/2018|Central|Smith|Binder|87|15.00|1,305.00
362/18/2018|East|Jones|Binder|4|4.99|19.96
373/7/2018|West|Sorvino|Binder|7|19.99|139.93
383/24/2018|Central|Jardine|Pen Set|50|4.99|249.50
394/10/2018|Central|Andrews|Pencil|66|1.99|131.34
404/27/2018|East|Howard|Pen|96|4.99|479.04
415/14/2018|Central|Gill|Pencil|53|1.29|68.37
425/31/2018|Central|Gill|Binder|80|8.99|719.20
436/17/2018|Central|Kivell|Desk|5|125.00|625.00
447/4/2018|East|Jones|Pen Set|62|4.99|309.38
457/21/2018|Central|Morgan|Pen Set|55|12.49|686.95
468/7/2018|Central|Kivell|Pen Set|42|23.95|1,005.90
478/24/2018|West|Sorvino|Desk|3|275.00|825.00
489/10/2018|Central|Gill|Pencil|7|1.29|9.03
499/27/2018|West|Sorvino|Pen|76|1.99|151.24
5010/14/2018|West|Thompson|Binder|57|19.99|1,139.43
5110/31/2018|Central|Andrews|Pencil|14|1.29|18.06
5211/17/2018|Central|Jardine|Binder|11|4.99|54.89
5312/4/2018|Central|Jardine|Binder|94|19.99|1,879.06
5412/21/2018|Central|Andrews|Binder|28|4.99|139.72`
55
56const tableBasic = `[green]func[white] [yellow]main[white]() {
57    table := tview.[yellow]NewTable[white]().
58        [yellow]SetFixed[white]([red]1[white], [red]1[white])
59    [yellow]for[white] row := [red]0[white]; row < [red]40[white]; row++ {
60        [yellow]for[white] column := [red]0[white]; column < [red]7[white]; column++ {
61            color := tcell.ColorWhite
62            [yellow]if[white] row == [red]0[white] {
63                color = tcell.ColorYellow
64            } [yellow]else[white] [yellow]if[white] column == [red]0[white] {
65                color = tcell.ColorDarkCyan
66            }
67            align := tview.AlignLeft
68            [yellow]if[white] row == [red]0[white] {
69                align = tview.AlignCenter
70            } [yellow]else[white] [yellow]if[white] column == [red]0[white] || column >= [red]4[white] {
71                align = tview.AlignRight
72            }
73            table.[yellow]SetCell[white](row,
74                column,
75                &tview.TableCell{
76                    Text:  [red]"..."[white],
77                    Color: color,
78                    Align: align,
79                })
80        }
81    }
82    tview.[yellow]NewApplication[white]().
83        [yellow]SetRoot[white](table, true).
84        [yellow]Run[white]()
85}`
86
87const tableSeparator = `[green]func[white] [yellow]main[white]() {
88    table := tview.[yellow]NewTable[white]().
89        [yellow]SetFixed[white]([red]1[white], [red]1[white]).
90        [yellow]SetSeparator[white](Borders.Vertical)
91    [yellow]for[white] row := [red]0[white]; row < [red]40[white]; row++ {
92        [yellow]for[white] column := [red]0[white]; column < [red]7[white]; column++ {
93            color := tcell.ColorWhite
94            [yellow]if[white] row == [red]0[white] {
95                color = tcell.ColorYellow
96            } [yellow]else[white] [yellow]if[white] column == [red]0[white] {
97                color = tcell.ColorDarkCyan
98            }
99            align := tview.AlignLeft
100            [yellow]if[white] row == [red]0[white] {
101                align = tview.AlignCenter
102            } [yellow]else[white] [yellow]if[white] column == [red]0[white] || column >= [red]4[white] {
103                align = tview.AlignRight
104            }
105            table.[yellow]SetCell[white](row,
106                column,
107                &tview.TableCell{
108                    Text:  [red]"..."[white],
109                    Color: color,
110                    Align: align,
111                })
112        }
113    }
114    tview.[yellow]NewApplication[white]().
115        [yellow]SetRoot[white](table, true).
116        [yellow]Run[white]()
117}`
118
119const tableBorders = `[green]func[white] [yellow]main[white]() {
120    table := tview.[yellow]NewTable[white]().
121        [yellow]SetFixed[white]([red]1[white], [red]1[white]).
122        [yellow]SetBorders[white](true)
123    [yellow]for[white] row := [red]0[white]; row < [red]40[white]; row++ {
124        [yellow]for[white] column := [red]0[white]; column < [red]7[white]; column++ {
125            color := tcell.ColorWhite
126            [yellow]if[white] row == [red]0[white] {
127                color = tcell.ColorYellow
128            } [yellow]else[white] [yellow]if[white] column == [red]0[white] {
129                color = tcell.ColorDarkCyan
130            }
131            align := tview.AlignLeft
132            [yellow]if[white] row == [red]0[white] {
133                align = tview.AlignCenter
134            } [yellow]else[white] [yellow]if[white] column == [red]0[white] || column >= [red]4[white] {
135                align = tview.AlignRight
136            }
137            table.[yellow]SetCell[white](row,
138                column,
139                &tview.TableCell{
140                    Text:  [red]"..."[white],
141                    Color: color,
142                    Align: align,
143                })
144        }
145    }
146    tview.[yellow]NewApplication[white]().
147        [yellow]SetRoot[white](table, true).
148        [yellow]Run[white]()
149}`
150
151const tableSelectRow = `[green]func[white] [yellow]main[white]() {
152    table := tview.[yellow]NewTable[white]().
153        [yellow]SetFixed[white]([red]1[white], [red]1[white]).
154        [yellow]SetSelectable[white](true, false)
155    [yellow]for[white] row := [red]0[white]; row < [red]40[white]; row++ {
156        [yellow]for[white] column := [red]0[white]; column < [red]7[white]; column++ {
157            color := tcell.ColorWhite
158            [yellow]if[white] row == [red]0[white] {
159                color = tcell.ColorYellow
160            } [yellow]else[white] [yellow]if[white] column == [red]0[white] {
161                color = tcell.ColorDarkCyan
162            }
163            align := tview.AlignLeft
164            [yellow]if[white] row == [red]0[white] {
165                align = tview.AlignCenter
166            } [yellow]else[white] [yellow]if[white] column == [red]0[white] || column >= [red]4[white] {
167                align = tview.AlignRight
168            }
169            table.[yellow]SetCell[white](row,
170                column,
171                &tview.TableCell{
172                    Text:          [red]"..."[white],
173                    Color:         color,
174                    Align:         align,
175                    NotSelectable: row == [red]0[white] || column == [red]0[white],
176                })
177        }
178    }
179    tview.[yellow]NewApplication[white]().
180        [yellow]SetRoot[white](table, true).
181        [yellow]Run[white]()
182}`
183
184const tableSelectColumn = `[green]func[white] [yellow]main[white]() {
185    table := tview.[yellow]NewTable[white]().
186        [yellow]SetFixed[white]([red]1[white], [red]1[white]).
187        [yellow]SetSelectable[white](false, true)
188    [yellow]for[white] row := [red]0[white]; row < [red]40[white]; row++ {
189        [yellow]for[white] column := [red]0[white]; column < [red]7[white]; column++ {
190            color := tcell.ColorWhite
191            [yellow]if[white] row == [red]0[white] {
192                color = tcell.ColorYellow
193            } [yellow]else[white] [yellow]if[white] column == [red]0[white] {
194                color = tcell.ColorDarkCyan
195            }
196            align := tview.AlignLeft
197            [yellow]if[white] row == [red]0[white] {
198                align = tview.AlignCenter
199            } [yellow]else[white] [yellow]if[white] column == [red]0[white] || column >= [red]4[white] {
200                align = tview.AlignRight
201            }
202            table.[yellow]SetCell[white](row,
203                column,
204                &tview.TableCell{
205                    Text:          [red]"..."[white],
206                    Color:         color,
207                    Align:         align,
208                    NotSelectable: row == [red]0[white] || column == [red]0[white],
209                })
210        }
211    }
212    tview.[yellow]NewApplication[white]().
213        [yellow]SetRoot[white](table, true).
214        [yellow]Run[white]()
215}`
216
217const tableSelectCell = `[green]func[white] [yellow]main[white]() {
218    table := tview.[yellow]NewTable[white]().
219        [yellow]SetFixed[white]([red]1[white], [red]1[white]).
220        [yellow]SetSelectable[white](true, true)
221    [yellow]for[white] row := [red]0[white]; row < [red]40[white]; row++ {
222        [yellow]for[white] column := [red]0[white]; column < [red]7[white]; column++ {
223            color := tcell.ColorWhite
224            [yellow]if[white] row == [red]0[white] {
225                color = tcell.ColorYellow
226            } [yellow]else[white] [yellow]if[white] column == [red]0[white] {
227                color = tcell.ColorDarkCyan
228            }
229            align := tview.AlignLeft
230            [yellow]if[white] row == [red]0[white] {
231                align = tview.AlignCenter
232            } [yellow]else[white] [yellow]if[white] column == [red]0[white] || column >= [red]4[white] {
233                align = tview.AlignRight
234            }
235            table.[yellow]SetCell[white](row,
236                column,
237                &tview.TableCell{
238                    Text:          [red]"..."[white],
239                    Color:         color,
240                    Align:         align,
241                    NotSelectable: row == [red]0[white] || column == [red]0[white],
242                })
243        }
244    }
245    tview.[yellow]NewApplication[white]().
246        [yellow]SetRoot[white](table, true).
247        [yellow]Run[white]()
248}`
249
250// Table demonstrates the Table.
251func Table(nextSlide func()) (title string, content tview.Primitive) {
252	table := tview.NewTable().
253		SetFixed(1, 1)
254	for row, line := range strings.Split(tableData, "\n") {
255		for column, cell := range strings.Split(line, "|") {
256			color := tcell.ColorWhite
257			if row == 0 {
258				color = tcell.ColorYellow
259			} else if column == 0 {
260				color = tcell.ColorDarkCyan
261			}
262			align := tview.AlignLeft
263			if row == 0 {
264				align = tview.AlignCenter
265			} else if column == 0 || column >= 4 {
266				align = tview.AlignRight
267			}
268			tableCell := tview.NewTableCell(cell).
269				SetTextColor(color).
270				SetAlign(align).
271				SetSelectable(row != 0 && column != 0)
272			if column >= 1 && column <= 3 {
273				tableCell.SetExpansion(1)
274			}
275			table.SetCell(row, column, tableCell)
276		}
277	}
278	table.SetBorder(true).SetTitle("Table")
279
280	code := tview.NewTextView().
281		SetWrap(false).
282		SetDynamicColors(true)
283	code.SetBorderPadding(1, 1, 2, 0)
284
285	list := tview.NewList()
286
287	basic := func() {
288		table.SetBorders(false).
289			SetSelectable(false, false).
290			SetSeparator(' ')
291		code.Clear()
292		fmt.Fprint(code, tableBasic)
293	}
294
295	separator := func() {
296		table.SetBorders(false).
297			SetSelectable(false, false).
298			SetSeparator(tview.Borders.Vertical)
299		code.Clear()
300		fmt.Fprint(code, tableSeparator)
301	}
302
303	borders := func() {
304		table.SetBorders(true).
305			SetSelectable(false, false)
306		code.Clear()
307		fmt.Fprint(code, tableBorders)
308	}
309
310	selectRow := func() {
311		table.SetBorders(false).
312			SetSelectable(true, false).
313			SetSeparator(' ')
314		code.Clear()
315		fmt.Fprint(code, tableSelectRow)
316	}
317
318	selectColumn := func() {
319		table.SetBorders(false).
320			SetSelectable(false, true).
321			SetSeparator(' ')
322		code.Clear()
323		fmt.Fprint(code, tableSelectColumn)
324	}
325
326	selectCell := func() {
327		table.SetBorders(false).
328			SetSelectable(true, true).
329			SetSeparator(' ')
330		code.Clear()
331		fmt.Fprint(code, tableSelectCell)
332	}
333
334	navigate := func() {
335		app.SetFocus(table)
336		table.SetDoneFunc(func(key tcell.Key) {
337			app.SetFocus(list)
338		}).SetSelectedFunc(func(row int, column int) {
339			app.SetFocus(list)
340		})
341	}
342
343	list.ShowSecondaryText(false).
344		AddItem("Basic table", "", 'b', basic).
345		AddItem("Table with separator", "", 's', separator).
346		AddItem("Table with borders", "", 'o', borders).
347		AddItem("Selectable rows", "", 'r', selectRow).
348		AddItem("Selectable columns", "", 'c', selectColumn).
349		AddItem("Selectable cells", "", 'l', selectCell).
350		AddItem("Navigate", "", 'n', navigate).
351		AddItem("Next slide", "", 'x', nextSlide)
352	list.SetBorderPadding(1, 1, 2, 2)
353
354	basic()
355
356	return "Table", tview.NewFlex().
357		AddItem(tview.NewFlex().
358			SetDirection(tview.FlexRow).
359			AddItem(list, 10, 1, true).
360			AddItem(table, 0, 1, false), 0, 1, true).
361		AddItem(code, codeWidth, 1, false)
362}
363