Beispiel #1
0
func (g *Graph) Draw(self Widget, ctx *nanovgo.Context) {
	g.WidgetImplement.Draw(self, ctx)

	x := float32(g.x)
	y := float32(g.y)
	w := float32(g.w)
	h := float32(g.h)

	ctx.BeginPath()
	ctx.Rect(x, y, w, h)
	ctx.SetFillColor(g.backgroundColor)
	ctx.Fill()

	if len(g.values) < 2 {
		return
	}

	ctx.BeginPath()
	ctx.MoveTo(x, y+h)
	dx := float32(len(g.values) - 1)
	for i, v := range g.values {
		vx := x + float32(i)*w/dx
		vy := y + (1.0-v)*h
		ctx.LineTo(vx, vy)
	}

	ctx.LineTo(x+w, y+h)
	ctx.SetStrokeColor(nanovgo.MONO(100, 255))
	ctx.Stroke()
	ctx.SetFillColor(g.foregroundColor)
	ctx.Fill()

	ctx.SetFontFace(g.theme.FontNormal)
	ctx.SetFillColor(g.textColor)
	if g.caption != "" {
		ctx.SetFontSize(14)
		ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignTop)
		ctx.Text(x+3, y+1, g.caption)
	}

	if g.header != "" {
		ctx.SetFontSize(18)
		ctx.SetTextAlign(nanovgo.AlignRight | nanovgo.AlignTop)
		ctx.Text(x+w-3, y+1, g.header)
	}

	if g.footer != "" {
		ctx.SetFontSize(15)
		ctx.SetTextAlign(nanovgo.AlignRight | nanovgo.AlignBottom)
		ctx.Text(x+w-3, y+h-1, g.footer)
	}

	ctx.BeginPath()
	ctx.Rect(x, y, w, h)
	ctx.SetStrokeColor(nanovgo.MONO(100, 255))
	ctx.Stroke()
}
Beispiel #2
0
func (s *Screen) drawWidgets() {
	if !s.visible {
		return
	}
	s.window.MakeContextCurrent()
	s.fbW, s.fbH = s.window.GetFramebufferSize()
	s.w, s.h = s.window.GetSize()
	gl.Viewport(0, 0, s.fbW, s.fbH)

	s.pixelRatio = float32(s.fbW) / float32(s.w)
	s.context.BeginFrame(s.w, s.h, s.pixelRatio)
	s.Draw(s, s.context)
	elapsed := GetTime() - s.lastInteraction

	if elapsed > 0.5 {
		// Draw tooltips
		widget := s.FindWidget(s, s.mousePosX, s.mousePosY)
		if widget != nil && widget.Tooltip() != "" {
			var tooltipWidth float32 = 150
			ctx := s.context
			ctx.SetFontFace(s.theme.FontNormal)
			ctx.SetFontSize(15.0)
			ctx.SetTextAlign(nanovgo.AlignCenter | nanovgo.AlignTop)
			ctx.SetTextLineHeight(1.1)
			posX, posY := widget.AbsolutePosition()
			posX += widget.Width() / 2
			posY += widget.Height() + 10
			bounds := ctx.TextBoxBounds(float32(posX), float32(posY), tooltipWidth, widget.Tooltip())
			ctx.SetGlobalAlpha(minF(1.0, 2*(elapsed-0.5)) * 0.8)
			ctx.BeginPath()
			ctx.SetFillColor(nanovgo.MONO(0, 255))
			h := (bounds[2] - bounds[0]) / 2
			ctx.RoundedRect(bounds[0]-4-h, bounds[1]-4, bounds[2]-bounds[0]+8, bounds[3]-bounds[1]+8, 3)
			px := (bounds[2]+bounds[0])/2 - h
			ctx.MoveTo(px, bounds[1]-10)
			ctx.LineTo(px+7, bounds[1]+1)
			ctx.LineTo(px-7, bounds[1]+1)
			ctx.Fill()

			ctx.SetFillColor(nanovgo.MONO(255, 255))
			ctx.SetFontBlur(0.0)
			ctx.TextBox(float32(posX)-h, float32(posY), tooltipWidth, widget.Tooltip())

		}
	}

	s.context.EndFrame()
}
Beispiel #3
0
func (i *ImagePanel) Draw(self Widget, ctx *nanovgo.Context) {
	cols, _ := i.gridSize()

	x := float32(i.x)
	y := float32(i.y)
	thumbSize := float32(i.thumbSize)

	for j, image := range i.images {
		pX := x + float32(i.margin+(j%cols)*(i.thumbSize+i.spacing))
		pY := y + float32(i.margin+(j/cols)*(i.thumbSize+i.spacing))

		imgW, imgH, _ := ctx.ImageSize(image.ImageID)
		var iw, ih, ix, iy float32
		if imgW < imgH {
			iw = thumbSize
			ih = iw * float32(imgH) / float32(imgW)
			ix = 0
			iy = -(ih - thumbSize) * 0.5
		} else {
			ih = thumbSize
			iw = ih * float32(imgH) / float32(imgW)
			iy = 0
			ix = -(iw - thumbSize) * 0.5
		}
		imgPaint := nanovgo.ImagePattern(pX+ix, pY+iy, iw, ih, 0, image.ImageID, toF(i.mouseIndex == j, 1.0, 0.7))
		ctx.BeginPath()
		ctx.RoundedRect(pX, pY, thumbSize, thumbSize, 5)
		ctx.SetFillPaint(imgPaint)
		ctx.Fill()

		shadowPaint := nanovgo.BoxGradient(pX-1, pY, thumbSize+2, thumbSize+2, 5, 3, nanovgo.MONO(0, 128), nanovgo.MONO(0, 0))

		ctx.BeginPath()
		ctx.Rect(pX-5, pY-5, thumbSize+10, thumbSize+10)
		ctx.RoundedRect(pX, pY, thumbSize, thumbSize, 6)
		ctx.PathWinding(nanovgo.Hole)
		ctx.SetFillPaint(shadowPaint)
		ctx.Fill()

		ctx.BeginPath()
		ctx.RoundedRect(pX+0.5, pY+0.5, thumbSize-1, thumbSize-1, 4-0.5)
		ctx.SetStrokeWidth(1.0)
		ctx.SetStrokeColor(nanovgo.MONO(255, 80))
		ctx.Stroke()
	}
}
Beispiel #4
0
func NewGraph(parent Widget, captions ...string) *Graph {
	var caption string
	switch len(captions) {
	case 0:
		caption = "Untitled"
	case 1:
		caption = captions[0]
	default:
		panic("NewGraph can accept only one extra parameter (label)")
	}
	graph := &Graph{
		caption:         caption,
		backgroundColor: nanovgo.MONO(20, 128),
		foregroundColor: nanovgo.RGBA(255, 192, 0, 128),
		textColor:       nanovgo.MONO(240, 192),
	}
	InitWidget(graph, parent)
	return graph
}
Beispiel #5
0
func (p *ProgressBar) Draw(self Widget, ctx *nanovgo.Context) {
	px := float32(p.x)
	py := float32(p.y)
	pw := float32(p.w)
	ph := float32(p.h)
	p.WidgetImplement.Draw(self, ctx)
	paint := nanovgo.BoxGradient(px+1, py+1, pw-2, ph, 3, 4, nanovgo.MONO(0, 32), nanovgo.MONO(0, 92))
	ctx.BeginPath()
	ctx.RoundedRect(px, py, pw, ph, 3)
	ctx.SetFillPaint(paint)
	ctx.Fill()

	value := clampF(p.value, 0.0, 1.0)
	barPos := (pw - 2) * value
	barPaint := nanovgo.BoxGradient(px, py, barPos+1.5, ph-1, 3, 4, nanovgo.MONO(220, 100), nanovgo.MONO(128, 100))
	ctx.BeginPath()
	ctx.RoundedRect(px+1, py+1, barPos, ph-2, 3)
	ctx.SetFillPaint(barPaint)
	ctx.Fill()
}
Beispiel #6
0
func (v *VScrollPanel) Draw(self Widget, ctx *nanovgo.Context) {
	if len(v.children) == 0 {
		return
	}
	x := float32(v.x)
	y := float32(v.y)
	w := float32(v.w)
	h := float32(v.h)

	child := v.children[0]
	layout := self.Layout()
	if layout != nil {
		_, v.childPreferredHeight = layout.PreferredSize(self, ctx)
	} else {
		_, v.childPreferredHeight = child.PreferredSize(child, ctx)
	}

	ctx.Save()
	ctx.Translate(x, y)
	ctx.Scissor(0, 0, w, h)
	ctx.Translate(0, -v.scroll*(float32(v.childPreferredHeight)-h))
	if child.Visible() {
		child.Draw(child, ctx)
	}
	ctx.Restore()
	if v.childPreferredHeight > v.h {
		scrollH := h * minF(1.0, h/float32(v.childPreferredHeight))
		scrollH = minF(maxF(20.0, scrollH), h)
		paint := nanovgo.BoxGradient(x+w-12+1, y+4+1, 8, h-8, 3, 4, nanovgo.MONO(0, 32), nanovgo.MONO(0, 92))
		ctx.BeginPath()
		ctx.RoundedRect(x+w-12, y+4, 8, h-8, 3)
		ctx.SetFillPaint(paint)
		ctx.Fill()

		barPaint := nanovgo.BoxGradient(x+y-12-1, y+4+1+(h-8-scrollH)*v.scroll-1, 8, scrollH, 3, 4, nanovgo.MONO(220, 100), nanovgo.MONO(128, 100))
		ctx.BeginPath()
		ctx.RoundedRect(x+w-12+1, y+4+1+(h-8-scrollH)*v.scroll, 8-2, scrollH-2, 2)
		ctx.SetFillPaint(barPaint)
		ctx.Fill()
	}
}
Beispiel #7
0
func (c *CheckBox) Draw(self Widget, ctx *nanovgo.Context) {
	cx := float32(c.x)
	cy := float32(c.y)
	ch := float32(c.h)
	c.WidgetImplement.Draw(self, ctx)
	fontSize := float32(c.FontSize())
	ctx.SetFontSize(fontSize)
	ctx.SetFontFace(c.theme.FontNormal)
	if c.enabled {
		ctx.SetFillColor(c.theme.TextColor)
	} else {
		ctx.SetFillColor(c.theme.DisabledTextColor)
	}
	ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignMiddle)
	ctx.Text(cx+1.2*ch+5, cy+ch*0.5, c.caption)
	var bgAlpha uint8
	if c.pushed {
		bgAlpha = 100
	} else {
		bgAlpha = 32
	}
	bgPaint := nanovgo.BoxGradient(cx+1.5, cy+1.5, ch-2.0, ch-2.0, 3, 3, nanovgo.MONO(0, bgAlpha), nanovgo.MONO(0, 180))
	ctx.BeginPath()
	ctx.RoundedRect(cx+1.0, cy+1.0, ch-2.0, ch-2.0, 3)
	ctx.SetFillPaint(bgPaint)
	ctx.Fill()

	if c.checked {
		ctx.SetFontSize(ch)
		ctx.SetFontFace(c.theme.FontIcons)
		if c.enabled {
			ctx.SetFillColor(c.theme.IconColor)
		} else {
			ctx.SetFillColor(c.theme.DisabledTextColor)
		}
		ctx.SetTextAlign(nanovgo.AlignCenter | nanovgo.AlignMiddle)
		ctx.Text(cx+ch*0.5+1.0, cy+ch*0.5, string([]rune{rune(IconCheck)}))
	}
}
Beispiel #8
0
func (c *ColorWheel) Draw(self Widget, ctx *nanovgo.Context) {
	c.WidgetImplement.Draw(self, ctx)

	if !c.visible {
		return
	}
	x := float32(c.x)
	y := float32(c.y)
	w := float32(c.w)
	h := float32(c.h)

	ctx.Save()
	defer ctx.Restore()

	cx := x + w*0.5
	cy := y + h*0.5
	r1 := toF(w < h, w, h)*0.5 - 5.0
	r0 := r1 * 0.75

	aeps := 0.7 / r1 // half a pixel arc length in radians (2pi cancels out).
	for i := 0; i < 6; i++ {
		a0 := float32(i)/6.0*nanovgo.PI*2.0 - aeps
		a1 := float32(i+1)/6.0*nanovgo.PI*2.0 + aeps
		ctx.BeginPath()
		ctx.Arc(cx, cy, r0, a0, a1, nanovgo.Clockwise)
		ctx.Arc(cx, cy, r1, a1, a0, nanovgo.CounterClockwise)
		ctx.ClosePath()

		sin1, cos1 := sinCosF(a0)
		sin2, cos2 := sinCosF(a1)
		ax := cx + cos1*(r0+r1)*0.5
		ay := cy + sin1*(r0+r1)*0.5
		bx := cx + cos2*(r0+r1)*0.5
		by := cy + sin2*(r0+r1)*0.5
		color1 := nanovgo.HSLA(a0/(nanovgo.PI*2), 1.0, 0.55, 255)
		color2 := nanovgo.HSLA(a1/(nanovgo.PI*2), 1.0, 0.55, 255)
		paint := nanovgo.LinearGradient(ax, ay, bx, by, color1, color2)
		ctx.SetFillPaint(paint)
		ctx.Fill()
	}

	ctx.BeginPath()
	ctx.Circle(cx, cy, r0-0.5)
	ctx.Circle(cx, cy, r1+0.5)
	ctx.SetStrokeColor(nanovgo.MONO(0, 64))
	ctx.Stroke()

	// Selector
	ctx.Save()
	defer ctx.Restore()
	ctx.Translate(cx, cy)
	ctx.Rotate(c.hue * nanovgo.PI * 2)

	// Marker on
	u := clampF(r1/50, 1.5, 4.0)
	ctx.SetStrokeWidth(u)
	ctx.BeginPath()
	ctx.Rect(r0-1, -2*u, r1-r0+2, 4*u)
	ctx.SetStrokeColor(nanovgo.MONO(255, 192))
	ctx.Stroke()

	paint := nanovgo.BoxGradient(r0-3, -5, r1-r0+6, 10, 2, 4, nanovgo.MONO(0, 128), nanovgo.MONO(0, 0))
	ctx.BeginPath()
	ctx.Rect(r0-2-10, -4-10, r1-r0+4+20, 8+20)
	ctx.Rect(r0-2, -4, r1-r0+4, 8)
	ctx.PathWinding(nanovgo.Hole)
	ctx.SetFillPaint(paint)
	ctx.Fill()

	// Center triangle
	r := r0 - 6
	sin1, cos1 := sinCosF(120.0 / 180.0 * nanovgo.PI)
	sin2, cos2 := sinCosF(-120.0 / 180.0 * nanovgo.PI)
	ax := cos1 * r
	ay := sin1 * r
	bx := cos2 * r
	by := sin2 * r
	ctx.BeginPath()
	ctx.MoveTo(r, 0)
	ctx.LineTo(ax, ay)
	ctx.LineTo(bx, by)
	ctx.ClosePath()
	triPaint1 := nanovgo.LinearGradient(r, 0, ax, ay, nanovgo.HSL(c.hue, 1.0, 0.5), nanovgo.MONO(255, 255))
	ctx.SetFillPaint(triPaint1)
	ctx.Fill()
	triPaint2 := nanovgo.LinearGradient((r+ax)*0.5, ay*0.5, bx, by, nanovgo.MONO(0, 0), nanovgo.MONO(0, 255))
	ctx.SetFillPaint(triPaint2)
	ctx.Fill()

	// selector circle on triangle
	px, py := c.calculatePosition()
	ctx.SetStrokeWidth(u)
	ctx.BeginPath()
	ctx.Circle(px, py, 2*u)
	ctx.SetStrokeColor(nanovgo.MONO(255, 192))
	ctx.Stroke()
}
Beispiel #9
0
func NewStandardTheme(ctx *nanovgo.Context) *Theme {
	ctx.CreateFontFromMemory("sans", MustAsset("fonts/Roboto-Regular.ttf"), 0)
	ctx.CreateFontFromMemory("sans-bold", MustAsset("fonts/Roboto-Bold.ttf"), 0)
	ctx.CreateFontFromMemory("icons", MustAsset("fonts/entypo.ttf"), 0)
	return &Theme{
		StandardFontSize:     16,
		ButtonFontSize:       20,
		TextBoxFontSize:      20,
		WindowCornerRadius:   2,
		WindowHeaderHeight:   30,
		WindowDropShadowSize: 10,
		ButtonCornerRadius:   2,

		DropShadow:        nanovgo.MONO(0, 128),
		Transparent:       nanovgo.MONO(0, 0),
		BorderDark:        nanovgo.MONO(29, 255),
		BorderLight:       nanovgo.MONO(92, 255),
		BorderMedium:      nanovgo.MONO(35, 255),
		TextColor:         nanovgo.MONO(255, 160),
		DisabledTextColor: nanovgo.MONO(255, 80),
		TextColorShadow:   nanovgo.MONO(0, 160),
		IconColor:         nanovgo.MONO(255, 160),

		ButtonGradientTopFocused:   nanovgo.MONO(64, 255),
		ButtonGradientBotFocused:   nanovgo.MONO(48, 255),
		ButtonGradientTopUnfocused: nanovgo.MONO(74, 255),
		ButtonGradientBotUnfocused: nanovgo.MONO(58, 255),
		ButtonGradientTopPushed:    nanovgo.MONO(41, 255),
		ButtonGradientBotPushed:    nanovgo.MONO(29, 255),

		WindowFillUnfocused:  nanovgo.MONO(43, 230),
		WindowFillFocused:    nanovgo.MONO(45, 230),
		WindowTitleUnfocused: nanovgo.MONO(220, 160),
		WindowTitleFocused:   nanovgo.MONO(255, 190),

		WindowHeaderGradientTop: nanovgo.MONO(74, 255),
		WindowHeaderGradientBot: nanovgo.MONO(58, 255),
		WindowHeaderSepTop:      nanovgo.MONO(92, 255),
		WindowHeaderSepBot:      nanovgo.MONO(29, 255),

		WindowPopup:            nanovgo.MONO(50, 255),
		WindowPopupTransparent: nanovgo.MONO(50, 0),

		FontNormal: "sans",
		FontBold:   "sans-bold",
		FontIcons:  "icons",
	}
}
Beispiel #10
0
func (t *TextBox) Draw(self Widget, ctx *nanovgo.Context) {
	t.WidgetImplement.Draw(self, ctx)

	x := float32(t.x)
	y := float32(t.y)
	w := float32(t.w)
	h := float32(t.h)

	bg := nanovgo.BoxGradient(x+1, y+2, w-2, h-2, 3, 4, nanovgo.MONO(255, 32), nanovgo.MONO(32, 32))
	fg1 := nanovgo.BoxGradient(x+1, y+2, w-2, h-2, 3, 4, nanovgo.MONO(150, 32), nanovgo.MONO(32, 32))
	fg2 := nanovgo.BoxGradient(x+1, y+2, w-2, h-2, 3, 4, nanovgo.RGBA(255, 0, 0, 100), nanovgo.RGBA(255, 0, 0, 50))

	ctx.BeginPath()
	ctx.RoundedRect(x+1, y+2, w-2, h-2, 3)
	if t.editable && t.Focused() {
		if t.validFormat {
			ctx.SetFillPaint(fg1)
		} else {
			ctx.SetFillPaint(fg2)
		}
	} else {
		ctx.SetFillPaint(bg)
	}

	ctx.Fill()

	ctx.BeginPath()
	ctx.RoundedRect(x+0.5, y+0.5, w-1, h-1, 2.5)
	ctx.SetStrokeColor(nanovgo.MONO(0, 48))
	ctx.Stroke()

	ctx.SetFontSize(float32(t.FontSize()))
	ctx.SetFontFace(t.Font())
	drawPosX := x
	drawPosY := y + h*0.5 + 1

	xSpacing := h * 0.3
	var unitWidth float32

	if t.unitImage > 0 {
		iw, ih, _ := ctx.ImageSize(t.unitImage)
		unitHeight := float32(ih) * 0.4
		unitWidth = float32(iw) * unitHeight / float32(h)
		imgPaint := nanovgo.ImagePattern(x+w-xSpacing-unitWidth, drawPosY-unitHeight*0.5,
			unitWidth, unitHeight, 0, t.unitImage, toF(t.enabled, 0.7, 0.35))
		ctx.BeginPath()
		ctx.Rect(x+w-xSpacing-unitWidth, drawPosY-unitHeight*0.5, unitWidth, unitHeight)
		ctx.SetFillPaint(imgPaint)
		ctx.Fill()
		unitWidth += 2
	} else if t.units != "" {
		unitWidth, _ = ctx.TextBounds(0, 0, t.units)
		ctx.SetFillColor(nanovgo.MONO(255, toB(t.enabled, 64, 32)))
		ctx.SetTextAlign(nanovgo.AlignRight | nanovgo.AlignMiddle)
		ctx.Text(x+w-xSpacing, drawPosY, t.units)
	}

	switch t.alignment {
	case TextLeft:
		ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignMiddle)
		drawPosX += xSpacing
	case TextRight:
		ctx.SetTextAlign(nanovgo.AlignRight | nanovgo.AlignMiddle)
		drawPosX += w - unitWidth - xSpacing
	case TextCenter:
		ctx.SetTextAlign(nanovgo.AlignCenter | nanovgo.AlignMiddle)
		drawPosX += w * 0.5
	}
	if t.enabled {
		ctx.SetFillColor(t.theme.TextColor)
	} else {
		ctx.SetFillColor(t.theme.DisabledTextColor)
	}
	// clip visible text area
	clipX := x + xSpacing - 1
	clipY := y + 1.0
	clipWidth := w - unitWidth - 2.0*xSpacing + 2.0
	clipHeight := h - 3.0
	ctx.Scissor(clipX, clipY, clipWidth, clipHeight)
	oldDrawPosX := drawPosX
	drawPosX += t.textOffset

	if t.committed {
		ctx.Text(drawPosX, drawPosY, t.value)
	} else {
		text := t.editingText()
		textString := string(text)
		_, bounds := ctx.TextBounds(drawPosX, drawPosY, textString)
		lineH := bounds[3] - bounds[1]
		// find cursor positions
		glyphs := ctx.TextGlyphPositionsRune(drawPosX, drawPosY, text)
		t.updateCursor(ctx, bounds[2], glyphs)

		// compute text offset
		prevCPos := toI(t.cursorPos > 0, t.cursorPos-1, 0)
		nextCPos := toI(t.cursorPos < len(glyphs), t.cursorPos+1, len(glyphs))
		prevCX := t.textIndex2Position(prevCPos, bounds[2], glyphs)
		nextCX := t.textIndex2Position(nextCPos, bounds[2], glyphs)

		if nextCX > clipX+clipWidth {
			t.textOffset -= nextCX - (clipX + clipWidth) + 1.0
		}
		if prevCX < clipX {
			t.textOffset += clipX - prevCX + 1.0
		}
		drawPosX = oldDrawPosX + t.textOffset

		// draw text with offset
		ctx.TextRune(drawPosX, drawPosY, text)
		_, bounds = ctx.TextBounds(drawPosX, drawPosY, textString)

		// recompute cursor position
		glyphs = ctx.TextGlyphPositionsRune(drawPosX, drawPosY, text)

		var caretX float32 = -1
		if len(t.preeditText) != 0 {
			// draw preedit text
			caretX = t.textIndex2Position(t.cursorPos+len(t.preeditText), bounds[2], glyphs)

			offsetIndex := t.cursorPos
			offsetX := t.textIndex2Position(t.cursorPos, bounds[2], glyphs)
			ctx.SetStrokeColor(nanovgo.MONO(255, 160))
			ctx.SetFillColor(nanovgo.MONO(255, 80))
			ctx.SetStrokeWidth(2.0)
			for i, blockLength := range t.preeditBlocks {
				nextOffsetIndex := offsetIndex + blockLength
				nextOffsetX := t.textIndex2Position(nextOffsetIndex, bounds[2], glyphs)
				if i != t.preeditFocusedBlock {
					ctx.BeginPath()
					ctx.MoveTo(offsetX+2, drawPosY+lineH*0.5-1)
					ctx.LineTo(nextOffsetX-2, drawPosY+lineH*0.5-1)
					ctx.Stroke()
				} else {
					ctx.BeginPath()
					ctx.Rect(offsetX, drawPosY-lineH*0.5, nextOffsetX-offsetX, lineH)
					ctx.Fill()
				}
				offsetIndex = nextOffsetIndex
				offsetX = nextOffsetX
			}
			screen := t.FindWindow().Parent().(*Screen)
			oldCurX, oldCurY, oldCurH := screen.PreeditCursorPos()
			absX, absY := t.Parent().AbsolutePosition()
			newCurX := int(caretX) + absX
			newCurY := int(drawPosY+lineH*0.5) + absY
			newCurH := int(lineH)
			if oldCurX != newCurX || oldCurY != newCurY || oldCurH != newCurH {
				screen.SetPreeditCursorPos(newCurX, newCurY, newCurH)
			}
		} else if t.cursorPos > -1 {
			// regular cursor and selection area
			caretX = t.textIndex2Position(t.cursorPos, bounds[2], glyphs)

			if t.selectionPos > -1 {
				caretX2 := caretX
				selX := t.textIndex2Position(t.selectionPos, bounds[2], glyphs)

				if caretX2 > selX {
					selX, caretX2 = caretX2, selX
				}

				// draw selection
				ctx.BeginPath()
				ctx.SetFillColor(nanovgo.MONO(255, 80))
				ctx.Rect(caretX2, drawPosY-lineH*0.5, selX-caretX2, lineH)
				ctx.Fill()
			}
		}
		if caretX > 0 {
			// draw cursor
			ctx.BeginPath()
			ctx.MoveTo(caretX, drawPosY-lineH*0.5)
			ctx.LineTo(caretX, drawPosY+lineH*0.5)
			ctx.SetStrokeColor(nanovgo.RGBA(255, 192, 0, 255))
			ctx.SetStrokeWidth(1.0)
			ctx.Stroke()
		}
	}
	ctx.ResetScissor()
}