mirror of https://github.com/mum4k/termdash.git
203 lines
7.4 KiB
Go
203 lines
7.4 KiB
Go
// Copyright 2018 Google Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Package widgetapi defines the API of a widget on the dashboard.
|
|
package widgetapi
|
|
|
|
import (
|
|
"image"
|
|
|
|
"github.com/mum4k/termdash/private/canvas"
|
|
"github.com/mum4k/termdash/terminal/terminalapi"
|
|
)
|
|
|
|
// KeyScope indicates the scope at which the widget wants to receive keyboard
|
|
// events.
|
|
type KeyScope int
|
|
|
|
// String implements fmt.Stringer()
|
|
func (ks KeyScope) String() string {
|
|
if n, ok := keyScopeNames[ks]; ok {
|
|
return n
|
|
}
|
|
return "KeyScopeUnknown"
|
|
}
|
|
|
|
// keyScopeNames maps KeyScope values to human readable names.
|
|
var keyScopeNames = map[KeyScope]string{
|
|
KeyScopeNone: "KeyScopeNone",
|
|
KeyScopeFocused: "KeyScopeFocused",
|
|
KeyScopeGlobal: "KeyScopeGlobal",
|
|
}
|
|
|
|
const (
|
|
// KeyScopeNone is used when the widget doesn't want to receive any
|
|
// keyboard events.
|
|
KeyScopeNone KeyScope = iota
|
|
|
|
// KeyScopeFocused is used when the widget wants to only receive keyboard
|
|
// events when its container is focused.
|
|
KeyScopeFocused
|
|
|
|
// KeyScopeGlobal is used when the widget wants to receive all keyboard
|
|
// events regardless of which container is focused.
|
|
KeyScopeGlobal
|
|
)
|
|
|
|
// MouseScope indicates the scope at which the widget wants to receive mouse
|
|
// events.
|
|
type MouseScope int
|
|
|
|
// String implements fmt.Stringer()
|
|
func (ms MouseScope) String() string {
|
|
if n, ok := mouseScopeNames[ms]; ok {
|
|
return n
|
|
}
|
|
return "MouseScopeUnknown"
|
|
}
|
|
|
|
// mouseScopeNames maps MouseScope values to human readable names.
|
|
var mouseScopeNames = map[MouseScope]string{
|
|
MouseScopeNone: "MouseScopeNone",
|
|
MouseScopeWidget: "MouseScopeWidget",
|
|
MouseScopeContainer: "MouseScopeContainer",
|
|
MouseScopeGlobal: "MouseScopeGlobal",
|
|
}
|
|
|
|
const (
|
|
// MouseScopeNone is used when the widget doesn't want to receive any mouse
|
|
// events.
|
|
MouseScopeNone MouseScope = iota
|
|
|
|
// MouseScopeWidget is used when the widget only wants mouse events that
|
|
// fall onto its canvas.
|
|
// The position of these widgets is always relative to widget's canvas.
|
|
MouseScopeWidget
|
|
|
|
// MouseScopeContainer is used when the widget only wants mouse events that
|
|
// fall onto its container. The area size of a container is always larger
|
|
// or equal to the one of the widget's canvas. So a widget selecting
|
|
// MouseScopeContainer will either receive the same or larger amount of
|
|
// events as compared to MouseScopeWidget.
|
|
// The position of mouse events that fall outside of widget's canvas is
|
|
// reset to image.Point{-1, -1}.
|
|
// The widgets are allowed to process the button event.
|
|
MouseScopeContainer
|
|
|
|
// MouseScopeGlobal is used when the widget wants to receive all mouse
|
|
// events regardless on where on the terminal they land.
|
|
// The position of mouse events that fall outside of widget's canvas is
|
|
// reset to image.Point{-1, -1} and must not be used by the widgets.
|
|
// The widgets are allowed to process the button event.
|
|
MouseScopeGlobal
|
|
)
|
|
|
|
// Options contains registration options for a widget.
|
|
// This is how the widget indicates its needs to the infrastructure.
|
|
type Options struct {
|
|
// Ratio allows a widget to request a canvas whose size will always have
|
|
// the specified ratio of width:height (Ratio.X:Ratio.Y).
|
|
// The zero value i.e. image.Point{0, 0} indicates that the widget accepts
|
|
// canvas of any ratio.
|
|
Ratio image.Point
|
|
|
|
// MinimumSize allows a widget to specify the smallest allowed canvas size.
|
|
// If the terminal size and/or splits cause the assigned canvas to be
|
|
// smaller than this, the widget will be skipped. I.e. The Draw() method
|
|
// won't be called until a resize above the specified minimum.
|
|
MinimumSize image.Point
|
|
|
|
// MaximumSize allows a widget to specify the largest allowed canvas size.
|
|
// If the terminal size and/or splits cause the assigned canvas to be larger
|
|
// than this, the widget will only receive a canvas of this size within its
|
|
// container. Setting any of the two coordinates to zero indicates
|
|
// unlimited.
|
|
MaximumSize image.Point
|
|
|
|
// WantKeyboard allows a widget to request keyboard events and specify
|
|
// their desired scope. If set to KeyScopeNone, no keyboard events are
|
|
// forwarded to the widget.
|
|
WantKeyboard KeyScope
|
|
|
|
// ExclusiveKeyboardOnFocus allows a widget to request exclusive access to
|
|
// keyboard events when its container is focused. When set to true, no
|
|
// other widgets will receive any keyboard events that happen while the
|
|
// container of this widget is focused even if they registered for
|
|
// KeyScopeGlobal.
|
|
ExclusiveKeyboardOnFocus bool
|
|
|
|
// WantMouse allows a widget to request mouse events and specify their
|
|
// desired scope. If set to MouseScopeNone, no mouse events are forwarded
|
|
// to the widget.
|
|
// Note that the widget is only able to see the position of the mouse event
|
|
// if it falls onto its canvas. See the documentation next to individual
|
|
// MouseScope values for details.
|
|
WantMouse MouseScope
|
|
}
|
|
|
|
// Meta provide additional metadata to widgets.
|
|
type Meta struct {
|
|
// Focused asserts whether the widget's container is focused.
|
|
Focused bool
|
|
}
|
|
|
|
// EventMeta provides additional metadata about events to widgets.
|
|
type EventMeta struct {
|
|
// Focused asserts whether the widget's container is focused at the time of the event.
|
|
// If the event itself changes focus, the value here reflects the state of
|
|
// the focus after the change.
|
|
Focused bool
|
|
}
|
|
|
|
// Widget is a single widget on the dashboard.
|
|
// Implementations must be thread safe.
|
|
type Widget interface {
|
|
// When the infrastructure calls Draw(), the widget must block on the call
|
|
// until it finishes drawing onto the provided canvas. When given the
|
|
// canvas, the widget must first determine its size by calling
|
|
// Canvas.Size(), then limit all its drawing to this area.
|
|
//
|
|
// The widget must not assume that the size of the canvas or its content
|
|
// remains the same between calls.
|
|
//
|
|
// The argument meta is guaranteed to be valid (i.e. non-nil).
|
|
Draw(cvs *canvas.Canvas, meta *Meta) error
|
|
|
|
// Keyboard is called with every keyboard event whose scope the widget
|
|
// registered for.
|
|
//
|
|
// The argument meta is guaranteed to be valid (i.e. non-nil).
|
|
Keyboard(k *terminalapi.Keyboard, meta *EventMeta) error
|
|
|
|
// Mouse is called with every mouse event whose scope the widget registered
|
|
// for.
|
|
//
|
|
// The argument meta is guaranteed to be valid (i.e. non-nil).
|
|
Mouse(m *terminalapi.Mouse, meta *EventMeta) error
|
|
|
|
// Options returns registration options for the widget.
|
|
// This is how the widget indicates to the infrastructure whether it is
|
|
// interested in keyboard or mouse shortcuts, what is its minimum canvas
|
|
// size, etc.
|
|
//
|
|
// Most widgets will return statically compiled options (minimum and
|
|
// maximum size, etc.). If the returned options depend on the runtime state
|
|
// of the widget (e.g. the user data provided to the widget), the widget
|
|
// must protect against a case where the infrastructure calls the Draw
|
|
// method with a canvas that doesn't meet the requested options. This is
|
|
// because the data in the widget might change between calls to Options and
|
|
// Draw.
|
|
Options() Options
|
|
}
|