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  }