Skip to content

Commit bb7c7bb

Browse files
committed
Support visual selections with rounded corners
1 parent a20cb7a commit bb7c7bb

File tree

2 files changed

+215
-14
lines changed

2 files changed

+215
-14
lines changed

editor/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ type editorConfig struct {
8585
HideTitlebar bool
8686
HideMouseWhenTyping bool
8787
IgnoreSaveConfirmationWithCloseButton bool
88+
RoundedSelection bool
8889
}
8990

9091
type cursorConfig struct {

editor/window.go

Lines changed: 214 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ type HlDecoration struct {
6868
underdashed bool
6969
}
7070

71+
type VSelection struct {
72+
highlight *Highlight
73+
start int
74+
end int
75+
}
76+
7177
// Cell is
7278
type Cell struct {
7379
highlight *Highlight
@@ -253,11 +259,15 @@ func (w *Window) paint(event *gui.QPaintEvent) {
253259
}
254260

255261
// Draw contents
262+
var vsSlice []*VSelection
263+
// for y := row; y < row+rows; y++ {
264+
for y := row; y < w.rows; y++ {
265+
vsSlice = w.drawBackground(p, y, col, cols, vsSlice)
266+
}
256267
for y := row; y < row+rows; y++ {
257268
if y >= w.rows {
258269
continue
259270
}
260-
w.drawBackground(p, y, col, cols)
261271
w.drawForeground(p, y, col, cols)
262272
}
263273

@@ -1596,6 +1606,11 @@ func (w *Window) update() {
15961606
end = w.rows
15971607
}
15981608

1609+
if editor.config.Editor.RoundedSelection && w.grid != 1 && !w.isMsgGrid {
1610+
start = 0
1611+
end = w.rows
1612+
}
1613+
15991614
for i := start; i < end; i++ {
16001615

16011616
if len(w.content) <= i {
@@ -1611,6 +1626,11 @@ func (w *Window) update() {
16111626

16121627
drawWithSingleRect := false
16131628

1629+
if editor.config.Editor.RoundedSelection && w.grid != 1 && !w.isMsgGrid {
1630+
width = w.maxLenContent
1631+
drawWithSingleRect = true
1632+
}
1633+
16141634
// If DrawIndentGuide is enabled
16151635
if editor.config.Editor.IndentGuide {
16161636
if i < w.rows-1 {
@@ -1753,9 +1773,9 @@ func (w *Window) queueRedraw(x, y, width, height int) {
17531773
w.redrawMutex.Unlock()
17541774
}
17551775

1756-
func (w *Window) drawBackground(p *gui.QPainter, y int, col int, cols int) {
1776+
func (w *Window) drawBackground(p *gui.QPainter, y int, col int, cols int, vsSlice []*VSelection) []*VSelection {
17571777
if y >= len(w.content) {
1758-
return
1778+
return vsSlice
17591779
}
17601780

17611781
line := w.content[y]
@@ -1833,9 +1853,11 @@ func (w *Window) drawBackground(p *gui.QPainter, y int, col int, cols int) {
18331853
// }
18341854

18351855
// The same color combines the rectangular areas and paints at once
1856+
18361857
var start, end int
18371858
var lastBg *RGBA
18381859
var lastHighlight, highlight *Highlight
1860+
var vss []*VSelection
18391861

18401862
for x := col; x <= col+cols; x++ {
18411863

@@ -1877,22 +1899,49 @@ func (w *Window) drawBackground(p *gui.QPainter, y int, col int, cols int) {
18771899
end = x
18781900
}
18791901
if !lastBg.equals(bg) || x == bounds {
1880-
w.fillCellRect(p, lastHighlight, lastBg, y, start, end, horScrollPixels, verScrollPixels, isDrawDefaultBg)
1902+
1903+
w.fillCellRect(p, lastHighlight, lastBg, y, start, end, horScrollPixels, verScrollPixels, isDrawDefaultBg, vsSlice)
1904+
width := end - start + 1
1905+
if !isDrawDefaultBg && lastBg.equals(w.background) {
1906+
width = 0
1907+
}
1908+
if width > 0 {
1909+
vss = append(vss, &VSelection{
1910+
highlight: lastHighlight,
1911+
start: start,
1912+
end: end,
1913+
})
1914+
}
18811915

18821916
start = x
18831917
end = x
18841918
lastBg = bg
18851919
lastHighlight = highlight
18861920

18871921
if x == bounds {
1888-
w.fillCellRect(p, lastHighlight, lastBg, y, start, end, horScrollPixels, verScrollPixels, isDrawDefaultBg)
1922+
1923+
w.fillCellRect(p, lastHighlight, lastBg, y, start, end, horScrollPixels, verScrollPixels, isDrawDefaultBg, vsSlice)
1924+
width := end - start + 1
1925+
if !isDrawDefaultBg && lastBg.equals(w.background) {
1926+
width = 0
1927+
}
1928+
if width > 0 {
1929+
vss = append(vss, &VSelection{
1930+
highlight: lastHighlight,
1931+
start: start,
1932+
end: end,
1933+
})
1934+
}
1935+
18891936
}
18901937
}
18911938
}
18921939
}
1940+
1941+
return vss
18931942
}
18941943

1895-
func (w *Window) fillCellRect(p *gui.QPainter, lastHighlight *Highlight, lastBg *RGBA, y, start, end, horScrollPixels, verScrollPixels int, isDrawDefaultBg bool) {
1944+
func (w *Window) fillCellRect(p *gui.QPainter, lastHighlight *Highlight, lastBg *RGBA, y, start, end, horScrollPixels, verScrollPixels int, isDrawDefaultBg bool, vsSlice []*VSelection) {
18961945

18971946
if lastHighlight == nil {
18981947
return
@@ -1915,15 +1964,50 @@ func (w *Window) fillCellRect(p *gui.QPainter, lastHighlight *Highlight, lastBg
19151964
// Set diff pattern
19161965
pattern, color, transparent := w.getFillpatternAndTransparent(lastHighlight)
19171966

1918-
// Fill background with pattern
1919-
rectF := core.NewQRectF4(
1920-
float64(start)*font.cellwidth+float64(horScrollPixels),
1921-
float64((y)*font.lineHeight+verScrollPixels),
1922-
float64(width)*font.cellwidth,
1923-
float64(font.lineHeight),
1967+
if !(editor.config.Editor.RoundedSelection && w.grid != 1 && !w.isMsgGrid) {
1968+
// Fill background with pattern
1969+
rectF := core.NewQRectF4(
1970+
float64(start)*font.cellwidth+float64(horScrollPixels),
1971+
float64((y)*font.lineHeight+verScrollPixels),
1972+
float64(width)*font.cellwidth,
1973+
float64(font.lineHeight),
1974+
)
1975+
p.FillRect(
1976+
rectF,
1977+
gui.NewQBrush3(
1978+
gui.NewQColor3(
1979+
color.R,
1980+
color.G,
1981+
color.B,
1982+
transparent,
1983+
),
1984+
pattern,
1985+
),
1986+
)
1987+
1988+
return
1989+
}
1990+
1991+
// ---------------------
1992+
// Apply rounded corners
1993+
// ---------------------
1994+
1995+
path := gui.NewQPainterPath()
1996+
path.AddRoundedRect(
1997+
core.NewQRectF4(
1998+
float64(start)*font.cellwidth+float64(horScrollPixels),
1999+
float64((y)*font.lineHeight+verScrollPixels),
2000+
float64(width)*font.cellwidth,
2001+
float64(font.lineHeight),
2002+
),
2003+
font.cellwidth/2.5,
2004+
font.cellwidth/2.5,
2005+
core.Qt__AbsoluteSize,
19242006
)
1925-
p.FillRect(
1926-
rectF,
2007+
2008+
p.SetPen2(color.QColor())
2009+
p.FillPath(
2010+
path,
19272011
gui.NewQBrush3(
19282012
gui.NewQColor3(
19292013
color.R,
@@ -1934,9 +2018,125 @@ func (w *Window) fillCellRect(p *gui.QPainter, lastHighlight *Highlight, lastBg
19342018
pattern,
19352019
),
19362020
)
2021+
2022+
for _, vs := range vsSlice {
2023+
if !vs.highlight.bg().equals(color) {
2024+
continue
2025+
}
2026+
2027+
if start < vs.start && end >= vs.start {
2028+
w.drawRoundedCorner("rightbottom", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2029+
}
2030+
if end > vs.end && start <= vs.end {
2031+
w.drawRoundedCorner("leftbottom", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2032+
}
2033+
2034+
if vs.start < start && vs.end >= start {
2035+
w.drawRoundedCorner("topright", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2036+
}
2037+
if vs.end > end && vs.start <= end {
2038+
w.drawRoundedCorner("topleft", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2039+
}
2040+
2041+
if vs.start == start {
2042+
w.drawRoundedCorner("leftside", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2043+
}
2044+
if vs.end == end {
2045+
w.drawRoundedCorner("rightside", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2046+
}
2047+
2048+
}
2049+
19372050
}
19382051
}
19392052

2053+
func (w *Window) drawRoundedCorner(pStr string, p *gui.QPainter, y int, pattern core.Qt__BrushStyle, color *RGBA, transparent, start, end int, vs *VSelection, horScrollPixels, verScrollPixels int) {
2054+
font := w.getFont()
2055+
2056+
var a [2]float64
2057+
var b [2]int
2058+
switch pStr {
2059+
case "rightbottom":
2060+
a[0] = float64(vs.start) - 0.5
2061+
a[1] = -0.5
2062+
b[0] = vs.start - 1
2063+
b[1] = -1
2064+
case "leftbottom":
2065+
a[0] = float64(vs.end+1) - 0.5
2066+
a[1] = -0.5
2067+
b[0] = vs.end + 1
2068+
b[1] = -1
2069+
case "topright":
2070+
a[0] = float64(start) - 0.5
2071+
a[1] = 0
2072+
b[0] = start - 1
2073+
b[1] = 0
2074+
case "topleft":
2075+
a[0] = float64(end+1) - 0.5
2076+
a[1] = 0
2077+
b[0] = end + 1
2078+
b[1] = 0
2079+
case "rightside":
2080+
a[0] = float64(end)
2081+
a[1] = -0.25
2082+
b[0] = 0
2083+
b[1] = 0
2084+
case "leftside":
2085+
a[0] = float64(start)
2086+
a[1] = -0.25
2087+
b[0] = 0
2088+
b[1] = 0
2089+
}
2090+
2091+
rect := core.NewQRectF4(
2092+
a[0]*font.cellwidth+float64(horScrollPixels),
2093+
(float64(y)+a[1])*float64(font.lineHeight)+float64(verScrollPixels),
2094+
float64(1.0)*font.cellwidth,
2095+
float64(font.lineHeight)*0.5,
2096+
)
2097+
p.FillRect(
2098+
rect,
2099+
gui.NewQBrush3(
2100+
gui.NewQColor3(
2101+
vs.highlight.bg().R,
2102+
vs.highlight.bg().G,
2103+
vs.highlight.bg().B,
2104+
transparent,
2105+
),
2106+
pattern,
2107+
),
2108+
)
2109+
2110+
if pStr == "leftside" || pStr == "rightside" {
2111+
return
2112+
}
2113+
2114+
path := gui.NewQPainterPath()
2115+
path.AddRoundedRect(
2116+
core.NewQRectF4(
2117+
float64(b[0])*font.cellwidth+float64(horScrollPixels),
2118+
float64((y+b[1])*font.lineHeight+verScrollPixels),
2119+
float64(1)*font.cellwidth,
2120+
float64(font.lineHeight),
2121+
),
2122+
font.cellwidth/2.5,
2123+
font.cellwidth/2.5,
2124+
core.Qt__AbsoluteSize,
2125+
)
2126+
p.FillPath(
2127+
path,
2128+
gui.NewQBrush3(
2129+
gui.NewQColor3(
2130+
w.background.R,
2131+
w.background.G,
2132+
w.background.B,
2133+
transparent,
2134+
),
2135+
pattern,
2136+
),
2137+
)
2138+
}
2139+
19402140
func (w *Window) drawText(p *gui.QPainter, y int, col int, cols int) {
19412141
if y >= len(w.content) {
19422142
return

0 commit comments

Comments
 (0)