9fans.net/go@v0.0.5/draw/frame/frselect.go (about)

     1  package frame
     2  
     3  import (
     4  	"9fans.net/go/draw"
     5  )
     6  
     7  func region(a, b int) int {
     8  	if a < b {
     9  		return -1
    10  	}
    11  	if a == b {
    12  		return 0
    13  	}
    14  	return +1
    15  }
    16  
    17  // Select tracks the mouse to select a contiguous string of
    18  // text in the Frame.  When called, a mouse button is typically
    19  // down.  Select will return when the button state has
    20  // changed (some buttons may still be down) and will set f.P0
    21  // and f.P1 to the selected range of text.
    22  func (f *Frame) Select(mc *draw.Mousectl) {
    23  	// when called, button 1 is down
    24  
    25  	mp := mc.Point
    26  	b := mc.Buttons
    27  	f.modified = false
    28  	f.Drawsel(f.PointOf(f.P0), f.P0, f.P1, false)
    29  	p0 := f.CharOf(mp)
    30  	p1 := p0
    31  	f.P0 = p0
    32  	f.P1 = p1
    33  	pt0 := f.PointOf(p0)
    34  	pt1 := f.PointOf(p1)
    35  	f.Drawsel(pt0, p0, p1, true)
    36  	reg := 0
    37  	for mc.Buttons == b {
    38  		scrolled := false
    39  		if f.Scroll != nil {
    40  			if mp.Y < f.R.Min.Y {
    41  				f.Scroll(f, -(f.R.Min.Y-mp.Y)/f.Font.Height-1)
    42  				p0 = f.P1
    43  				p1 = f.P0
    44  				scrolled = true
    45  			} else if mp.Y > f.R.Max.Y {
    46  				f.Scroll(f, (mp.Y-f.R.Max.Y)/f.Font.Height+1)
    47  				p0 = f.P0
    48  				p1 = f.P1
    49  				scrolled = true
    50  			}
    51  			if scrolled {
    52  				if reg != region(p1, p0) {
    53  					p0, p1 = p1, p0 // undo the swap that will happen below
    54  				}
    55  				pt0 = f.PointOf(p0)
    56  				pt1 = f.PointOf(p1)
    57  				reg = region(p1, p0)
    58  			}
    59  		}
    60  		if q := f.CharOf(mp); p1 != q {
    61  			if reg != region(q, p0) { // crossed starting point; reset
    62  				if reg > 0 {
    63  					f.Drawsel(pt0, p0, p1, false)
    64  				} else if reg < 0 {
    65  					f.Drawsel(pt1, p1, p0, false)
    66  				}
    67  				p1 = p0
    68  				pt1 = pt0
    69  				reg = region(q, p0)
    70  				if reg == 0 {
    71  					f.Drawsel(pt0, p0, p1, true)
    72  				}
    73  			}
    74  			qt := f.PointOf(q)
    75  			if reg > 0 {
    76  				if q > p1 {
    77  					f.Drawsel(pt1, p1, q, true)
    78  				} else {
    79  					f.Drawsel(qt, q, p1, false)
    80  				}
    81  			} else if reg < 0 {
    82  				if q > p1 {
    83  					f.Drawsel(pt1, p1, q, false)
    84  				} else {
    85  					f.Drawsel(qt, q, p1, true)
    86  				}
    87  			}
    88  			p1 = q
    89  			pt1 = qt
    90  		}
    91  		f.modified = false
    92  		if p0 < p1 {
    93  			f.P0 = p0
    94  			f.P1 = p1
    95  		} else {
    96  			f.P0 = p1
    97  			f.P1 = p0
    98  		}
    99  		if scrolled {
   100  			f.Scroll(f, 0)
   101  		}
   102  		f.Display.Flush()
   103  		if !scrolled {
   104  			mc.Read()
   105  		}
   106  		mp = mc.Point
   107  	}
   108  }
   109  
   110  // SelectPaint uses a solid color, col, to paint a region of the frame
   111  // defined by the points p0 and p1.
   112  func (f *Frame) SelectPaint(p0, p1 draw.Point, col *draw.Image) {
   113  	q0 := p0
   114  	q1 := p1
   115  	q0.Y += f.Font.Height
   116  	q1.Y += f.Font.Height
   117  	n := (p1.Y - p0.Y) / f.Font.Height
   118  	if f.B == nil {
   119  		drawerror(f.Display, "frselectpaint b==0")
   120  	}
   121  	if p0.Y == f.R.Max.Y {
   122  		return
   123  	}
   124  	if n == 0 {
   125  		f.B.Draw(draw.Rectangle{Min: p0, Max: q1}, col, nil, draw.ZP)
   126  	} else {
   127  		if p0.X >= f.R.Max.X {
   128  			p0.X = f.R.Max.X - 1
   129  		}
   130  		f.B.Draw(draw.Rect(p0.X, p0.Y, f.R.Max.X, q0.Y), col, nil, draw.ZP)
   131  		if n > 1 {
   132  			f.B.Draw(draw.Rect(f.R.Min.X, q0.Y, f.R.Max.X, p1.Y), col, nil, draw.ZP)
   133  		}
   134  		f.B.Draw(draw.Rect(f.R.Min.X, p1.Y, q1.X, q1.Y), col, nil, draw.ZP)
   135  	}
   136  }