9fans.net/go@v0.0.7/cmd/samterm/scroll.go (about) 1 package main 2 3 import ( 4 "image" 5 6 "9fans.net/go/draw" 7 "9fans.net/go/draw/frame" 8 ) 9 10 var scrtmp *draw.Image 11 var scrback *draw.Image 12 13 func scrtemps() { 14 if scrtmp != nil { 15 return 16 } 17 var h int 18 if !screensize(nil, &h) { 19 h = 2048 20 } 21 scrtmp, _ = display.AllocImage(image.Rect(0, 0, 32, h), screen.Pix, false, 0) 22 scrback, _ = display.AllocImage(image.Rect(0, 0, 32, h), screen.Pix, false, 0) 23 if scrtmp == nil || scrback == nil { 24 panic("scrtemps") 25 } 26 } 27 28 func scrpos(r image.Rectangle, p0 int, p1 int, tot int) image.Rectangle { 29 q := r 30 h := q.Max.Y - q.Min.Y 31 if tot == 0 { 32 return q 33 } 34 if tot > 1024*1024 { 35 tot >>= 10 36 p0 >>= 10 37 p1 >>= 10 38 } 39 if p0 > 0 { 40 q.Min.Y += h * p0 / tot 41 } 42 if p1 < tot { 43 q.Max.Y -= h * (tot - p1) / tot 44 } 45 if q.Max.Y < q.Min.Y+2 { 46 if q.Min.Y+2 <= r.Max.Y { 47 q.Max.Y = q.Min.Y + 2 48 } else { 49 q.Min.Y = q.Max.Y - 2 50 } 51 } 52 return q 53 } 54 55 func scrmark(l *Flayer, r image.Rectangle) { 56 r.Max.X-- 57 if draw.RectClip(&r, l.scroll) { 58 l.f.B.Draw(r, l.f.Cols[frame.HIGH], nil, draw.ZP) 59 } 60 } 61 62 func scrunmark(l *Flayer, r image.Rectangle) { 63 if draw.RectClip(&r, l.scroll) { 64 l.f.B.Draw(r, scrback, nil, image.Pt(0, r.Min.Y-l.scroll.Min.Y)) 65 } 66 } 67 68 func scrdraw(l *Flayer, tot int) { 69 scrtemps() 70 if l.f.B == nil { 71 panic("scrdraw") 72 } 73 r := l.scroll 74 r1 := r 75 var b *draw.Image 76 if l.visible == All { 77 b = scrtmp 78 r1.Min.X = 0 79 r1.Max.X = r.Dx() 80 } else { 81 b = l.f.B 82 } 83 r2 := scrpos(r1, l.origin, l.origin+l.f.NumChars, tot) 84 if r2 != l.lastsr { 85 l.lastsr = r2 86 b.Draw(r1, l.f.Cols[frame.BORD], nil, draw.ZP) 87 b.Draw(r2, l.f.Cols[frame.BACK], nil, r2.Min) 88 r2 = r1 89 r2.Min.X = r2.Max.X - 1 90 b.Draw(r2, l.f.Cols[frame.BORD], nil, draw.ZP) 91 if b != l.f.B { 92 l.f.B.Draw(r, b, nil, r1.Min) 93 } 94 } 95 } 96 97 func abs(x int) int { 98 if x < 0 { 99 return -x 100 } 101 return x 102 } 103 104 func scroll(l *Flayer, but int) { 105 in := false 106 tot := scrtotal(l) 107 s := l.scroll 108 x := s.Min.X + FLSCROLLWID(l)/2 109 scr := scrpos(l.scroll, l.origin, l.origin+l.f.NumChars, tot) 110 r := scr 111 y := scr.Min.Y 112 my := mousep.Point.Y 113 scrback.Draw(image.Rect(0, 0, l.scroll.Dx(), l.scroll.Dy()), l.f.B, nil, l.scroll.Min) 114 var p0 int 115 for { 116 oin := in 117 in = abs(x-mousep.Point.X) <= FLSCROLLWID(l)/2 118 if oin && !in { 119 scrunmark(l, r) 120 } 121 if in { 122 scrmark(l, r) 123 oy := y 124 my = mousep.Point.Y 125 if my < s.Min.Y { 126 my = s.Min.Y 127 } 128 if my >= s.Max.Y { 129 my = s.Max.Y 130 } 131 if mousep.Point != image.Pt(x, my) { 132 display.MoveCursor(image.Pt(x, my)) 133 } 134 if but == 1 { 135 p0 = l.origin - l.f.CharOf(image.Pt(s.Max.X, my)) 136 rt := scrpos(l.scroll, p0, p0+l.f.NumChars, tot) 137 y = rt.Min.Y 138 } else if but == 2 { 139 y = my 140 if y > s.Max.Y-2 { 141 y = s.Max.Y - 2 142 } 143 } else if but == 3 { 144 p0 = l.origin + l.f.CharOf(image.Pt(s.Max.X, my)) 145 rt := scrpos(l.scroll, p0, p0+l.f.NumChars, tot) 146 y = rt.Min.Y 147 } 148 if y != oy { 149 scrunmark(l, r) 150 r = scr.Add(image.Pt(0, y-scr.Min.Y)) 151 scrmark(l, r) 152 } 153 } 154 if button(but) == 0 { 155 break 156 } 157 } 158 if in { 159 h := s.Max.Y - s.Min.Y 160 scrunmark(l, r) 161 p0 = 0 162 if but == 1 { 163 p0 = int(my-s.Min.Y)/l.f.Font.Height + 1 164 } else if but == 2 { 165 if tot > 1024*1024 { 166 p0 = ((tot >> 10) * (y - s.Min.Y) / h) << 10 167 } else { 168 p0 = tot * (y - s.Min.Y) / h 169 } 170 } else if but == 3 { 171 p0 = l.origin + l.f.CharOf(image.Pt(s.Max.X, my)) 172 if p0 > tot { 173 p0 = tot 174 } 175 } 176 scrorigin(l, but, p0) 177 } 178 }