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  }