Example #1
0
func drawDropDown(ctx *nanovgo.Context, text string, x, y, w, h float32) {

	var cornerRadius float32 = 4.0

	bg := nanovgo.LinearGradient(x, y, x, y+h, nanovgo.RGBA(255, 255, 255, 16), nanovgo.RGBA(0, 0, 0, 16))
	ctx.BeginPath()
	ctx.RoundedRect(x+1, y+1, w-2, h-2, cornerRadius-1)
	ctx.SetFillPaint(bg)
	ctx.Fill()

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

	ctx.SetFontSize(20.0)
	ctx.SetFontFace("sans")
	ctx.SetFillColor(nanovgo.RGBA(255, 255, 255, 160))
	ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignMiddle)
	ctx.Text(x+h*0.3, y+h*0.5, text)

	ctx.SetFontSize(h * 1.3)
	ctx.SetFontFace("icons")
	ctx.SetFillColor(nanovgo.RGBA(255, 255, 255, 64))
	ctx.SetTextAlign(nanovgo.AlignCenter | nanovgo.AlignMiddle)
	ctx.Text(x+w-h*0.5, y+h*0.5, cpToUTF8(IconCHEVRONRIGHT))
}
Example #2
0
func drawLabel(ctx *nanovgo.Context, text string, x, y, w, h float32) {

	ctx.SetFontSize(18.0)
	ctx.SetFontFace("sans")
	ctx.SetFillColor(nanovgo.RGBA(255, 255, 255, 128))

	ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignMiddle)
	ctx.Text(x, y+h*0.5, text)
}
Example #3
0
func drawEditBox(ctx *nanovgo.Context, text string, x, y, w, h float32) {

	drawEditBoxBase(ctx, x, y, w, h)

	ctx.SetFontSize(20.0)
	ctx.SetFontFace("sans")
	ctx.SetFillColor(nanovgo.RGBA(255, 255, 255, 64))
	ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignMiddle)
	ctx.Text(x+h*0.3, y+h*0.5, text)
}
Example #4
0
func drawWindow(ctx *nanovgo.Context, title string, x, y, w, h float32) {
	var cornerRadius float32 = 3.0

	ctx.Save()
	defer ctx.Restore()
	//      ctx.Reset();

	// Window
	ctx.BeginPath()
	ctx.RoundedRect(x, y, w, h, cornerRadius)
	ctx.SetFillColor(nanovgo.RGBA(28, 30, 34, 192))
	//      ctx.FillColor(nanovgo.RGBA(0,0,0,128));
	ctx.Fill()

	// Drop shadow
	shadowPaint := nanovgo.BoxGradient(x, y+2, w, h, cornerRadius*2, 10, nanovgo.RGBA(0, 0, 0, 128), nanovgo.RGBA(0, 0, 0, 0))
	ctx.BeginPath()
	ctx.Rect(x-10, y-10, w+20, h+30)
	ctx.RoundedRect(x, y, w, h, cornerRadius)
	ctx.PathWinding(nanovgo.Hole)
	ctx.SetFillPaint(shadowPaint)
	ctx.Fill()

	// Header
	headerPaint := nanovgo.LinearGradient(x, y, x, y+15, nanovgo.RGBA(255, 255, 255, 8), nanovgo.RGBA(0, 0, 0, 16))
	ctx.BeginPath()
	ctx.RoundedRect(x+1, y+1, w-2, 30, cornerRadius-1)
	ctx.SetFillPaint(headerPaint)
	ctx.Fill()
	ctx.BeginPath()
	ctx.MoveTo(x+0.5, y+0.5+30)
	ctx.LineTo(x+0.5+w-1, y+0.5+30)
	ctx.SetStrokeColor(nanovgo.RGBA(0, 0, 0, 32))
	ctx.Stroke()

	ctx.SetFontSize(18.0)
	ctx.SetFontFace("sans-bold")
	ctx.SetTextAlign(nanovgo.AlignCenter | nanovgo.AlignMiddle)

	ctx.SetFontBlur(2)
	ctx.SetFillColor(nanovgo.RGBA(0, 0, 0, 128))
	ctx.Text(x+w/2, y+16+1, title)

	ctx.SetFontBlur(0)
	ctx.SetFillColor(nanovgo.RGBA(220, 220, 220, 160))
	ctx.Text(x+w/2, y+16, title)
}
Example #5
0
func drawButton(ctx *nanovgo.Context, preicon int, text string, x, y, w, h float32, col nanovgo.Color) {
	var cornerRadius float32 = 4.0
	var iw float32

	var alpha uint8
	if isBlack(col) {
		alpha = 16
	} else {
		alpha = 32
	}
	bg := nanovgo.LinearGradient(x, y, x, y+h, nanovgo.RGBA(255, 255, 255, alpha), nanovgo.RGBA(0, 0, 0, alpha))
	ctx.BeginPath()
	ctx.RoundedRect(x+1, y+1, w-2, h-2, cornerRadius-1)
	if !isBlack(col) {
		ctx.SetFillColor(col)
		ctx.Fill()
	}
	ctx.SetFillPaint(bg)
	ctx.Fill()

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

	ctx.SetFontSize(20.0)
	ctx.SetFontFace("sans-bold")
	tw, _ := ctx.TextBounds(0, 0, text)
	if preicon != 0 {
		ctx.SetFontSize(h * 1.3)
		ctx.SetFontFace("icons")
		iw, _ = ctx.TextBounds(0, 0, cpToUTF8(preicon))
		iw += h * 0.15

		ctx.SetFillColor(nanovgo.RGBA(255, 255, 255, 96))
		ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignMiddle)
		ctx.Text(x+w*0.5-tw*0.5-iw*0.75, y+h*0.5, cpToUTF8(preicon))
	}

	ctx.SetFontSize(20.0)
	ctx.SetFontFace("sans-bold")
	ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignMiddle)
	ctx.SetFillColor(nanovgo.RGBA(0, 0, 0, 160))
	ctx.Text(x+w*0.5-tw*0.5+iw*0.25, y+h*0.5-1, text)
	ctx.SetFillColor(nanovgo.RGBA(255, 255, 255, 160))
	ctx.Text(x+w*0.5-tw*0.5+iw*0.25, y+h*0.5, text)
}
Example #6
0
func drawEditBoxNum(ctx *nanovgo.Context, text, units string, x, y, w, h float32) {
	drawEditBoxBase(ctx, x, y, w, h)

	uw, _ := ctx.TextBounds(0, 0, units)

	ctx.SetFontSize(18.0)
	ctx.SetFontFace("sans")
	ctx.SetFillColor(nanovgo.RGBA(255, 255, 255, 64))
	ctx.SetTextAlign(nanovgo.AlignRight | nanovgo.AlignMiddle)
	ctx.Text(x+w-h*0.3, y+h*0.5, units)

	ctx.SetFontSize(20.0)
	ctx.SetFontFace("sans")
	ctx.SetFillColor(nanovgo.RGBA(255, 255, 255, 128))
	ctx.SetTextAlign(nanovgo.AlignRight | nanovgo.AlignMiddle)
	ctx.Text(x+w-uw-h*0.5, y+h*0.5, text)
}
Example #7
0
func (p *PopupButton) Draw(self Widget, ctx *nanovgo.Context) {
	if !p.enabled && p.pushed {
		p.pushed = false
	}
	p.popup.SetVisible(p.pushed)
	p.Button.Draw(self, ctx)
	if p.chevronIcon != 0 {
		ctx.SetFillColor(p.TextColor())
		ctx.SetFontSize(float32(p.FontSize()))
		ctx.SetFontFace(p.theme.FontIcons)
		ctx.SetTextAlign(nanovgo.AlignMiddle | nanovgo.AlignLeft)
		fontString := string([]rune{rune(p.chevronIcon)})
		iw, _ := ctx.TextBounds(0, 0, fontString)
		px, py := p.Position()
		w, h := p.Size()
		ix := px + w - int(iw) - 8
		iy := py + h/2 - 1
		ctx.Text(float32(ix), float32(iy), fontString)
	}
}
Example #8
0
func (l *Label) Draw(self Widget, ctx *nanovgo.Context) {
	l.WidgetImplement.Draw(self, ctx)
	ctx.SetFontSize(float32(l.FontSize()))
	ctx.SetFontFace(l.Font())
	ctx.SetFillColor(l.color)

	width := 0
	if l.FixedWidth() > 0 {
		width = l.FixedWidth()
	} else if l.columnWidth > 0 && l.wrap {
		width = l.columnWidth
	}

	if width > 0 {
		ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignTop)
		ctx.TextBox(float32(l.x), float32(l.y), float32(width), l.caption)
	} else {
		ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignMiddle)
		ctx.Text(float32(l.x), float32(l.y)+float32(l.h)*0.5, l.caption)
	}
}
Example #9
0
func drawCheckBox(ctx *nanovgo.Context, text string, x, y, w, h float32) {

	ctx.SetFontSize(18.0)
	ctx.SetFontFace("sans")
	ctx.SetFillColor(nanovgo.RGBA(255, 255, 255, 160))

	ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignMiddle)
	ctx.Text(x+28, y+h*0.5, text)

	bg := nanovgo.BoxGradient(x+1, y+float32(int(h*0.5))-9+1, 18, 18, 3, 3, nanovgo.RGBA(0, 0, 0, 32), nanovgo.RGBA(0, 0, 0, 92))
	ctx.BeginPath()
	ctx.RoundedRect(x+1, y+float32(int(h*0.5))-9, 18, 18, 3)
	ctx.SetFillPaint(bg)
	ctx.Fill()

	ctx.SetFontSize(40)
	ctx.SetFontFace("icons")
	ctx.SetFillColor(nanovgo.RGBA(255, 255, 255, 128))
	ctx.SetTextAlign(nanovgo.AlignCenter | nanovgo.AlignMiddle)
	ctx.Text(x+9+2, y+h*0.5, cpToUTF8(IconCHECK))
}
Example #10
0
func drawSearchBox(ctx *nanovgo.Context, text string, x, y, w, h float32) {
	cornerRadius := h/2 - 1

	// Edit
	bg := nanovgo.BoxGradient(x, y+1.5, w, h, h/2, 5, nanovgo.RGBA(0, 0, 0, 16), nanovgo.RGBA(0, 0, 0, 92))
	ctx.BeginPath()
	ctx.RoundedRect(x, y, w, h, cornerRadius)
	ctx.SetFillPaint(bg)
	ctx.Fill()

	/*      ctx.BeginPath();
	        ctx.RoundedRect(x+0.5f,y+0.5f, w-1,h-1, cornerRadius-0.5f);
	        ctx.StrokeColor(ctx.RGBA(0,0,0,48));
	        ctx.Stroke();*/

	ctx.SetFontSize(h * 1.3)
	ctx.SetFontFace("icons")
	ctx.SetFillColor(nanovgo.RGBA(255, 255, 255, 64))
	ctx.SetTextAlign(nanovgo.AlignCenter | nanovgo.AlignMiddle)
	ctx.Text(x+h*0.55, y+h*0.55, cpToUTF8(IconSEARCH))

	ctx.SetFontSize(20.0)
	ctx.SetFontFace("sans")
	ctx.SetFillColor(nanovgo.RGBA(255, 255, 255, 32))

	ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignMiddle)
	ctx.Text(x+h*1.05, y+h*0.5, text)

	ctx.SetFontSize(h * 1.3)
	ctx.SetFontFace("icons")
	ctx.SetFillColor(nanovgo.RGBA(255, 255, 255, 32))
	ctx.SetTextAlign(nanovgo.AlignCenter | nanovgo.AlignMiddle)
	ctx.Text(x+w-h*0.55, y+h*0.55, cpToUTF8(IconCIRCLEDCROSS))
}
Example #11
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)}))
	}
}
Example #12
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()
}
Example #13
0
func (l *Label) PreferredSize(self Widget, ctx *nanovgo.Context) (int, int) {
	if l.caption == "" {
		return 0, 0
	}
	ctx.SetFontSize(float32(l.FontSize()))
	ctx.SetFontFace(l.Font())

	width := 0
	if l.FixedWidth() > 0 {
		width = l.FixedWidth()
	} else if l.columnWidth > 0 && l.wrap {
		width = l.columnWidth
	}

	if width > 0 {
		ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignTop)
		bounds := ctx.TextBoxBounds(0, 0, float32(width), l.caption)
		return width, int(bounds[3] - bounds[1])
	} else {
		ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignTop)
		w, _ := ctx.TextBounds(0, 0, l.caption)
		return int(w), l.Theme().StandardFontSize
	}
}
Example #14
0
// RenderGraph shows graph
func (pg *PerfGraph) RenderGraph(ctx *nanovgo.Context, x, y float32) {
	avg := pg.GetGraphAverage()
	var w float32 = 200
	var h float32 = 35

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

	ctx.BeginPath()
	ctx.MoveTo(x, y+h)
	for i := 0; i < nvgGraphHistoryCount; i++ {
		v := float32(1.0) / float32(0.00001+pg.values[(pg.head+i)%nvgGraphHistoryCount])
		if v > 80.0 {
			v = 80.0
		}
		vx := x + float32(i)/float32(nvgGraphHistoryCount-1)*w
		vy := y + h - ((v / 80.0) * h)
		ctx.LineTo(vx, vy)
	}
	ctx.LineTo(x+w, y+h)
	ctx.SetFillColor(graphColor)
	ctx.Fill()

	ctx.SetFontFace(pg.fontFace)

	if len(pg.name) > 0 {
		ctx.SetFontSize(14.0)
		ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignTop)
		ctx.SetFillColor(titleTextColor)
		ctx.Text(x+3, y+1, pg.name)
	}

	ctx.SetFontSize(18.0)
	ctx.SetTextAlign(nanovgo.AlignRight | nanovgo.AlignTop)
	ctx.SetFillColor(fpsTextColor)
	ctx.Text(x+w-3, y+1, fmt.Sprintf("%.2f FPS", 1.0/avg))

	ctx.SetFontSize(15.0)
	ctx.SetTextAlign(nanovgo.AlignRight | nanovgo.AlignBottom)
	ctx.SetFillColor(averageTextColor)
	ctx.Text(x+w-3, y+h+1, fmt.Sprintf("%.2f ms", avg*1000.0))
}
Example #15
0
func (w *Window) Draw(self Widget, ctx *nanovgo.Context) {
	ds := float32(w.theme.WindowDropShadowSize)
	cr := float32(w.theme.WindowCornerRadius)
	hh := float32(w.theme.WindowHeaderHeight)

	// Draw window
	wx := float32(w.x)
	wy := float32(w.y)
	ww := float32(w.w)
	wh := float32(w.h)
	ctx.Save()
	ctx.BeginPath()
	ctx.RoundedRect(wx, wy, ww, wh, cr)
	if w.mouseFocus {
		ctx.SetFillColor(w.theme.WindowFillFocused)
	} else {
		ctx.SetFillColor(w.theme.WindowFillUnfocused)
	}
	ctx.Fill()

	// Draw a drop shadow
	shadowPaint := nanovgo.BoxGradient(wx, wy, ww, wh, cr*2, ds*2, w.theme.DropShadow, w.theme.Transparent)
	ctx.BeginPath()
	ctx.Rect(wx-ds, wy-ds, ww+ds*2, wh+ds*2)
	ctx.RoundedRect(wx, wy, ww, wh, cr)
	ctx.PathWinding(nanovgo.Hole)
	ctx.SetFillPaint(shadowPaint)
	ctx.Fill()

	if w.title != "" {
		headerPaint := nanovgo.LinearGradient(wx, wy, ww, wh+hh, w.theme.WindowHeaderGradientTop, w.theme.WindowHeaderGradientBot)

		ctx.BeginPath()
		ctx.RoundedRect(wx, wy, ww, hh, cr)
		ctx.SetFillPaint(headerPaint)
		ctx.Fill()

		ctx.BeginPath()
		ctx.RoundedRect(wx, wy, ww, wh, cr)
		ctx.SetStrokeColor(w.theme.WindowHeaderSepTop)
		ctx.Scissor(wx, wy, ww, 0.5)
		ctx.Stroke()
		ctx.ResetScissor()

		ctx.BeginPath()
		ctx.MoveTo(wx+0.5, wy+hh-1.5)
		ctx.LineTo(wx+ww-0.5, wy+hh-1.5)
		ctx.SetStrokeColor(w.theme.WindowHeaderSepTop)
		ctx.Stroke()

		ctx.SetFontSize(18.0)
		ctx.SetFontFace(w.theme.FontBold)
		ctx.SetTextAlign(nanovgo.AlignCenter | nanovgo.AlignMiddle)
		ctx.SetFontBlur(2.0)
		ctx.SetFillColor(w.theme.DropShadow)
		ctx.Text(wx+ww*0.5, wy+hh*0.5, w.title)
		ctx.SetFontBlur(0.0)
		if w.focused {
			ctx.SetFillColor(w.theme.WindowTitleFocused)
		} else {
			ctx.SetFillColor(w.theme.WindowTitleUnfocused)
		}
		ctx.Text(wx+ww*0.5, wy+hh*0.5-1, w.title)
	}
	ctx.Restore()
	w.WidgetImplement.Draw(self, ctx)
}
Example #16
0
func (b *Button) Draw(self Widget, ctx *nanovgo.Context) {
	b.WidgetImplement.Draw(self, ctx)

	bx := float32(b.x)
	by := float32(b.y)
	bw := float32(b.w)
	bh := float32(b.h)

	var gradTop nanovgo.Color
	var gradBot nanovgo.Color

	if b.pushed {
		gradTop = b.theme.ButtonGradientTopPushed
		gradBot = b.theme.ButtonGradientBotPushed
	} else if b.mouseFocus && b.enabled {
		gradTop = b.theme.ButtonGradientTopFocused
		gradBot = b.theme.ButtonGradientBotFocused
	} else {
		gradTop = b.theme.ButtonGradientTopUnfocused
		gradBot = b.theme.ButtonGradientBotUnfocused
	}
	ctx.BeginPath()
	ctx.RoundedRect(bx+1.0, by+1.0, bw-2.0, bh-2.0, float32(b.theme.ButtonCornerRadius-1))

	if b.backgroundColor.A != 0.0 {
		bgColor := b.backgroundColor
		bgColor.A = 1.0
		ctx.SetFillColor(bgColor)
		ctx.Fill()
		if b.pushed {
			gradTop.A = 0.8
			gradBot.A = 0.8
		} else {
			a := 1 - b.backgroundColor.A
			if !b.enabled {
				a = a*0.5 + 0.5
			}
			gradTop.A = a
			gradBot.A = a
		}
	}

	bg := nanovgo.LinearGradient(bx, by, bx, by+bh, gradTop, gradBot)
	ctx.SetFillPaint(bg)
	ctx.Fill()

	ctx.BeginPath()
	var pOff float32 = 0.0
	if b.pushed {
		pOff = 1.0
	}
	ctx.RoundedRect(bx+0.5, by+1.5-pOff, bw-1.0, bh-2+pOff, float32(b.theme.ButtonCornerRadius))
	ctx.SetStrokeColor(b.theme.BorderLight)
	ctx.Stroke()

	ctx.BeginPath()
	ctx.RoundedRect(bx+0.5, by+0.5, bw-1.0, bh-2, float32(b.theme.ButtonCornerRadius))
	ctx.SetStrokeColor(b.theme.BorderDark)
	ctx.Stroke()

	fontSize := float32(b.FontSize())
	ctx.SetFontSize(fontSize)
	ctx.SetFontFace(b.theme.FontBold)
	caption := b.caption
	tw, _ := ctx.TextBounds(0, 0, caption)

	centerX := bx + bw*0.5
	centerY := by + bh*0.5
	textPosX := centerX - tw*0.5
	textPosY := centerY - 1.0

	textColor := b.TextColor()
	if b.icon > 0 || b.imageIcon > 0 {
		var iw, ih float32
		if b.icon > 0 {
			ih = fontSize * 1.5 / 2
			ctx.SetFontSize(ih)
			ctx.SetFontFace(b.theme.FontIcons)
			iw, _ = ctx.TextBounds(0, 0, string([]rune{rune(b.icon)}))
		} else if b.imageIcon > 0 {
			ih = fontSize * 0.9
			w, h, _ := ctx.ImageSize(b.imageIcon)
			iw = float32(w) * ih / float32(h)
		}
		if b.caption != "" {
			iw += float32(b.h) * 0.15
		}
		ctx.SetFillColor(textColor)
		ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignMiddle)
		iconPosX := centerX
		iconPosY := centerY - 1

		switch b.iconPosition {
		case ButtonIconLeftCentered:
			iconPosX -= (tw + iw) * 0.5
			textPosX += iw * 0.5
		case ButtonIconRightCentered:
			iconPosX -= iw * 0.5
			textPosX += tw * 0.5
		case ButtonIconLeft:
			iconPosX = bx + 8.0
		case ButtonIconRight:
			iconPosX = bx + bw - iw - 8
		}
		if b.icon > 0 {
			ctx.TextRune(iconPosX, iconPosY, []rune{rune(b.icon)})
		} else {
			var eOff float32 = 0.25
			if b.enabled {
				eOff = 0.5
			}
			imgPaint := nanovgo.ImagePattern(iconPosX, iconPosY-ih*0.5, iw, ih, 0, b.imageIcon, eOff)
			ctx.SetFillPaint(imgPaint)
			ctx.Fill()
		}
	}
	ctx.SetFontSize(fontSize)
	ctx.SetFontFace(b.theme.FontBold)
	ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignMiddle)
	ctx.SetFillColor(b.theme.TextColorShadow)
	ctx.Text(textPosX, textPosY, caption)
	ctx.SetFillColor(textColor)
	ctx.Text(textPosX, textPosY+1.0, caption)
}
Example #17
0
func drawParagraph(ctx *nanovgo.Context, x, y, width, height, mx, my float32) {
	text := "This is longer chunk of text.\n  \n  Would have used lorem ipsum but she    was busy jumping over the lazy dog with the fox and all the men who came to the aid of the party."

	ctx.Save()
	defer ctx.Restore()

	ctx.SetFontSize(18.0)
	ctx.SetFontFace("sans")
	ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignTop)
	_, _, lineh := ctx.TextMetrics()
	// The text break API can be used to fill a large buffer of rows,
	// or to iterate over the text just few lines (or just one) at a time.
	// The "next" variable of the last returned item tells where to continue.
	runes := []rune(text)

	var gx, gy float32
	var gutter int
	lnum := 0

	for _, row := range ctx.TextBreakLinesRune(runes, width) {
		hit := mx > x && mx < (x+width) && my >= y && my < (y+lineh)

		ctx.BeginPath()
		var alpha uint8
		if hit {
			alpha = 64
		} else {
			alpha = 16
		}
		ctx.SetFillColor(nanovgo.RGBA(255, 255, 255, alpha))
		ctx.Rect(x, y, row.Width, lineh)
		ctx.Fill()

		ctx.SetFillColor(nanovgo.RGBA(255, 255, 255, 255))
		ctx.TextRune(x, y, runes[row.StartIndex:row.EndIndex])

		if hit {
			var caretX float32
			if mx < x+row.Width/2 {
				caretX = x
			} else {
				caretX = x + row.Width
			}
			px := x
			lineRune := runes[row.StartIndex:row.EndIndex]
			glyphs := ctx.TextGlyphPositionsRune(x, y, lineRune)
			for j, glyph := range glyphs {
				x0 := glyph.X
				var x1 float32
				if j+1 < len(glyphs) {
					x1 = glyphs[j+1].X
				} else {
					x1 = x + row.Width
				}
				gx = x0*0.3 + x1*0.7
				if mx >= px && mx < gx {
					caretX = glyph.X
				}
				px = gx
			}
			ctx.BeginPath()
			ctx.SetFillColor(nanovgo.RGBA(255, 192, 0, 255))
			ctx.Rect(caretX, y, 1, lineh)
			ctx.Fill()

			gutter = lnum + 1
			gx = x - 10
			gy = y + lineh/2
		}
		lnum++
		y += lineh
	}

	if gutter > 0 {
		txt := strconv.Itoa(gutter)

		ctx.SetFontSize(13.0)
		ctx.SetTextAlign(nanovgo.AlignRight | nanovgo.AlignMiddle)

		_, bounds := ctx.TextBounds(gx, gy, txt)

		ctx.BeginPath()
		ctx.SetFillColor(nanovgo.RGBA(255, 192, 0, 255))
		ctx.RoundedRect(
			float32(int(bounds[0]-4)),
			float32(int(bounds[1]-2)),
			float32(int(bounds[2]-bounds[0])+8),
			float32(int(bounds[3]-bounds[1])+4),
			float32(int(bounds[3]-bounds[1])+4)/2.0-1.0)
		ctx.Fill()

		ctx.SetFillColor(nanovgo.RGBA(32, 32, 32, 255))
		ctx.Text(gx, gy, txt)
	}

	y += 20.0

	ctx.SetFontSize(13.0)
	ctx.SetTextAlign(nanovgo.AlignLeft | nanovgo.AlignTop)
	ctx.SetTextLineHeight(1.2)

	bounds := ctx.TextBoxBounds(x, y, 150, "Hover your mouse over the text to see calculated caret position.")

	// Fade the tooltip out when close to it.
	gx = absF((mx - (bounds[0]+bounds[2])*0.5) / (bounds[0] - bounds[2]))
	gy = absF((my - (bounds[1]+bounds[3])*0.5) / (bounds[1] - bounds[3]))
	a := maxF(gx, gy) - 0.5
	a = clampF(a, 0, 1)
	ctx.SetGlobalAlpha(a)

	ctx.BeginPath()
	ctx.SetFillColor(nanovgo.RGBA(220, 220, 220, 255))
	ctx.RoundedRect(bounds[0]-2, bounds[1]-2, float32(int(bounds[2]-bounds[0])+4), float32(int(bounds[3]-bounds[1])+4), 3)
	px := float32(int((bounds[2] + bounds[0]) / 2))
	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.RGBA(0, 0, 0, 220))
	ctx.TextBox(x, y, 150, "Hover your mouse over the text to see calculated caret position.")
}
Example #18
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()
}