github.com/jmigpin/editor@v1.6.0/ui/contextfloatbox.go (about) 1 package ui 2 3 import ( 4 "image" 5 6 "github.com/jmigpin/editor/util/uiutil/event" 7 "github.com/jmigpin/editor/util/uiutil/widget" 8 ) 9 10 type ContextFloatBox struct { 11 *widget.FloatBox 12 13 root *Root 14 sa *widget.ScrollArea 15 TextArea *TextArea 16 } 17 18 func NewContextFloatBox(root *Root) *ContextFloatBox { 19 cfb := &ContextFloatBox{root: root} 20 21 cfb.TextArea = NewTextArea(root.UI) 22 cfb.SetStrClearHistory("") 23 24 cfb.sa = widget.NewScrollArea(root.UI, cfb.TextArea, false, true) 25 cfb.sa.LeftScroll = ScrollBarLeft 26 27 border := widget.NewBorder(root.UI, cfb.sa) 28 border.SetAll(1) 29 30 container := WrapInBottomShadowOrNone(root.UI, border) 31 32 cfb.FloatBox = widget.NewFloatBox(root.MultiLayer, container) 33 cfb.FloatBox.MaxSize = image.Point{800, 100000} 34 root.MultiLayer.ContextLayer.Append(cfb) 35 cfb.FloatBox.Hide() 36 37 cfb.SetThemePaletteNamePrefix("contextfloatbox_") 38 39 return cfb 40 } 41 42 //---------- 43 44 func (cfb *ContextFloatBox) SetStrClearHistory(s string) { 45 if s == "" { 46 s = "No content provided." 47 } 48 cfb.TextArea.SetStrClearHistory(s) 49 } 50 51 //---------- 52 53 func (cfb *ContextFloatBox) Layout() { 54 ff := cfb.TextArea.TreeThemeFontFace() 55 cfb.sa.ScrollWidth = UIThemeUtil.GetScrollBarWidth(ff) 56 cfb.FloatBox.Layout() 57 } 58 59 //---------- 60 61 func (cfb *ContextFloatBox) OnInputEvent(ev interface{}, p image.Point) event.Handled { 62 switch ev.(type) { 63 case *event.KeyUp, 64 *event.KeyDown: 65 // let lower layers get events 66 return false 67 } 68 return true 69 } 70 71 //---------- 72 73 func (cfb *ContextFloatBox) AutoClose(ev interface{}, p image.Point) { 74 if cfb.Visible() && !p.In(cfb.Bounds) { 75 switch ev.(type) { 76 case *event.KeyDown, 77 *event.MouseDown: 78 cfb.Hide() 79 return 80 case *event.MouseMove: 81 default: 82 //fmt.Printf("%T\n", ev) 83 } 84 } 85 } 86 87 //---------- 88 89 func (cfb *ContextFloatBox) Toggle() { 90 visible := cfb.Visible() 91 if !visible { 92 cfb.Show() 93 } else { 94 cfb.Hide() 95 } 96 } 97 98 //---------- 99 100 func (cfb *ContextFloatBox) SetRefPointToTextAreaCursor(ta *TextArea) { 101 p := ta.GetPoint(ta.CursorIndex()) 102 p.Y += ta.LineHeight() 103 cfb.RefPoint = p 104 // compensate scrollwidth for a better position 105 if cfb.sa.LeftScroll { 106 cfb.RefPoint.X -= cfb.sa.ScrollWidth 107 } 108 } 109 110 //---------- 111 112 func (cfb *ContextFloatBox) FindTextAreaUnderPointer() (*TextArea, bool) { 113 // pointer position 114 p, err := cfb.root.UI.QueryPointer() 115 if err != nil { 116 return nil, false 117 } 118 ta := cfb.visitToFindTA(p, cfb.root) 119 return ta, ta != nil 120 } 121 122 func (cfb *ContextFloatBox) visitToFindTA(p image.Point, node widget.Node) (ta *TextArea) { 123 if p.In(node.Embed().Bounds) { 124 if u, ok := node.(*TextArea); ok { 125 return u 126 } 127 if u, ok := node.(*Toolbar); ok { 128 return u.TextArea 129 } 130 if u, ok := node.(*RowToolbar); ok { 131 return u.TextArea 132 } 133 } 134 node.Embed().IterateWrappersReverse(func(n widget.Node) bool { 135 u := cfb.visitToFindTA(p, n) 136 if u != nil { 137 ta = u 138 return false 139 } 140 return true 141 }) 142 return ta 143 }