diff --git a/README.md b/README.md index da5fde9..91f6b0f 100644 --- a/README.md +++ b/README.md @@ -31,11 +31,13 @@ together. # Requirements -1. Apache-2.0 licence for the project. -1. Tree based container for placing dashboard elements. +1. Native support of the UTF-8 encoding. +1. Simple container management to position the widgets and set their size. 1. Mouse and keyboard input. 1. Cross-platform terminal based output. 1. Unit testing framework for simple and readable tests of dashboard elements. +1. Tooling to streamline addition of new widgets. +1. Apache-2.0 licence for the project. # High-Level design diff --git a/doc/design.md b/doc/design.md index 877999c..d5b5568 100644 --- a/doc/design.md +++ b/doc/design.md @@ -2,12 +2,154 @@ ## Objective +Develop infrastructure of dashboard widgets. The widgets should support both +input (mouse and keyboard) and output (display of information to the user). + +Fulfill the requirements outlined in the main +[README](http://github.com/mum4k/termdash). + ## Background +The terminal dashboard allows placement of configurable widgets onto the terminal. + +A widget displays some information to the user, e.g. A graph, a chart, a +progress bar. A widget can receive information from the user in the form of +events, e.g. Mouse or keyboard input. + +The widgets aren't placed onto the terminal directly, instead the terminal is +organized into containers. Each container can contain either a widget or +other containers. + ## Overview +The terminal dashboard consists of the following layers: + +- Display. +- Infrastructure. +- Widgets. + +The **display layer** abstracts the display implementation. A real terminal +implementation is used in production when displaying on the terminal. A fake +terminal implementation is used in widget unit tests and system tests. Other +implementations are possible, e.g. Image export. The display layer is private, +neither the users of this library nor the widgets interact with the display +directly. + +The **infrastructure layer** is responsible for container management, tracking +of keyboard and mouse focus and handling external events like resizing of the +display. The infrastructure layer also decides when to flush the buffer and +refresh the screen. I.e. The widgets update content of a back buffer and the +infrastructure decides when it is synchronized to the display. + +The **widgets layer** contains the implementations of individual widgets. Each +widget receives a canvas from the container on which it presents its content to +the user. Widgets indicate to the infrastructure layer if they support input +events, which are then forwarded from the infrastructure layer. + +The user interacts with the widget API when constructing individual widgets and +with the container API when placing the widgets onto the dashboard. + +![hld](hld.png "High-Level Design") + ## Detailed design +### Display + +### Infrastructure + +### Widgets + +## APIs + +### Display API + +The Display API is an interface private to the terminal dashboard library. Its +primary purpose is to act as a shim layer over different display +implementations. + +The API allows to: + +- Set values and attributes of cells on a back buffer representing a 2-D + canvas. +- Flush the content of the back buffer to the output. +- Manipulate the cursor position and visibility. +- Read input events (keyboard, mouse, display resize, etc...). + +The following outlines the display API: + +```go +// Display abstracts an implementation of a 2-D display. +// A display consists of a number of cells. +type Display interface { + // Size returns the display width and height in cells. + Size() image.Point + + // Clear clears the content of the internal back buffer, resetting all cells + // to their default content and attributes. + Clear() error + // Flush flushes the internal back buffer to the display. + Flush() error + + // SetCursor sets the position of the cursor. + SetCursor(p image.Point) + // HideCursos hides the cursor. + HideCursor() + + // SetCell sets the value of the specified cell to the provided rune. + // Use the options to specify which attributes to modify, if an attribute + // option isn't specified, the attribute retains its previous value. + SetCell(p image.Point, r rune, opts ...CellOption) + + // Event waits for the next event and returns it. + // This call blocks until the next event or cancellation of the context. + Event(ctx context.Context) Event +} +``` + +The **Event()** method returns the next input event. Different input event +types are defined as follows. + +``` +// Event represents an input event. +type Event interface { + isEvent() +} + +// Keyboard is the event used when a key is pressed. +// Implements Event. +type Keyboard struct { + // Key identifies the pressed key. + Key rune +} + +func (*Keyboard) isEvent() {} + +// DisplayResize is the event used when the display was resized. +// Implements Event. +type DisplayResize struct { + // Size is the new size of the display. + Size image.Point +} + +func (*DisplayResize) isEvent() {} + +// Mouse is the event used when the mouse is moved or a mouse button is +// pressed. +// Implements Event. +type Mouse struct { + // Position of the mouse on the display. + Position() image.Point + // Button identifies the pressed button if any. + Button MouseButton +} + +func (*Mouse) isEvent() {} +``` + +### Container API + +### Widget API + ## Project information ## Caveats @@ -20,5 +162,20 @@ ## Document history -Date | Author | Description ------|--------|------------ +Date | Author | Description +------------|--------|--------------- +24-Mar-2018 | mum4k | Initial draft. + +## Notes (work in progress) + +- container styling, borders. +- coordinates translation for widgets. +- library to parse events and identify known keyboard shortcuts. +- widget API (creation, options, updating displayed status, reading inputs). +- infra API for widgets. +- widget registration options (subscribe to input / events). +- testing framework (fake display and test helper functions). +- container and splits (layout management). +- buffer sync managed by infra. +- focus of keyboard and mouse (follow mouse / click). +- registration for system-wide events (like quit shortcuts). diff --git a/doc/hld.graffle b/doc/hld.graffle new file mode 100644 index 0000000..63a6652 Binary files /dev/null and b/doc/hld.graffle differ diff --git a/doc/hld.png b/doc/hld.png new file mode 100644 index 0000000..1a2f889 Binary files /dev/null and b/doc/hld.png differ