1# Terminal Dashboard High-Level Design
2
3## Objective
4
5Develop infrastructure of dashboard widgets. The widgets should support both
6input (mouse and keyboard) and output (display of information to the user).
7
8Fulfil the requirements outlined in the main
9[README](http://github.com/mum4k/termdash).
10
11## Background
12
13The terminal dashboard allows placement of configurable widgets onto the terminal.
14
15A widget displays some information to the user, e.g. A graph, a chart, a
16progress bar. A widget can receive information from the user in the form of
17events, e.g. Mouse or keyboard input.
18
19The widgets aren't placed onto the terminal directly, instead the terminal is
20organized into containers. Each container can contain either a widget or
21other containers.
22
23## Overview
24
25The terminal dashboard consists of the following layers:
26
27- Terminal.
28- Infrastructure.
29- Widgets.
30
31The **terminal layer** abstracts the terminal implementation. A real terminal
32implementation is used in production when displaying data to the user. A fake
33terminal implementation is used in widget unit tests and system tests. Other
34implementations are possible, e.g. Image export. The terminal layer is private,
35neither the users of this library nor the widgets interact with the terminal
36directly.
37
38The **infrastructure layer** is responsible for container management, tracking
39of keyboard and mouse focus and distribution and handling of external events
40like resizing of the terminal. The infrastructure layer also decides when to
41flush the buffer and refresh the screen. I.e. The widgets update content of a
42back buffer and the infrastructure decides when it is synchronized to the
43terminal.
44
45The **widgets layer** contains the implementations of individual widgets. Each
46widget receives a canvas from the container on which it presents its content to
47the user. Widgets indicate to the infrastructure layer if they support input
48events, which are then forwarded from the infrastructure layer.
49
50The user interacts with the widget API when constructing individual widgets and
51with the container API when placing the widgets onto the dashboard.
52
53<p align="center">
54  <img src="images/hld.png" width="50%">
55</p>
56
57## Detailed design
58
59### Terminal
60
61The terminal provides access to the input and output.
62
63It allows to:
64
65- Set values and attributes of cells on a back buffer representing a 2-D
66  canvas.
67- Flush the content of the back buffer to the output.
68- Manipulate the cursor position and visibility.
69- Allow the infrastructure to read input events (keyboard, mouse, terminal
70  resize, etc...).
71
72### Infrastructure
73
74The infrastructure handles terminal setup, input events and manages containers.
75
76#### Input events
77
78The infrastructure regularly polls events from the terminal layer and feeds
79them into the event distribution system (EDS). The EDS fulfils the following
80functions:
81
82- Allow subscribers to specify the type of events they want to receive.
83- Distributes events in a non-blocking manner, i.e. a single slow subscriber
84  cannot slow down other subscribers.
85- Events to each subscriber are throttled, if a subscriber builds a long tail
86  of unprocessed input events, the EDS selectively drops repetitive events
87  towards the subscriber and eventually implements a tail-drop strategy.
88
89The infrastructure itself is an input event subscriber and processes resize and
90error events. The infrastructure panics on error events by default, unless an
91error handler is provided by the user. Each widget that registers for keyboard
92or mouse events is also an event subscriber. Any errors that happen while
93processing an input event are send back to the EDS in the form of an Error
94event and are processed by the infrastructure.
95
96
97#### Input keyboard focus
98
99The infrastructure tracks focus. Only the focused widget receives keyboard
100events. Focus can be changed using mouse or keyboard shortcuts. The focused
101widget is highlighted on the dashboard.
102
103#### Containers
104
105The container provides a way of splitting the dashboard down to smaller
106elements where individual widgets can be placed. Each container can be split to
107multiple sub containers. A container contains either a sub container or a
108widget.
109
110Container is responsible for coordinate translation. Each widget receives a
111virtual canvas it can draw on. Each of these canvases starts at coordinates
112image.Point{0, 0}. The parent container translates coordinates from the virtual
113canvas to the real terminal. The container therefore enforces limits for widgets.
114
115Containers can be styled with borders and other options.
116
117#### Flushing the terminal
118
119All widgets indirectly write to the back buffer of the terminal implementation.
120The changes to the back buffer only become visible when the infrastructure
121flushes its content.
122
123#### Terminal resizing
124
125The terminal resize events are processed by the infrastructure. Each widget
126indicates its desired and minimum size for its canvas when registering with its
127parent container.
128
129The parent container in turn informs the widget what is the actual size of its
130canvas. The infrastructure guarantees that the actual size won't ever be
131smaller than the advertised minimum and guarantees that the size will keep the
132aspect ration requested by the widget.
133
134When the size of terminal changes, the infrastructure resizes all containers
135according to the rules outlined above, asks all widgets to redraw their
136canvases and flushes to the back buffer to the terminal.
137
138### Widgets
139
140Users of the terminal dashboard construct the widgets directly. Therefore each
141widget can define its own options and API for setting values (e.g. The
142displayed percentage on a progress bar). The users then create the desired
143container splits and place each widget into a dedicated container.
144
145Each widget receives a canvas from the parent container, the widget can draw
146anything on the canvas as long as it stays within the limits. Helper libraries
147are developed that allow placement and drawing of common elements like lines or
148geometric shapes.
149
150## APIs
151
152### Terminal API
153
154The Terminal API is an interface private to the terminal dashboard library. Its
155primary purpose is to act as a shim layer over different terminal
156implementations.
157
158The Terminal API is defined in the
159[terminalapi](http://github.com/mum4k/termdash/terminalapi/terminalapi.go)
160package.
161
162The **Event()** method returns the next input event. Different input event
163types are defined in the
164[event.go](http://github.com/mum4k/termdash/terminalapi/event.go)
165file.
166
167### Container API
168
169The Container API is used to split the terminal and place the widgets. Each
170container can be split to two sub containers or have a widget placed into it.
171A container can be split either horizontally or vertically.
172
173The containers further accept styling options and alignment options. The
174following indicates how the Container API will be used.
175
176The Container API is defined in the
177[container](http://github.com/mum4k/termdash/container/container.go)
178package.
179
180A demonstration how this is used from the client perspective is in the
181[container_test.go](http://github.com/mum4k/termdash/container/container_test.go)
182file.
183
184### Widget API
185
186Each widget must implement the Widget API. All widget implementations must
187be thread-safe since the calls that update the displayed values come in
188concurrently with requests and events from the infrastructure.
189
190The Widget API is defined in the
191[widget](http://github.com/mum4k/termdash/widget/widget.go)
192package.
193
194Each widget gets a Canvas to draw on. The Canvas API is defined in the
195[canvas](http://github.com/mum4k/termdash/canvas/canvas.go)
196package.
197
198## Testing plan
199
200Unit test helpers are provided with the terminal dashboard library, these
201include:
202
203- A fake implementation of the terminal API.
204- Unit test comparison helpers to verify the content of the fake terminal.
205- Visualization tools to display differences between the expected and the
206  actual.
207
208## Document history
209
210Date        | Author | Description
211------------|--------|-----------------------------------
21224-Mar-2018 | mum4k  | Initial draft.
21320-Feb-2019 | mum4k  | Added notes on event distribution.
214