Skip to content

Commit e242caf

Browse files
committed
Support visual selections with rounded corners
1 parent e83508f commit e242caf

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
@@ -260,11 +266,15 @@ func (w *Window) paint(event *gui.QPaintEvent) {
260266
}
261267

262268
// Draw contents
269+
var vsSlice []*VSelection
270+
// for y := row; y < row+rows; y++ {
271+
for y := row; y < w.rows; y++ {
272+
vsSlice = w.drawBackground(p, y, col, cols, vsSlice)
273+
}
263274
for y := row; y < row+rows; y++ {
264275
if y >= w.rows {
265276
continue
266277
}
267-
w.drawBackground(p, y, col, cols)
268278
w.drawForeground(p, y, col, cols)
269279
}
270280

@@ -1568,6 +1578,11 @@ func (w *Window) update() {
15681578
end = w.rows
15691579
}
15701580

1581+
if editor.config.Editor.RoundedSelection && w.grid != 1 && !w.isMsgGrid {
1582+
start = 0
1583+
end = w.rows
1584+
}
1585+
15711586
for i := start; i < end; i++ {
15721587

15731588
if len(w.content) <= i {
@@ -1583,6 +1598,11 @@ func (w *Window) update() {
15831598

15841599
drawWithSingleRect := false
15851600

1601+
if editor.config.Editor.RoundedSelection && w.grid != 1 && !w.isMsgGrid {
1602+
width = w.maxLenContent
1603+
drawWithSingleRect = true
1604+
}
1605+
15861606
// If DrawIndentGuide is enabled
15871607
if editor.config.Editor.IndentGuide {
15881608
if i < w.rows-1 {
@@ -1725,9 +1745,9 @@ func (w *Window) queueRedraw(x, y, width, height int) {
17251745
w.redrawMutex.Unlock()
17261746
}
17271747

1728-
func (w *Window) drawBackground(p *gui.QPainter, y int, col int, cols int) {
1748+
func (w *Window) drawBackground(p *gui.QPainter, y int, col int, cols int, vsSlice []*VSelection) []*VSelection {
17291749
if y >= len(w.content) {
1730-
return
1750+
return vsSlice
17311751
}
17321752

17331753
line := w.content[y]
@@ -1805,9 +1825,11 @@ func (w *Window) drawBackground(p *gui.QPainter, y int, col int, cols int) {
18051825
// }
18061826

18071827
// The same color combines the rectangular areas and paints at once
1828+
18081829
var start, end int
18091830
var lastBg *RGBA
18101831
var lastHighlight, highlight *Highlight
1832+
var vss []*VSelection
18111833

18121834
for x := col; x <= col+cols; x++ {
18131835

@@ -1849,22 +1871,49 @@ func (w *Window) drawBackground(p *gui.QPainter, y int, col int, cols int) {
18491871
end = x
18501872
}
18511873
if !lastBg.equals(bg) || x == bounds {
1852-
w.fillCellRect(p, lastHighlight, lastBg, y, start, end, horScrollPixels, verScrollPixels, isDrawDefaultBg)
1874+
1875+
w.fillCellRect(p, lastHighlight, lastBg, y, start, end, horScrollPixels, verScrollPixels, isDrawDefaultBg, vsSlice)
1876+
width := end - start + 1
1877+
if !isDrawDefaultBg && lastBg.equals(w.background) {
1878+
width = 0
1879+
}
1880+
if width > 0 {
1881+
vss = append(vss, &VSelection{
1882+
highlight: lastHighlight,
1883+
start: start,
1884+
end: end,
1885+
})
1886+
}
18531887

18541888
start = x
18551889
end = x
18561890
lastBg = bg
18571891
lastHighlight = highlight
18581892

18591893
if x == bounds {
1860-
w.fillCellRect(p, lastHighlight, lastBg, y, start, end, horScrollPixels, verScrollPixels, isDrawDefaultBg)
1894+
1895+
w.fillCellRect(p, lastHighlight, lastBg, y, start, end, horScrollPixels, verScrollPixels, isDrawDefaultBg, vsSlice)
1896+
width := end - start + 1
1897+
if !isDrawDefaultBg && lastBg.equals(w.background) {
1898+
width = 0
1899+
}
1900+
if width > 0 {
1901+
vss = append(vss, &VSelection{
1902+
highlight: lastHighlight,
1903+
start: start,
1904+
end: end,
1905+
})
1906+
}
1907+
18611908
}
18621909
}
18631910
}
18641911
}
1912+
1913+
return vss
18651914
}
18661915

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

18691918
if lastHighlight == nil {
18701919
return
@@ -1887,15 +1936,50 @@ func (w *Window) fillCellRect(p *gui.QPainter, lastHighlight *Highlight, lastBg
18871936
// Set diff pattern
18881937
pattern, color, transparent := w.getFillpatternAndTransparent(lastHighlight)
18891938

1890-
// Fill background with pattern
1891-
rectF := core.NewQRectF4(
1892-
float64(start)*font.cellwidth+float64(horScrollPixels),
1893-
float64((y)*font.lineHeight+verScrollPixels),
1894-
float64(width)*font.cellwidth,
1895-
float64(font.lineHeight),
1939+
if !(editor.config.Editor.RoundedSelection && w.grid != 1 && !w.isMsgGrid) {
1940+
// Fill background with pattern
1941+
rectF := core.NewQRectF4(
1942+
float64(start)*font.cellwidth+float64(horScrollPixels),
1943+
float64((y)*font.lineHeight+verScrollPixels),
1944+
float64(width)*font.cellwidth,
1945+
float64(font.lineHeight),
1946+
)
1947+
p.FillRect(
1948+
rectF,
1949+
gui.NewQBrush3(
1950+
gui.NewQColor3(
1951+
color.R,
1952+
color.G,
1953+
color.B,
1954+
transparent,
1955+
),
1956+
pattern,
1957+
),
1958+
)
1959+
1960+
return
1961+
}
1962+
1963+
// ---------------------
1964+
// Apply rounded corners
1965+
// ---------------------
1966+
1967+
path := gui.NewQPainterPath()
1968+
path.AddRoundedRect(
1969+
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+
font.cellwidth/2.5,
1976+
font.cellwidth/2.5,
1977+
core.Qt__AbsoluteSize,
18961978
)
1897-
p.FillRect(
1898-
rectF,
1979+
1980+
p.SetPen2(color.QColor())
1981+
p.FillPath(
1982+
path,
18991983
gui.NewQBrush3(
19001984
gui.NewQColor3(
19011985
color.R,
@@ -1906,9 +1990,125 @@ func (w *Window) fillCellRect(p *gui.QPainter, lastHighlight *Highlight, lastBg
19061990
pattern,
19071991
),
19081992
)
1993+
1994+
for _, vs := range vsSlice {
1995+
if !vs.highlight.bg().equals(color) {
1996+
continue
1997+
}
1998+
1999+
if start < vs.start && end >= vs.start {
2000+
w.drawRoundedCorner("rightbottom", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2001+
}
2002+
if end > vs.end && start <= vs.end {
2003+
w.drawRoundedCorner("leftbottom", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2004+
}
2005+
2006+
if vs.start < start && vs.end >= start {
2007+
w.drawRoundedCorner("topright", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2008+
}
2009+
if vs.end > end && vs.start <= end {
2010+
w.drawRoundedCorner("topleft", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2011+
}
2012+
2013+
if vs.start == start {
2014+
w.drawRoundedCorner("leftside", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2015+
}
2016+
if vs.end == end {
2017+
w.drawRoundedCorner("rightside", p, y, pattern, color, transparent, start, end, vs, horScrollPixels, verScrollPixels)
2018+
}
2019+
2020+
}
2021+
19092022
}
19102023
}
19112024

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

0 commit comments

Comments
 (0)