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 }