114 lines
3.8 KiB
Go
114 lines
3.8 KiB
Go
package codeview
|
|
|
|
import (
|
|
"image"
|
|
"strings"
|
|
|
|
"gioui.org/f32"
|
|
"gioui.org/font"
|
|
"gioui.org/layout"
|
|
"gioui.org/op"
|
|
"gioui.org/op/clip"
|
|
"gioui.org/op/paint"
|
|
"gioui.org/widget/material"
|
|
|
|
"loov.dev/lensm/internal/asmhelp"
|
|
"loov.dev/lensm/internal/gui"
|
|
)
|
|
|
|
// layoutHelp draws the instruction help tooltip for the hovered assembly
|
|
// line, when help is enabled and the user is not selecting or editing.
|
|
func (ui Style) layoutHelp(gtx layout.Context, c codeColumns, hover codeHover) {
|
|
commentEditing := ui.CommentEditor != nil && gtx.Focused(ui.CommentEditor)
|
|
if !ui.ShowHelp || ui.selecting || commentEditing || !gui.InRange(hover.asmIndex, len(ui.Code.Insts)) {
|
|
return
|
|
}
|
|
inst := ui.Code.Insts[hover.asmIndex]
|
|
nativeHovered := ui.ShowNative && c.native.Contains(hover.position.X)
|
|
var help asmhelp.Help
|
|
var ok bool
|
|
if nativeHovered {
|
|
help, ok = asmhelp.ForNative(ui.Code.Arch, inst.Mnemonic, inst.NativeText)
|
|
} else {
|
|
help, ok = asmhelp.ForInstruction(ui.Code.Arch, inst.Mnemonic, inst.Text)
|
|
}
|
|
if ok {
|
|
ui.layoutAssemblyHelp(gtx, help, hover.position)
|
|
}
|
|
}
|
|
|
|
func (ui Style) layoutAssemblyHelp(gtx layout.Context, help asmhelp.Help, position f32.Point) {
|
|
maxWidth := gtx.Metric.Dp(460)
|
|
if maxWidth > gtx.Constraints.Max.X-16 {
|
|
maxWidth = max(0, gtx.Constraints.Max.X-16)
|
|
}
|
|
if maxWidth == 0 {
|
|
return
|
|
}
|
|
|
|
contentContext := gtx
|
|
contentContext.Constraints.Min = image.Point{}
|
|
contentContext.Constraints.Max = image.Pt(maxWidth, gtx.Metric.Dp(140))
|
|
macro := op.Record(gtx.Ops)
|
|
dims := layout.UniformInset(8).Layout(contentContext, func(gtx layout.Context) layout.Dimensions {
|
|
children := []layout.FlexChild{
|
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
label := material.Body1(ui.Theme.Theme, help.Mnemonic+" — "+help.Description)
|
|
label.Font.Weight = font.Bold
|
|
label.Color = ui.Theme.Colors.Text
|
|
label.TextSize = ui.TextHeight * 9 / 10
|
|
return label.Layout(gtx)
|
|
}),
|
|
}
|
|
if help.Explanation != "" {
|
|
children = append(children, layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
label := material.Body1(ui.Theme.Theme, help.Explanation)
|
|
label.Font.Typeface = "override-monospace,Go,monospace"
|
|
label.Color = ui.Syntax.Plain
|
|
label.TextSize = ui.TextHeight * 9 / 10
|
|
return layout.Inset{Top: 5}.Layout(gtx, label.Layout)
|
|
}))
|
|
}
|
|
if len(help.Ports) > 0 {
|
|
children = append(children, layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
label := material.Body1(ui.Theme.Theme, "ports: "+strings.Join(help.Ports, ", "))
|
|
label.Font.Typeface = "override-monospace,Go,monospace"
|
|
label.Color = ui.Syntax.Comment
|
|
label.TextSize = ui.TextHeight * 8 / 10
|
|
return layout.Inset{Top: 5}.Layout(gtx, label.Layout)
|
|
}))
|
|
}
|
|
if help.Note != "" {
|
|
children = append(children, layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
|
label := material.Body1(ui.Theme.Theme, help.Note)
|
|
label.Font.Style = font.Italic
|
|
label.Color = ui.Syntax.Comment
|
|
label.TextSize = ui.TextHeight * 8 / 10
|
|
return layout.Inset{Top: 5}.Layout(gtx, label.Layout)
|
|
}))
|
|
}
|
|
return layout.Flex{Axis: layout.Vertical}.Layout(gtx, children...)
|
|
})
|
|
call := macro.Stop()
|
|
|
|
left := int(position.X) + gtx.Metric.Dp(12)
|
|
top := int(position.Y) + gtx.Metric.Dp(18)
|
|
if left+dims.Size.X > gtx.Constraints.Max.X-4 {
|
|
left = gtx.Constraints.Max.X - dims.Size.X - 4
|
|
}
|
|
if top+dims.Size.Y > gtx.Constraints.Max.Y-4 {
|
|
top = int(position.Y) - dims.Size.Y - gtx.Metric.Dp(8)
|
|
}
|
|
left = max(4, left)
|
|
top = max(4, top)
|
|
|
|
stack := op.Offset(image.Pt(left, top)).Push(gtx.Ops)
|
|
paint.FillShape(gtx.Ops, ui.Theme.Colors.SecondaryBackground, clip.UniformRRect(image.Rectangle{Max: dims.Size}, 5).Op(gtx.Ops))
|
|
paint.FillShape(gtx.Ops, ui.Theme.Colors.Splitter, clip.Stroke{
|
|
Path: clip.UniformRRect(image.Rectangle{Max: dims.Size}, 5).Path(gtx.Ops),
|
|
Width: 1,
|
|
}.Op())
|
|
call.Add(gtx.Ops)
|
|
stack.Pop()
|
|
}
|