akiyosi.goneovim/editor/palette.go

335 lines
8.4 KiB
Go
Raw Normal View History

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"
"sync"
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-09-02 15:55:24 +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)
shadow.SetBlurRadius(20)
shadow.SetColor(gui.NewQColor3(0, 0, 0, 255))
shadow.SetOffset3(0, 2)
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)
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)
resultMainWidget.SetContentsMargins(0, 0, 0, 0)
resultMainLayout.AddWidget(resultWidget, 0, 0)
resultMainLayout.AddWidget(scrollCol, 0, 0)
resultMainWidget.SetLayout(resultMainLayout)
pattern := widgets.NewQLabel(nil, 0)
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)
icon.SetFixedWidth(14)
icon.SetFixedHeight(14)
icon.SetContentsMargins(0, 0, 0, 0)
base := widgets.NewQLabel(nil, 0)
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-09-02 15:55:24 +09:00
if p.procCount > 0 {
return
2018-01-11 06:11:34 +00:00
}
2018-09-02 15:55:24 +09:00
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
}
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)
return
}
}
2017-06-28 08:28:24 +01:00
2018-09-02 15:55:24 +09:00
p.pattern.SetFixedWidth(p.width - padding*2)
p.widget.SetMaximumWidth(p.width)
p.widget.SetMinimumWidth(p.width)
x := editor.width - p.width
if x < 0 {
x = 0
}
p.widget.Move2(x/2, 0)
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])))
p.cursorX = int(p.ws.font.defaultFontMetrics.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-01-05 08:07:29 +00:00
svgContent := f.p.ws.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()
}
}