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