github.com/jmigpin/editor@v1.6.0/util/drawutil/drawer4/annotations.go (about) 1 package drawer4 2 3 import ( 4 "github.com/jmigpin/editor/util/fontutil" 5 "github.com/jmigpin/editor/util/mathutil" 6 ) 7 8 type Annotations struct { 9 d *Drawer 10 notesFFace *fontutil.FontFace 11 } 12 13 func (ann *Annotations) Init() { 14 size2 := ann.d.st.runeR.fface.Size * 0.70 15 ann.notesFFace = ann.d.st.runeR.fface.Font.FontFace2(size2) 16 } 17 18 func (ann *Annotations) Iter() { 19 if ann.d.Opt.Annotations.On { 20 if ann.d.iters.runeR.isNormal() { 21 ann.iter2() 22 } 23 } 24 if !ann.d.iterNext() { 25 return 26 } 27 } 28 29 func (ann *Annotations) iter2() { 30 entries := ann.d.Opt.Annotations.Entries // *mostly* ordered by offset 31 i := &ann.d.st.annotations.cei 32 q := &ann.d.st.annotations.indexQ 33 // add annotations up to the first entry offset, only need to check next entries with offsets smaller then the first entry (ex: function literals with inner annotations that have higher entry index, but lower offsets). 34 var first *Annotation 35 for k := *i; k < len(entries); k++ { 36 e := entries[k] 37 if e == nil { 38 continue 39 } 40 // past annotation 41 if e.Offset < ann.d.st.runeR.ri { 42 continue 43 } 44 45 if first == nil { 46 first = e 47 } 48 49 // annotation match 50 if e.Offset == ann.d.st.runeR.ri { 51 *q = append(*q, k) 52 if k == *i { // handled next entry 53 *i++ 54 first = nil 55 continue 56 } 57 } 58 59 // future annotation 60 // Commented: need to handle next entries with earlier offsets 61 //if e.Offset > ann.d.st.runeR.ri { 62 //break 63 //} 64 // future annotation after the first entry 65 if e.Offset > first.Offset { 66 break 67 } 68 } 69 70 // add annotations after newline 71 if len(*q) > 0 { 72 switch ann.d.st.runeR.ru { 73 case '\n', 0: // insert annotations at newline or EOF 74 ann.insertAnnotations() 75 } 76 } 77 } 78 79 func (ann *Annotations) End() {} 80 81 //---------- 82 83 func (ann *Annotations) insertAnnotations() { 84 tmp := ann.d.st.runeR // keep state 85 defer func() { ann.d.st.runeR = tmp }() // restore state 86 ann.insertAnnotations2() 87 } 88 89 func (ann *Annotations) insertAnnotations2() { 90 // clear at the end 91 defer func() { ann.d.st.annotations.indexQ = []int{} }() 92 93 // separator between content and annotation 94 { 95 pen := &ann.d.st.runeR.pen 96 startX := pen.X + ann.d.st.runeR.advance 97 98 //if !ann.insertSeparatorString("\t") { 99 // return 100 //} 101 102 space := ann.d.iters.runeR.glyphAdvance(' ') 103 boundsMinX := mathutil.Intf1(ann.d.bounds.Min.X) 104 min := boundsMinX + space*(8*10) 105 margin := space * 10 106 max := ann.d.iters.runeR.maxX() - margin 107 if pen.X < min { 108 pen.X = min 109 } 110 if pen.X > max { 111 pen.X = max 112 } 113 if pen.X < startX { 114 pen.X = startX 115 } 116 } 117 118 // annotations 119 c := 0 120 for _, index := range ann.d.st.annotations.indexQ { 121 entry := ann.d.Opt.Annotations.Entries[index] 122 if entry == nil { 123 continue 124 } 125 126 // space separator between entries on the same line 127 c++ 128 if c >= 2 { 129 if !ann.insertSeparatorString(" ") { 130 return 131 } 132 } 133 134 s1 := string(entry.Bytes) 135 if !ann.insertAnnotationString(s1, index, true) { 136 return 137 } 138 139 // entry.notes (used for arrival index) 140 s2 := string(entry.NotesBytes) 141 if !ann.insertNotesString(ann.notesFFace, s2) { 142 return 143 } 144 } 145 } 146 147 func (ann *Annotations) insertAnnotationString(s string, eindex int, colorizeIfIndex bool) bool { 148 // keep/restore color state 149 keep := ann.d.st.curColors 150 defer func() { ann.d.st.curColors = keep }() 151 // set colors 152 opt := &ann.d.Opt.Annotations 153 if colorizeIfIndex && eindex == opt.Selected.EntryIndex { 154 assignColor(&ann.d.st.curColors.fg, opt.Selected.Fg) 155 assignColor(&ann.d.st.curColors.bg, opt.Selected.Bg) 156 } else { 157 assignColor(&ann.d.st.curColors.fg, opt.Fg) 158 assignColor(&ann.d.st.curColors.bg, opt.Bg) 159 } 160 161 // update annotationsindexof state 162 ann.d.st.annotationsIndexOf.inside.on = true 163 ann.d.st.annotationsIndexOf.inside.ei = eindex 164 ann.d.st.annotationsIndexOf.inside.soffset = ann.d.st.runeR.ri 165 defer func() { ann.d.st.annotationsIndexOf.inside.on = false }() 166 167 return ann.d.iters.runeR.insertExtraString(s) 168 } 169 170 func (ann *Annotations) insertNotesString(fface *fontutil.FontFace, s string) bool { 171 // keep/restore color state 172 keep := ann.d.st.curColors 173 defer func() { ann.d.st.curColors = keep }() 174 // set colors 175 ann.d.st.curColors.fg = ann.d.fg 176 ann.d.st.curColors.bg = nil 177 178 // keep/restore face 179 keepf := ann.d.st.runeR.fface 180 ann.d.st.runeR.fface = fface 181 defer func() { ann.d.st.runeR.fface = keepf }() 182 183 return ann.d.iters.runeR.insertExtraString(" " + s) 184 } 185 186 func (ann *Annotations) insertSeparatorString(s string) bool { 187 // keep/restore color state 188 keep := ann.d.st.curColors 189 defer func() { ann.d.st.curColors = keep }() 190 // set colors 191 ann.d.st.curColors.fg = ann.d.fg 192 ann.d.st.curColors.bg = nil 193 return ann.d.iters.runeR.insertExtraString(s) 194 } 195 196 //---------- 197 198 type Annotation struct { 199 Offset int 200 Bytes []byte 201 NotesBytes []byte // used for arrival index 202 } 203 204 //---------- 205 206 type AnnotationsIndexOf struct { 207 d *Drawer 208 } 209 210 func (aio *AnnotationsIndexOf) Init() { 211 aio.d.st.annotationsIndexOf.eindex = -1 212 } 213 214 func (aio *AnnotationsIndexOf) Iter() { 215 if aio.d.st.annotationsIndexOf.inside.on { 216 aio.iter2() 217 } 218 _ = aio.d.iterNext() 219 } 220 221 func (aio *AnnotationsIndexOf) End() {} 222 223 //---------- 224 225 func (aio *AnnotationsIndexOf) iter2() { 226 p := &aio.d.st.annotationsIndexOf.p 227 pb := aio.d.iters.runeR.penBounds() 228 229 // before the y start 230 if p.Y < pb.Min.Y { 231 aio.d.iterStop() 232 return 233 } 234 // in the line 235 if p.Y < pb.Max.Y { 236 // before the x start 237 if p.X < pb.Min.X { 238 aio.d.iterStop() 239 return 240 } 241 // inside 242 if p.X < pb.Max.X { 243 st := &aio.d.st.annotationsIndexOf 244 st.eindex = st.inside.ei 245 st.offset = aio.d.st.runeR.ri - st.inside.soffset 246 aio.d.iterStop() 247 return 248 } 249 } 250 }