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
|
package compound
import (
"github.com/awesome-gocui/gocui"
"github.com/sirupsen/logrus"
"github.com/wagoodman/dive/runtime/ui/view"
"github.com/wagoodman/dive/utils"
)
type LayerDetailsCompoundLayout struct {
layer *view.Layer
layerDetails *view.LayerDetails
imageDetails *view.ImageDetails
constrainRealEstate bool
}
func NewLayerDetailsCompoundLayout(layer *view.Layer, layerDetails *view.LayerDetails, imageDetails *view.ImageDetails) *LayerDetailsCompoundLayout {
return &LayerDetailsCompoundLayout{
layer: layer,
layerDetails: layerDetails,
imageDetails: imageDetails,
}
}
func (cl *LayerDetailsCompoundLayout) Name() string {
return "layer-details-compound-column"
}
// OnLayoutChange is called whenever the screen dimensions are changed
func (cl *LayerDetailsCompoundLayout) OnLayoutChange() error {
err := cl.layer.OnLayoutChange()
if err != nil {
logrus.Error("unable to setup layer controller onLayoutChange", err)
return err
}
err = cl.layerDetails.OnLayoutChange()
if err != nil {
logrus.Error("unable to setup layer details controller onLayoutChange", err)
return err
}
err = cl.imageDetails.OnLayoutChange()
if err != nil {
logrus.Error("unable to setup image details controller onLayoutChange", err)
return err
}
return nil
}
func (cl *LayerDetailsCompoundLayout) layoutRow(g *gocui.Gui, minX, minY, maxX, maxY int, viewName string, setup func(*gocui.View, *gocui.View) error) error {
logrus.Tracef("layoutRow(g, minX: %d, minY: %d, maxX: %d, maxY: %d, viewName: %s, <setup func>)", minX, minY, maxX, maxY, viewName)
// header + border
headerHeight := 2
// TODO: investigate overlap
// note: maxY needs to account for the (invisible) border, thus a +1
headerView, headerErr := g.SetView(viewName+"Header", minX, minY, maxX, minY+headerHeight+1, 0)
// we are going to overlap the view over the (invisible) border (so minY will be one less than expected)
bodyView, bodyErr := g.SetView(viewName, minX, minY+headerHeight, maxX, maxY, 0)
if utils.IsNewView(bodyErr, headerErr) {
err := setup(bodyView, headerView)
if err != nil {
logrus.Debug("unable to setup row layout for ", viewName, err)
return err
}
}
return nil
}
func (cl *LayerDetailsCompoundLayout) Layout(g *gocui.Gui, minX, minY, maxX, maxY int) error {
logrus.Tracef("LayerDetailsCompountLayout.Layout(minX: %d, minY: %d, maxX: %d, maxY: %d) %s", minX, minY, maxX, maxY, cl.Name())
layouts := []view.IView{
cl.layer,
cl.layerDetails,
cl.imageDetails,
}
rowHeight := maxY / 3
for i := 0; i < 3; i++ {
if err := cl.layoutRow(g, minX, i*rowHeight, maxX, (i+1)*rowHeight, layouts[i].Name(), layouts[i].Setup); err != nil {
logrus.Debug("Laying out layers view errored!")
return err
}
}
if g.CurrentView() == nil {
if _, err := g.SetCurrentView(cl.layer.Name()); err != nil {
logrus.Error("unable to set view to layer", err)
return err
}
}
return nil
}
func (cl *LayerDetailsCompoundLayout) RequestedSize(available int) *int {
// "available" is the entire screen real estate, so we can guess when its a bit too small and take action.
// This isn't perfect, but it gets the job done for now without complicated layout constraint solvers
if available < 90 {
cl.layer.ConstrainLayout()
cl.constrainRealEstate = true
size := 8
return &size
}
cl.layer.ExpandLayout()
cl.constrainRealEstate = false
return nil
}
// todo: make this variable based on the nested views
func (cl *LayerDetailsCompoundLayout) IsVisible() bool {
return true
}
|