void Caret::updatePosFromIdx(NVGcontext *ctx) { float lineh; nvgTextMetrics(ctx, nullptr, nullptr, &lineh); const int maxGlyphs = 1024; NVGglyphPosition glyphs[maxGlyphs]; const std::string& textLine = mConsole->mBuffer[mIdx.y()]; float textBound[4]; nvgTextBounds(ctx, 0, 0, textLine.c_str(), nullptr, textBound); int nglyphs = nvgTextGlyphPositions(ctx, 0, 0, textLine.c_str(), nullptr, glyphs, maxGlyphs); //update carete position now mPos.y() = mIdx.y() * lineh; mPos.x() = cursorIndex2Position(mIdx.x(), textBound[2], glyphs, nglyphs); }
void Caret::onClick(NVGcontext *ctx, float lineh, Vector2i clickPos){ if (clickPos.x() > -1) { mIdx.y() = (int) clickPos.y()/lineh; //std::cout << "mPos = " << mConsole->mPos.x() << "," << mConsole->mPos.y() << std::endl; if(mIdx.y() < (int)mConsole->mBuffer.size()){ //std::cout << mBuffer.at(mCursorPosY)<< std::endl; double time = glfwGetTime(); if (time - mLastClick < 0.25) { /* Double-click: select a line */ int linew = mConsole->mSize.x(); mSelectionIdx = Vector2i(0,(int) clickPos.y()/lineh); mSelectionPos = Vector2i(0,mSelectionIdx.y()*lineh); mIdx = Vector2i(mConsole->mBuffer[mSelectionIdx.y()].size(), mSelectionIdx.y()); mPos = Vector2i(linew, mSelectionPos.y()); mSelectionState = true; std::cout << "Sel : " << mSelectionPos.x() << "," << mSelectionPos.y() << std::endl; std::cout << "Pos : " << mPos.x() << "," << mPos.y() << std::endl; } else { const int maxGlyphs = 1024; NVGglyphPosition glyphs[maxGlyphs]; const std::string& textLine = mConsole->mBuffer[mIdx.y()]; float textBound[4]; nvgTextBounds(ctx, 0, 0, textLine.c_str(), nullptr, textBound); int nglyphs = nvgTextGlyphPositions(ctx, 0, 0, textLine.c_str(), nullptr, glyphs, maxGlyphs); mIdx.x() = position2CursorIndex(clickPos.x(), textBound[2], glyphs, nglyphs); //update carete position now mPos.y() = mIdx.y() * lineh; mPos.x() = cursorIndex2Position(mIdx.x(), textBound[2], glyphs, nglyphs); } mLastClick = time; } } }
void TextBox::draw(NVGcontext* ctx) { Widget::draw(ctx); NVGpaint bg = nvgBoxGradient(ctx, mPos.x() + 1, mPos.y() + 1 + 1.0f, mSize.x() - 2, mSize.y() - 2, 3, 4, Color(255, 32), Color(32, 32)); NVGpaint fg1 = nvgBoxGradient(ctx, mPos.x() + 1, mPos.y() + 1 + 1.0f, mSize.x() - 2, mSize.y() - 2, 3, 4, Color(150, 32), Color(32, 32)); NVGpaint fg2 = nvgBoxGradient(ctx, mPos.x() + 1, mPos.y() + 1 + 1.0f, mSize.x() - 2, mSize.y() - 2, 3, 4, nvgRGBA(255, 0, 0, 100), nvgRGBA(255, 0, 0, 50)); nvgBeginPath(ctx); nvgRoundedRect(ctx, mPos.x() + 1, mPos.y() + 1 + 1.0f, mSize.x() - 2, mSize.y() - 2, 3); if(mEditable && focused()) mValidFormat ? nvgFillPaint(ctx, fg1) : nvgFillPaint(ctx, fg2); else nvgFillPaint(ctx, bg); nvgFill(ctx); nvgBeginPath(ctx); nvgRoundedRect(ctx, mPos.x() + 0.5f, mPos.y() + 0.5f, mSize.x() - 1, mSize.y() - 1, 2.5f); nvgStrokeColor(ctx, Color(0, 48)); nvgStroke(ctx); nvgFontSize(ctx, fontSize()); nvgFontFace(ctx, "sans"); Vector2i drawPos(mPos.x(), mPos.y() + mSize.y() * 0.5f + 1); float xSpacing = mSize.y() * 0.3f; float unitWidth = 0; if (mUnitsImage > 0) { int w, h; nvgImageSize(ctx, mUnitsImage, &w, &h); float unitHeight = mSize.y() * 0.4f; unitWidth = w * unitHeight / h; NVGpaint imgPaint = nvgImagePattern( ctx, mPos.x() + mSize.x() - xSpacing - unitWidth, drawPos.y() - unitHeight * 0.5f, unitWidth, unitHeight, 0, mUnitsImage, mEnabled ? 0.7f : 0.35f); nvgBeginPath(ctx); nvgRect(ctx, mPos.x() + mSize.x() - xSpacing - unitWidth, drawPos.y() - unitHeight * 0.5f, unitWidth, unitHeight); nvgFillPaint(ctx, imgPaint); nvgFill(ctx); unitWidth += 2; } else if (!mUnits.empty()) { unitWidth = nvgTextBounds(ctx, 0, 0, mUnits.c_str(), nullptr, nullptr); nvgFillColor(ctx, Color(255, mEnabled ? 64 : 32)); nvgTextAlign(ctx, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE); nvgText(ctx, mPos.x() + mSize.x() - xSpacing, drawPos.y(), mUnits.c_str(), nullptr); unitWidth += 2; } switch (mAlignment) { case Alignment::Left: nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); drawPos.x() += xSpacing; break; case Alignment::Right: nvgTextAlign(ctx, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE); drawPos.x() += mSize.x() - unitWidth - xSpacing; break; case Alignment::Center: nvgTextAlign(ctx, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE); drawPos.x() += mSize.x() * 0.5f; break; } nvgFontSize(ctx, fontSize()); nvgFillColor(ctx, mEnabled ? mTheme->mTextColor : mTheme->mDisabledTextColor); // clip visible text area float clipX = mPos.x() + xSpacing - 1.0f; float clipY = mPos.y() + 1.0f; float clipWidth = mSize.x() - unitWidth - 2 * xSpacing + 2.0f; float clipHeight = mSize.y() - 3.0f; nvgScissor(ctx, clipX, clipY, clipWidth, clipHeight); Vector2i oldDrawPos(drawPos); drawPos.x() += mTextOffset; if (mCommitted) { nvgText(ctx, drawPos.x(), drawPos.y(), mValue.c_str(), nullptr); } else { const int maxGlyphs = 1024; NVGglyphPosition glyphs[maxGlyphs]; float textBound[4]; nvgTextBounds(ctx, drawPos.x(), drawPos.y(), mValueTemp.c_str(), nullptr, textBound); float lineh = textBound[3] - textBound[1]; // find cursor positions int nglyphs = nvgTextGlyphPositions(ctx, drawPos.x(), drawPos.y(), mValueTemp.c_str(), nullptr, glyphs, maxGlyphs); updateCursor(ctx, textBound[2], glyphs, nglyphs); // compute text offset int prevCPos = mCursorPos > 0 ? mCursorPos - 1 : 0; int nextCPos = mCursorPos < nglyphs ? mCursorPos + 1 : nglyphs; float prevCX = cursorIndex2Position(prevCPos, textBound[2], glyphs, nglyphs); float nextCX = cursorIndex2Position(nextCPos, textBound[2], glyphs, nglyphs); if (nextCX > clipX + clipWidth) mTextOffset -= nextCX - (clipX + clipWidth) + 1; if (prevCX < clipX) mTextOffset += clipX - prevCX + 1; drawPos.x() = oldDrawPos.x() + mTextOffset; // draw text with offset nvgText(ctx, drawPos.x(), drawPos.y(), mValueTemp.c_str(), nullptr); nvgTextBounds(ctx, drawPos.x(), drawPos.y(), mValueTemp.c_str(), nullptr, textBound); // recompute cursor positions nglyphs = nvgTextGlyphPositions(ctx, drawPos.x(), drawPos.y(), mValueTemp.c_str(), nullptr, glyphs, maxGlyphs); if (mCursorPos > -1) { if (mSelectionPos > -1) { float caretx = cursorIndex2Position(mCursorPos, textBound[2], glyphs, nglyphs); float selx = cursorIndex2Position(mSelectionPos, textBound[2], glyphs, nglyphs); if (caretx > selx) std::swap(caretx, selx); // draw selection nvgBeginPath(ctx); nvgFillColor(ctx, nvgRGBA(255, 255, 255, 80)); nvgRect(ctx, caretx, drawPos.y() - lineh * 0.5f, selx - caretx, lineh); nvgFill(ctx); } float caretx = cursorIndex2Position(mCursorPos, textBound[2], glyphs, nglyphs); // draw cursor nvgBeginPath(ctx); nvgMoveTo(ctx, caretx, drawPos.y() - lineh * 0.5f); nvgLineTo(ctx, caretx, drawPos.y() + lineh * 0.5f); nvgStrokeColor(ctx, nvgRGBA(255, 192, 0, 255)); nvgStrokeWidth(ctx, 1.0f); nvgStroke(ctx); } } nvgResetScissor(ctx); }