summaryrefslogtreecommitdiffstats
path: root/runtime/ui/view/status.go
blob: 87a4b46a5b9d5998dea1fbad832cdbdf497f1b9c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package view

import (
	"fmt"
	"github.com/sirupsen/logrus"
	"github.com/wagoodman/dive/runtime/ui/format"
	"github.com/wagoodman/dive/runtime/ui/key"
	"github.com/wagoodman/dive/utils"
	"strings"

	"github.com/jroimartin/gocui"
)

// Status holds the UI objects and data models for populating the bottom-most pane. Specifically the panel
// shows the user a set of possible actions to take in the window and currently selected pane.
type Status struct {
	name string
	gui  *gocui.Gui
	view *gocui.View

	selectedView    Helper
	requestedHeight int

	helpKeys []*key.Binding
}

// newStatusView creates a new view object attached the the global [gocui] screen object.
func newStatusView(gui *gocui.Gui) (controller *Status) {
	controller = new(Status)

	// populate main fields
	controller.name = "status"
	controller.gui = gui
	controller.helpKeys = make([]*key.Binding, 0)
	controller.requestedHeight = 1

	return controller
}

func (v *Status) SetCurrentView(r Helper) {
	v.selectedView = r
}

func (v *Status) Name() string {
	return v.name
}

func (v *Status) AddHelpKeys(keys ...*key.Binding) {
	v.helpKeys = append(v.helpKeys, keys...)
}

// Setup initializes the UI concerns within the context of a global [gocui] view object.
func (v *Status) Setup(view *gocui.View) error {
	logrus.Tracef("view.Setup() %s", v.Name())

	// set controller options
	v.view = view
	v.view.Frame = false

	return v.Render()
}

// IsVisible indicates if the status view pane is currently initialized.
func (v *Status) IsVisible() bool {
	return v != nil
}

// Update refreshes the state objects for future rendering (currently does nothing).
func (v *Status) Update() error {
	return nil
}

// OnLayoutChange is called whenever the screen dimensions are changed
func (v *Status) OnLayoutChange() error {
	err := v.Update()
	if err != nil {
		return err
	}
	return v.Render()
}

// Render flushes the state objects to the screen.
func (v *Status) Render() error {
	logrus.Tracef("view.Render() %s", v.Name())

	v.gui.Update(func(g *gocui.Gui) error {
		v.view.Clear()

		var selectedHelp string
		if v.selectedView != nil {
			selectedHelp = v.selectedView.KeyHelp()
		}

		_, err := fmt.Fprintln(v.view, v.KeyHelp()+selectedHelp+format.StatusNormal("▏"+strings.Repeat(" ", 1000)))
		if err != nil {
			logrus.Debug("unable to write to buffer: ", err)
		}

		return err
	})
	return nil
}

// KeyHelp indicates all the possible global actions a user can take when any pane is selected.
func (v *Status) KeyHelp() string {
	var help string
	for _, binding := range v.helpKeys {
		help += binding.RenderKeyHelp()
	}
	return help
}

func (v *Status) Layout(g *gocui.Gui, minX, minY, maxX, maxY int) error {
	logrus.Tracef("view.Layout(minX: %d, minY: %d, maxX: %d, maxY: %d) %s", minX, minY, maxX, maxY, v.Name())

	view, viewErr := g.SetView(v.Name(), minX, minY, maxX, maxY)
	if utils.IsNewView(viewErr) {
		err := v.Setup(view)
		if err != nil {
			logrus.Error("unable to setup status controller", err)
			return err
		}
	}
	return nil
}

func (v *Status) RequestedSize(available int) *int {
	return &v.requestedHeight
}