예제 #1
0
파일: demo.go 프로젝트: hajimehoshi/nanovgo
func drawScissor(ctx *nanovgo.Context, x, y, t float32) {
	ctx.Save()

	// Draw first rect and set scissor to it's area.
	ctx.Translate(x, y)
	ctx.Rotate(nanovgo.DegToRad(5))
	ctx.BeginPath()
	ctx.Rect(-20, -20, 60, 40)
	ctx.SetFillColor(nanovgo.RGBA(255, 0, 0, 255))
	ctx.Fill()
	ctx.Scissor(-20, -20, 60, 40)

	// Draw second rectangle with offset and rotation.
	ctx.Translate(40, 0)
	ctx.Rotate(t)

	// Draw the intended second rectangle without any scissoring.
	ctx.Save()
	ctx.ResetScissor()
	ctx.BeginPath()
	ctx.Rect(-20, -10, 60, 30)
	ctx.SetFillColor(nanovgo.RGBA(255, 128, 0, 64))
	ctx.Fill()
	ctx.Restore()

	// Draw second rectangle with combined scissoring.
	ctx.IntersectScissor(-20, -10, 60, 30)
	ctx.BeginPath()
	ctx.Rect(-20, -10, 60, 30)
	ctx.SetFillColor(nanovgo.RGBA(255, 128, 0, 255))
	ctx.Fill()

	ctx.Restore()
}
예제 #2
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)
}
예제 #3
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()
}