2017-11-09 02:11:05 +00:00
|
|
|
package editor
|
2017-06-28 08:28:24 +01:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2018-09-02 15:55:24 +09:00
|
|
|
"math"
|
2017-06-28 08:28:24 +01:00
|
|
|
|
2018-04-29 18:34:49 +09:00
|
|
|
"github.com/akiyosi/gonvim/fuzzy"
|
2017-06-28 08:28:24 +01:00
|
|
|
"github.com/therecipe/qt/core"
|
|
|
|
"github.com/therecipe/qt/gui"
|
|
|
|
"github.com/therecipe/qt/svg"
|
|
|
|
"github.com/therecipe/qt/widgets"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Palette is the popup for fuzzy finder, cmdline etc
|
|
|
|
type Palette struct {
|
2018-10-31 12:12:57 +09:00
|
|
|
// mu sync.Mutex
|
|
|
|
// procCount int
|
2018-01-05 08:07:29 +00:00
|
|
|
ws *Workspace
|
2017-11-09 01:41:26 +00:00
|
|
|
hidden bool
|
2017-06-28 11:06:47 +01:00
|
|
|
widget *widgets.QWidget
|
|
|
|
patternText string
|
|
|
|
resultItems []*PaletteResultItem
|
|
|
|
resultWidget *widgets.QWidget
|
|
|
|
resultMainWidget *widgets.QWidget
|
|
|
|
itemHeight int
|
|
|
|
width int
|
|
|
|
cursor *widgets.QWidget
|
|
|
|
cursorX int
|
|
|
|
resultType string
|
|
|
|
itemTypes []string
|
|
|
|
max int
|
|
|
|
showTotal int
|
|
|
|
pattern *widgets.QLabel
|
|
|
|
patternPadding int
|
|
|
|
patternWidget *widgets.QWidget
|
|
|
|
scrollBar *widgets.QWidget
|
|
|
|
scrollBarPos int
|
|
|
|
scrollCol *widgets.QWidget
|
2017-06-28 08:28:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// PaletteResultItem is the result item
|
|
|
|
type PaletteResultItem struct {
|
2018-01-05 08:07:29 +00:00
|
|
|
p *Palette
|
2017-06-28 08:28:24 +01:00
|
|
|
hidden bool
|
|
|
|
icon *svg.QSvgWidget
|
|
|
|
iconType string
|
|
|
|
iconHidden bool
|
|
|
|
base *widgets.QLabel
|
|
|
|
baseText string
|
|
|
|
widget *widgets.QWidget
|
|
|
|
selected bool
|
|
|
|
}
|
|
|
|
|
|
|
|
func initPalette() *Palette {
|
|
|
|
width := 600
|
|
|
|
mainLayout := widgets.NewQVBoxLayout()
|
|
|
|
mainLayout.SetContentsMargins(0, 0, 0, 0)
|
|
|
|
mainLayout.SetSpacing(0)
|
2017-11-09 01:41:26 +00:00
|
|
|
mainLayout.SetSizeConstraint(widgets.QLayout__SetMinAndMaxSize)
|
2017-06-28 08:28:24 +01:00
|
|
|
widget := widgets.NewQWidget(nil, 0)
|
|
|
|
widget.SetLayout(mainLayout)
|
|
|
|
widget.SetContentsMargins(1, 1, 1, 1)
|
2017-11-09 01:41:26 +00:00
|
|
|
// widget.SetFixedWidth(width)
|
2017-06-28 08:28:24 +01:00
|
|
|
widget.SetObjectName("palette")
|
|
|
|
shadow := widgets.NewQGraphicsDropShadowEffect(nil)
|
2018-12-04 22:33:14 +09:00
|
|
|
shadow.SetBlurRadius(35)
|
2018-12-05 12:20:51 +09:00
|
|
|
shadow.SetColor(gui.NewQColor3(0, 0, 0, 200))
|
2018-12-04 22:33:14 +09:00
|
|
|
shadow.SetOffset3(-2, 8)
|
2017-06-28 08:28:24 +01:00
|
|
|
widget.SetGraphicsEffect(shadow)
|
|
|
|
|
|
|
|
resultMainLayout := widgets.NewQHBoxLayout()
|
|
|
|
resultMainLayout.SetContentsMargins(0, 0, 0, 0)
|
|
|
|
resultMainLayout.SetSpacing(0)
|
2017-11-09 01:41:26 +00:00
|
|
|
resultMainLayout.SetSizeConstraint(widgets.QLayout__SetMinAndMaxSize)
|
2017-06-28 08:28:24 +01:00
|
|
|
|
|
|
|
padding := 8
|
|
|
|
resultLayout := widgets.NewQVBoxLayout()
|
|
|
|
resultLayout.SetContentsMargins(0, 0, 0, 0)
|
|
|
|
resultLayout.SetSpacing(0)
|
2017-11-09 01:41:26 +00:00
|
|
|
resultLayout.SetSizeConstraint(widgets.QLayout__SetMinAndMaxSize)
|
2017-06-28 08:28:24 +01:00
|
|
|
resultWidget := widgets.NewQWidget(nil, 0)
|
2018-11-06 00:42:06 +09:00
|
|
|
resultWidget.SetFont(gui.NewQFont2(editor.config.Editor.FontFamily, editor.config.Editor.FontSize, 1, false))
|
2017-06-28 08:28:24 +01:00
|
|
|
resultWidget.SetLayout(resultLayout)
|
|
|
|
resultWidget.SetContentsMargins(0, 0, 0, 0)
|
|
|
|
|
|
|
|
scrollCol := widgets.NewQWidget(nil, 0)
|
|
|
|
scrollCol.SetContentsMargins(0, 0, 0, 0)
|
|
|
|
scrollCol.SetFixedWidth(5)
|
|
|
|
scrollBar := widgets.NewQWidget(scrollCol, 0)
|
|
|
|
scrollBar.SetFixedWidth(5)
|
|
|
|
|
|
|
|
resultMainWidget := widgets.NewQWidget(nil, 0)
|
2018-11-06 00:42:06 +09:00
|
|
|
resultMainWidget.SetFont(gui.NewQFont2(editor.config.Editor.FontFamily, editor.config.Editor.FontSize, 1, false))
|
2017-06-28 08:28:24 +01:00
|
|
|
resultMainWidget.SetContentsMargins(0, 0, 0, 0)
|
|
|
|
resultMainLayout.AddWidget(resultWidget, 0, 0)
|
|
|
|
resultMainLayout.AddWidget(scrollCol, 0, 0)
|
|
|
|
resultMainWidget.SetLayout(resultMainLayout)
|
|
|
|
|
|
|
|
pattern := widgets.NewQLabel(nil, 0)
|
2018-11-06 00:42:06 +09:00
|
|
|
pattern.SetFont(gui.NewQFont2(editor.config.Editor.FontFamily, editor.config.Editor.FontSize, 1, false))
|
2017-06-28 08:28:24 +01:00
|
|
|
pattern.SetContentsMargins(padding, padding, padding, padding)
|
2017-11-09 01:41:26 +00:00
|
|
|
pattern.SetFixedWidth(width - padding*2)
|
|
|
|
pattern.SetSizePolicy2(widgets.QSizePolicy__Preferred, widgets.QSizePolicy__Maximum)
|
2017-06-28 08:28:24 +01:00
|
|
|
patternLayout := widgets.NewQVBoxLayout()
|
|
|
|
patternLayout.AddWidget(pattern, 0, 0)
|
|
|
|
patternLayout.SetContentsMargins(0, 0, 0, 0)
|
|
|
|
patternLayout.SetSpacing(0)
|
2017-11-09 01:41:26 +00:00
|
|
|
patternLayout.SetSizeConstraint(widgets.QLayout__SetMinAndMaxSize)
|
2017-06-28 08:28:24 +01:00
|
|
|
patternWidget := widgets.NewQWidget(nil, 0)
|
|
|
|
patternWidget.SetLayout(patternLayout)
|
|
|
|
patternWidget.SetContentsMargins(padding, padding, padding, padding)
|
|
|
|
|
|
|
|
cursor := widgets.NewQWidget(nil, 0)
|
|
|
|
cursor.SetParent(pattern)
|
|
|
|
cursor.SetFixedSize2(1, pattern.SizeHint().Height()-padding*2)
|
|
|
|
cursor.Move2(padding, padding)
|
|
|
|
|
|
|
|
mainLayout.AddWidget(patternWidget, 0, 0)
|
|
|
|
mainLayout.AddWidget(resultMainWidget, 0, 0)
|
|
|
|
|
2018-01-05 08:07:29 +00:00
|
|
|
palette := &Palette{
|
|
|
|
width: width,
|
|
|
|
widget: widget,
|
|
|
|
resultWidget: resultWidget,
|
|
|
|
resultMainWidget: resultMainWidget,
|
|
|
|
pattern: pattern,
|
|
|
|
patternPadding: padding,
|
|
|
|
patternWidget: patternWidget,
|
|
|
|
scrollCol: scrollCol,
|
|
|
|
scrollBar: scrollBar,
|
|
|
|
cursor: cursor,
|
|
|
|
}
|
|
|
|
|
2017-06-28 08:28:24 +01:00
|
|
|
resultItems := []*PaletteResultItem{}
|
|
|
|
max := 30
|
|
|
|
for i := 0; i < max; i++ {
|
|
|
|
itemWidget := widgets.NewQWidget(nil, 0)
|
|
|
|
itemWidget.SetContentsMargins(0, 0, 0, 0)
|
2018-09-04 22:11:46 +09:00
|
|
|
itemLayout := newVFlowLayout(padding, padding*2, 0, 0, 9999)
|
2017-11-09 01:41:26 +00:00
|
|
|
itemLayout.SetSizeConstraint(widgets.QLayout__SetMinAndMaxSize)
|
2017-06-28 08:28:24 +01:00
|
|
|
itemWidget.SetLayout(itemLayout)
|
|
|
|
resultLayout.AddWidget(itemWidget, 0, 0)
|
|
|
|
icon := svg.NewQSvgWidget(nil)
|
2018-11-08 18:10:12 +09:00
|
|
|
icon.SetFixedWidth(editor.iconSize - 1)
|
|
|
|
icon.SetFixedHeight(editor.iconSize - 1)
|
2017-06-28 08:28:24 +01:00
|
|
|
icon.SetContentsMargins(0, 0, 0, 0)
|
|
|
|
base := widgets.NewQLabel(nil, 0)
|
2018-11-06 00:42:06 +09:00
|
|
|
base.SetFont(gui.NewQFont2(editor.config.Editor.FontFamily, editor.config.Editor.FontSize, 1, false))
|
2017-06-28 08:28:24 +01:00
|
|
|
base.SetText("base")
|
|
|
|
base.SetContentsMargins(0, padding, 0, padding)
|
|
|
|
base.SetStyleSheet("background-color: none; white-space: pre-wrap;")
|
2017-11-09 01:41:26 +00:00
|
|
|
// base.SetSizePolicy2(widgets.QSizePolicy__Preferred, widgets.QSizePolicy__Maximum)
|
2017-06-28 08:28:24 +01:00
|
|
|
itemLayout.AddWidget(icon)
|
|
|
|
itemLayout.AddWidget(base)
|
|
|
|
resultItem := &PaletteResultItem{
|
2018-01-05 08:07:29 +00:00
|
|
|
p: palette,
|
2017-06-28 08:28:24 +01:00
|
|
|
widget: itemWidget,
|
|
|
|
icon: icon,
|
|
|
|
base: base,
|
|
|
|
}
|
|
|
|
resultItems = append(resultItems, resultItem)
|
|
|
|
}
|
2018-01-05 08:07:29 +00:00
|
|
|
palette.max = max
|
|
|
|
palette.resultItems = resultItems
|
2017-06-28 08:28:24 +01:00
|
|
|
return palette
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Palette) resize() {
|
2018-10-31 12:12:57 +09:00
|
|
|
// if p.procCount > 0 {
|
|
|
|
// return
|
|
|
|
// }
|
|
|
|
// go func() {
|
|
|
|
// p.mu.Lock()
|
|
|
|
// defer p.mu.Unlock()
|
|
|
|
// p.procCount = 1
|
|
|
|
// defer func() { p.procCount = 0 }()
|
|
|
|
|
|
|
|
padding := 8
|
|
|
|
p.width = int(math.Trunc(float64(editor.width) * 0.7))
|
|
|
|
cursorBoundary := p.cursor.Pos().X() + 35
|
|
|
|
|
|
|
|
if cursorBoundary > p.width {
|
|
|
|
p.width = cursorBoundary
|
2018-01-11 06:11:34 +00:00
|
|
|
}
|
2018-10-31 12:12:57 +09:00
|
|
|
if p.width > editor.width {
|
|
|
|
p.width = editor.width
|
|
|
|
p.pattern.SetAlignment(core.Qt__AlignRight | core.Qt__AlignCenter)
|
|
|
|
return
|
|
|
|
} else if p.width <= editor.width {
|
|
|
|
if p.pattern.Alignment() != core.Qt__AlignLeft {
|
|
|
|
p.pattern.SetAlignment(core.Qt__AlignLeft)
|
2018-09-02 15:55:24 +09:00
|
|
|
return
|
|
|
|
}
|
2018-10-31 12:12:57 +09:00
|
|
|
}
|
2017-06-28 08:28:24 +01:00
|
|
|
|
2018-10-31 12:12:57 +09:00
|
|
|
p.pattern.SetFixedWidth(p.width - padding*2)
|
|
|
|
p.widget.SetMaximumWidth(p.width)
|
|
|
|
p.widget.SetMinimumWidth(p.width)
|
2018-09-02 15:55:24 +09:00
|
|
|
|
2018-10-31 12:12:57 +09:00
|
|
|
x := editor.width - p.width
|
|
|
|
if x < 0 {
|
|
|
|
x = 0
|
|
|
|
}
|
|
|
|
p.widget.Move2(x/2, 0)
|
2018-09-02 15:55:24 +09:00
|
|
|
|
2018-10-31 12:12:57 +09:00
|
|
|
itemHeight := p.resultItems[0].widget.SizeHint().Height()
|
|
|
|
p.itemHeight = itemHeight
|
|
|
|
p.showTotal = int(float64(p.ws.height)/float64(itemHeight)*0.5) - 1
|
|
|
|
if p.ws.uiAttached {
|
|
|
|
fuzzy.UpdateMax(p.ws.nvim, p.showTotal)
|
|
|
|
}
|
|
|
|
for i := p.showTotal; i < len(p.resultItems); i++ {
|
|
|
|
p.resultItems[i].hide()
|
|
|
|
}
|
|
|
|
// }()
|
2017-06-28 08:28:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Palette) show() {
|
2017-11-09 01:41:26 +00:00
|
|
|
if !p.hidden {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
p.hidden = false
|
2018-09-02 15:55:24 +09:00
|
|
|
p.widget.Raise()
|
|
|
|
p.widget.SetWindowOpacity(1.0)
|
2017-06-28 08:28:24 +01:00
|
|
|
p.widget.Show()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Palette) hide() {
|
2017-11-09 01:41:26 +00:00
|
|
|
if p.hidden {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
p.hidden = true
|
2017-06-28 08:28:24 +01:00
|
|
|
p.widget.Hide()
|
|
|
|
}
|
|
|
|
|
2017-06-28 11:06:47 +01:00
|
|
|
func (p *Palette) setPattern(text string) {
|
|
|
|
p.patternText = text
|
|
|
|
p.pattern.SetText(text)
|
|
|
|
}
|
|
|
|
|
2017-06-28 08:28:24 +01:00
|
|
|
func (p *Palette) cursorMove(x int) {
|
2018-07-01 07:19:43 +09:00
|
|
|
//p.cursorX = int(p.ws.font.defaultFontMetrics.Width(string(p.patternText[:x])))
|
2018-11-06 00:42:06 +09:00
|
|
|
font := gui.NewQFontMetricsF(gui.NewQFont2(editor.config.Editor.FontFamily, editor.config.Editor.FontSize, 1, false))
|
|
|
|
p.cursorX = int(font.HorizontalAdvance(string(p.patternText[:x]), -1))
|
2017-06-28 08:28:24 +01:00
|
|
|
p.cursor.Move2(p.cursorX+p.patternPadding, p.patternPadding)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Palette) showSelected(selected int) {
|
|
|
|
if p.resultType == "file_line" {
|
|
|
|
n := 0
|
|
|
|
for i := 0; i <= selected; i++ {
|
|
|
|
for n++; n < len(p.itemTypes) && p.itemTypes[n] == "file"; n++ {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
selected = n
|
|
|
|
}
|
|
|
|
for i, resultItem := range p.resultItems {
|
|
|
|
resultItem.setSelected(selected == i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PaletteResultItem) update() {
|
|
|
|
if f.selected {
|
|
|
|
f.widget.SetStyleSheet(fmt.Sprintf(".QWidget {background-color: %s;}", editor.selectedBg))
|
|
|
|
} else {
|
|
|
|
f.widget.SetStyleSheet("")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PaletteResultItem) setSelected(selected bool) {
|
|
|
|
if f.selected == selected {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
f.selected = selected
|
|
|
|
f.update()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PaletteResultItem) show() {
|
2017-11-09 01:41:26 +00:00
|
|
|
// if f.hidden {
|
|
|
|
f.hidden = false
|
|
|
|
f.widget.Show()
|
|
|
|
// }
|
2017-06-28 08:28:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PaletteResultItem) hide() {
|
|
|
|
if !f.hidden {
|
|
|
|
f.hidden = true
|
|
|
|
f.widget.Hide()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PaletteResultItem) setItem(text string, itemType string, match []int) {
|
|
|
|
iconType := ""
|
|
|
|
path := false
|
|
|
|
if itemType == "dir" {
|
|
|
|
iconType = "folder"
|
|
|
|
path = true
|
|
|
|
} else if itemType == "file" {
|
|
|
|
iconType = getFileType(text)
|
|
|
|
path = true
|
|
|
|
} else if itemType == "file_line" {
|
|
|
|
iconType = "empty"
|
|
|
|
}
|
|
|
|
if iconType != "" {
|
|
|
|
if iconType != f.iconType {
|
|
|
|
f.iconType = iconType
|
|
|
|
f.updateIcon()
|
|
|
|
}
|
|
|
|
f.showIcon()
|
|
|
|
} else {
|
|
|
|
f.hideIcon()
|
|
|
|
}
|
|
|
|
|
|
|
|
formattedText := formatText(text, match, path)
|
|
|
|
if formattedText != f.baseText {
|
|
|
|
f.baseText = formattedText
|
|
|
|
f.base.SetText(f.baseText)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PaletteResultItem) updateIcon() {
|
2018-10-13 23:14:34 +09:00
|
|
|
svgContent := editor.getSvg(f.iconType, nil)
|
2017-06-28 08:28:24 +01:00
|
|
|
f.icon.Load2(core.NewQByteArray2(svgContent, len(svgContent)))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PaletteResultItem) showIcon() {
|
|
|
|
if f.iconHidden {
|
|
|
|
f.iconHidden = false
|
|
|
|
f.icon.Show()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (f *PaletteResultItem) hideIcon() {
|
|
|
|
if !f.iconHidden {
|
|
|
|
f.iconHidden = true
|
|
|
|
f.icon.Hide()
|
|
|
|
}
|
|
|
|
}
|