Skip to content

Commit 2ae1999

Browse files
committed
Support visual selections with rounded corners
1 parent ec5f11b commit 2ae1999

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
@@ -62,6 +62,12 @@ type HlDecoration struct {
6262
strikethrough bool
6363
}
6464

65+
type VSelection struct {
66+
highlight *Highlight
67+
start int
68+
end int
69+
}
70+
6571
// Cell is
6672
type Cell struct {
6773
highlight *Highlight
@@ -247,11 +253,15 @@ func (w *Window) paint(event *gui.QPaintEvent) {
247253
}
248254

249255
// Draw contents
256+
var vsSlice []*VSelection
257+
// for y := row; y < row+rows; y++ {
258+
for y := row; y < w.rows; y++ {
259+
vsSlice = w.drawBackground(p, y, col, cols, vsSlice)
260+
}
250261
for y := row; y < row+rows; y++ {
251262
if y >= w.rows {
252263
continue
253264
}
254-
w.drawBackground(p, y, col, cols)
255265
w.drawForeground(p, y, col, cols)
256266
}
257267

@@ -1575,6 +1585,11 @@ func (w *Window) update() {
15751585
end = w.rows
15761586
}
15771587

1588+
if editor.config.Editor.RoundedSelection {
1589+
start = 0
1590+
end = w.rows
1591+
}
1592+
15781593
for i := start; i < end; i++ {
15791594

15801595
if len(w.content) <= i {
@@ -1590,6 +1605,11 @@ func (w *Window) update() {
15901605

15911606
drawWithSingleRect := false
15921607

1608+
if editor.config.Editor.RoundedSelection && w.grid != 1 && !w.isMsgGrid {
1609+
width = w.maxLenContent
1610+
drawWithSingleRect = true
1611+
}
1612+
15931613
// If DrawIndentGuide is enabled
15941614
if editor.config.Editor.IndentGuide {
15951615
if i < w.rows-1 {
@@ -1732,9 +1752,9 @@ func (w *Window) queueRedraw(x, y, width, height int) {
17321752
w.redrawMutex.Unlock()
17331753
}
17341754

1735-
func (w *Window) drawBackground(p *gui.QPainter, y int, col int, cols int) {
1755+
func (w *Window) drawBackground(p *gui.QPainter, y int, col int, cols int, vsSlice []*VSelection) []*VSelection {
17361756
if y >= len(w.content) {
1737-
return
1757+
return vsSlice
17381758
}
17391759

17401760
line := w.content[y]
@@ -1812,9 +1832,11 @@ func (w *Window) drawBackground(p *gui.QPainter, y int, col int, cols int) {
18121832
// }
18131833

18141834
// The same color combines the rectangular areas and paints at once
1835+
18151836
var start, end int
18161837
var lastBg *RGBA
18171838
var lastHighlight, highlight *Highlight
1839+
var vss []*VSelection
18181840

18191841
for x := col; x <= col+cols; x++ {
18201842

@@ -1856,22 +1878,49 @@ func (w *Window) drawBackground(p *gui.QPainter, y int, col int, cols int) {
18561878
end = x
18571879
}
18581880
if !lastBg.equals(bg) || x == bounds {
1859-
w.fillCellRect(p, lastHighlight, lastBg, y, start, end, horScrollPixels, verScrollPixels, isDrawDefaultBg)
1881+
1882+
w.fillCellRect(p, lastHighlight, lastBg, y, start, end, horScrollPixels, verScrollPixels, isDrawDefaultBg, vsSlice)
1883+
width := end - start + 1
1884+
if !isDrawDefaultBg && lastBg.equals(w.background) {
1885+
width = 0
1886+
}
1887+
if width > 0 {
1888+
vss = append(vss, &VSelection{
1889+
highlight: lastHighlight,
1890+
start: start,
1891+
end: end,
1892+
})
1893+
}
18601894

18611895
start = x
18621896
end = x
18631897
lastBg = bg
18641898
lastHighlight = highlight
18651899

18661900
if x == bounds {
1867-
w.fillCellRect(p, lastHighlight, lastBg, y, start, end, horScrollPixels, verScrollPixels, isDrawDefaultBg)
1901+
1902+
w.fillCellRect(p, lastHighlight, lastBg, y, start, end, horScrollPixels, verScrollPixels, isDrawDefaultBg, vsSlice)
1903+
width := end - start + 1
1904+
if !isDrawDefaultBg && lastBg.equals(w.background) {
1905+
width = 0
1906+
}
1907+
if width > 0 {
1908+
vss = append(vss, &VSelection{
1909+
highlight: lastHighlight,
1910+
start: start,
1911+
end: end,
1912+
})
1913+
}
1914+
18681915
}
18691916
}
18701917
}
18711918
}
1919+
1920+
return vss
18721921
}
18731922

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

18761925
if lastHighlight == nil {
18771926
return
@@ -1894,15 +1943,50 @@ func (w *Window) fillCellRect(p *gui.QPainter, lastHighlight *Highlight, lastBg
18941943
// Set diff pattern
18951944
pattern, color, transparent := w.getFillpatternAndTransparent(lastHighlight)
18961945

1897-
// Fill background with pattern
1898-
rectF := core.NewQRectF4(
1899-
float64(start)*font.cellwidth+float64(horScrollPixels),
1900-
float64((y)*font.lineHeight+verScrollPixels),
1901-
float64(width)*font.cellwidth,
1902-
float64(font.lineHeight),
1946+
if !(editor.config.Editor.RoundedSelection && w.grid != 1 && !w.isMsgGrid) {
1947+
// Fill background with pattern
1948+
rectF := core.NewQRectF4(
1949+
float64(start)*font.cellwidth+float64(horScrollPixels),
1950+
float64((y)*font.lineHeight+verScrollPixels),
1951+
float64(width)*font.cellwidth,
1952+
float64(font.lineHeight),
1953+
)
1954+
p.FillRect(
1955+
rectF,
1956+
gui.NewQBrush3(
1957+
gui.NewQColor3(
1958+
color.R,
1959+
color.G,
1960+
color.B,
1961+
transparent,
1962+
),
1963+
pattern,
1964+
),
1965+
)
1966+
1967+
return
1968+
}
1969+
1970+
// ---------------------
1971+
// Apply rounded corners
1972+
// ---------------------
1973+
1974+
path := gui.NewQPainterPath()
1975+
path.AddRoundedRect(
1976+
core.NewQRectF4(
1977+
float64(start)*font.cellwidth+float64(horScrollPixels),
1978+
float64((y)*font.lineHeight+verScrollPixels),
1979+
float64(width)*font.cellwidth,
1980+
float64(font.lineHeight),
1981+
),
1982+
font.cellwidth/2.0,
1983+
font.cellwidth/2.0,
1984+
core.Qt__AbsoluteSize,
19031985
)
1904-
p.FillRect(
1905-
rectF,
1986+
1987+
p.SetPen2(color.QColor())
1988+
p.FillPath(
1989+
path,
19061990
gui.NewQBrush3(
19071991
gui.NewQColor3(
19081992
color.R,
@@ -1913,9 +1997,125 @@ func (w *Window) fillCellRect(p *gui.QPainter, lastHighlight *Highlight, lastBg
19131997
pattern,
19141998
),
19151999
)
2000+
2001+
for _, vs := range vsSlice {
2002+
if !vs.highlight.bg().equals(color) {
2003+
continue
2004+
}
2005+
2006+
if start < vs.start && end >= vs.start {
2007+
w.drawRoundedCorner("rightbottom", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2008+
}
2009+
if end > vs.end && start <= vs.end {
2010+
w.drawRoundedCorner("leftbottom", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2011+
}
2012+
2013+
if vs.start < start && vs.end >= start {
2014+
w.drawRoundedCorner("topright", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2015+
}
2016+
if vs.end > end && vs.start <= end {
2017+
w.drawRoundedCorner("topleft", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2018+
}
2019+
2020+
if vs.start == start {
2021+
w.drawRoundedCorner("leftside", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2022+
}
2023+
if vs.end == end {
2024+
w.drawRoundedCorner("rightside", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2025+
}
2026+
2027+
}
2028+
19162029
}
19172030
}
19182031

2032+
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) {
2033+
font := w.getFont()
2034+
2035+
var a [2]float64
2036+
var b [2]int
2037+
switch pStr {
2038+
case "rightbottom":
2039+
a[0] = float64(vs.start) - 0.5
2040+
a[1] = -0.5
2041+
b[0] = vs.start - 1
2042+
b[1] = -1
2043+
case "leftbottom":
2044+
a[0] = float64(vs.end+1) - 0.5
2045+
a[1] = -0.5
2046+
b[0] = vs.end + 1
2047+
b[1] = -1
2048+
case "topright":
2049+
a[0] = float64(start) - 0.5
2050+
a[1] = 0
2051+
b[0] = start - 1
2052+
b[1] = 0
2053+
case "topleft":
2054+
a[0] = float64(end+1) - 0.5
2055+
a[1] = 0
2056+
b[0] = end + 1
2057+
b[1] = 0
2058+
case "rightside":
2059+
a[0] = float64(end)
2060+
a[1] = -0.25
2061+
b[0] = 0
2062+
b[1] = 0
2063+
case "leftside":
2064+
a[0] = float64(start)
2065+
a[1] = -0.25
2066+
b[0] = 0
2067+
b[1] = 0
2068+
}
2069+
2070+
rect := core.NewQRectF4(
2071+
a[0]*font.cellwidth+float64(horScrollPixels),
2072+
(float64(y)+a[1])*float64(font.lineHeight)+float64(verScrollPixels),
2073+
float64(1.0)*font.cellwidth,
2074+
float64(font.lineHeight)*0.5,
2075+
)
2076+
p.FillRect(
2077+
rect,
2078+
gui.NewQBrush3(
2079+
gui.NewQColor3(
2080+
vs.highlight.bg().R,
2081+
vs.highlight.bg().G,
2082+
vs.highlight.bg().B,
2083+
transparent,
2084+
),
2085+
pattern,
2086+
),
2087+
)
2088+
2089+
if pStr == "leftside" || pStr == "rightside" {
2090+
return
2091+
}
2092+
2093+
path := gui.NewQPainterPath()
2094+
path.AddRoundedRect(
2095+
core.NewQRectF4(
2096+
float64(b[0])*font.cellwidth+float64(horScrollPixels),
2097+
float64((y+b[1])*font.lineHeight+verScrollPixels),
2098+
float64(1)*font.cellwidth,
2099+
float64(font.lineHeight),
2100+
),
2101+
font.cellwidth/2.0,
2102+
font.cellwidth/2.0,
2103+
core.Qt__AbsoluteSize,
2104+
)
2105+
p.FillPath(
2106+
path,
2107+
gui.NewQBrush3(
2108+
gui.NewQColor3(
2109+
w.background.R,
2110+
w.background.G,
2111+
w.background.B,
2112+
transparent,
2113+
),
2114+
pattern,
2115+
),
2116+
)
2117+
}
2118+
19192119
func (w *Window) drawText(p *gui.QPainter, y int, col int, cols int) {
19202120
if y >= len(w.content) {
19212121
return

0 commit comments

Comments
 (0)