summaryrefslogtreecommitdiffstats
path: root/runtime/ui/view/debug.go
blob: e78340eeaaa73f11971e23c23c9a02a832cf3d4a (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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package view

import (
	"fmt"
	"github.com/jroimartin/gocui"
	"github.com/sirupsen/logrus"
	"github.com/wagoodman/dive/runtime/ui/format"
	"github.com/wagoodman/dive/utils"
)

// Debug is just for me :)
type Debug struct {
	name   string
	gui    *gocui.Gui
	view   *gocui.View
	header *gocui.View
	//once   sync.Once
	hidden bool

	selectedView Helper
}

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

	// populate main fields
	controller.name = "debug"
	controller.gui = gui
	controller.hidden = true

	return controller
}

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

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

func (v *Debug) ToggleHide() error {
	v.hidden = !v.hidden
	if v.hidden {
		logrus.Trace("hiding debug view...")

		// take note: deleting a view will invoke layout again, so ensure this call is protected from an infinite loop
		err := v.gui.DeleteView(v.Name())
		if err != nil {
			return err
		}
		// take note: deleting a view will invoke layout again, so ensure this call is protected from an infinite loop
		err = v.gui.DeleteView(v.Name() + "header")
		if err != nil {
			return err
		}
	}
	return nil
}

func (v *Debug) IsHidden() bool {
	return v.hidden
}

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

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

	v.header = header
	v.header.Editable = false
	v.header.Wrap = false
	v.header.Frame = false

	return v.Render()
}

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

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

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

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

	v.gui.Update(func(g *gocui.Gui) error {
		// update header...
		v.header.Clear()
		width, _ := g.Size()
		headerStr := format.RenderHeader("Debug", width, false, false)
		_, _ = fmt.Fprintln(v.header, headerStr)

		// update view...
		v.view.Clear()
		_, err := fmt.Fprintln(v.view, "blerg")
		if err != nil {
			logrus.Debug("unable to write to buffer: ", err)
		}

		return nil
	})
	return nil
}

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

	// header
	headerSize := 1
	// note: maxY needs to account for the (invisible) border, thus a +1
	header, headerErr := g.SetView(v.Name()+"header", minX, minY, maxX, minY+headerSize+1)
	// we are going to overlap the view over the (invisible) border (so minY will be one less than expected).
	// additionally, maxY will be bumped by one to include the border
	view, viewErr := g.SetView(v.Name(), minX, minY+headerSize, maxX, maxY+1)
	if utils.IsNewView(viewErr, headerErr) {
		err := v.Setup(view, header)
		if err != nil {
			logrus.Error("unable to setup debug controller", err)
			return err
		}
	}
	return nil
}

func (v *Debug) RequestedSize(available int) *int {
	return nil
}