void TabWidget::draw(NVGcontext* ctx) { int tabHeight = mHeader->preferredSize(ctx).y(); auto activeArea = mHeader->activeButtonArea(); for (int i = 0; i < 3; ++i) { nvgSave(ctx); if (i == 0) nvgIntersectScissor(ctx, mPos.x(), mPos.y(), activeArea.first.x() + 1, mSize.y()); else if (i == 1) nvgIntersectScissor(ctx, mPos.x() + activeArea.second.x(), mPos.y(), mSize.x() - activeArea.second.x(), mSize.y()); else nvgIntersectScissor(ctx, mPos.x(), mPos.y() + tabHeight + 2, mSize.x(), mSize.y()); nvgBeginPath(ctx); nvgStrokeWidth(ctx, 1.0f); nvgRoundedRect(ctx, mPos.x() + 0.5f, mPos.y() + tabHeight + 1.5f, mSize.x() - 1, mSize.y() - tabHeight - 2, mTheme->mButtonCornerRadius); nvgStrokeColor(ctx, mTheme->mBorderLight); nvgStroke(ctx); nvgBeginPath(ctx); nvgRoundedRect(ctx, mPos.x() + 0.5f, mPos.y() + tabHeight + 0.5f, mSize.x() - 1, mSize.y() - tabHeight - 2, mTheme->mButtonCornerRadius); nvgStrokeColor(ctx, mTheme->mBorderDark); nvgStroke(ctx); nvgRestore(ctx); } Widget::draw(ctx); }
void TabWidget::draw(NVGcontext* ctx) { int tab_height = m_header->preferred_size(ctx).y(); auto active_area = m_header->active_button_area(); for (int i = 0; i < 3; ++i) { nvgSave(ctx); if (i == 0) nvgIntersectScissor(ctx, m_pos.x(), m_pos.y(), active_area.first.x() + 1, m_size.y()); else if (i == 1) nvgIntersectScissor(ctx, m_pos.x() + active_area.second.x(), m_pos.y(), m_size.x() - active_area.second.x(), m_size.y()); else nvgIntersectScissor(ctx, m_pos.x(), m_pos.y() + tab_height + 2, m_size.x(), m_size.y()); nvgBeginPath(ctx); nvgStrokeWidth(ctx, 1.0f); nvgRoundedRect(ctx, m_pos.x() + 0.5f, m_pos.y() + tab_height + 1.5f, m_size.x() - 1, m_size.y() - tab_height - 2, m_theme->m_button_corner_radius); nvgStrokeColor(ctx, m_theme->m_border_light); nvgStroke(ctx); nvgBeginPath(ctx); nvgRoundedRect(ctx, m_pos.x() + 0.5f, m_pos.y() + tab_height + 0.5f, m_size.x() - 1, m_size.y() - tab_height - 2, m_theme->m_button_corner_radius); nvgStrokeColor(ctx, m_theme->m_border_dark); nvgStroke(ctx); nvgRestore(ctx); } Widget::draw(ctx); }
void VScrollPanel::draw(NVGcontext *ctx) { if (m_children.empty()) return; Widget *child = m_children[0]; child->set_position(Vector2i(0, -m_scroll*(m_child_preferred_height - m_size.y()))); m_child_preferred_height = child->preferred_size(ctx).y(); float scrollh = height() * std::min(1.0f, height() / (float) m_child_preferred_height); if (m_update_layout) { m_update_layout = false; child->perform_layout(ctx); } nvgSave(ctx); nvgTranslate(ctx, m_pos.x(), m_pos.y()); nvgIntersectScissor(ctx, 0, 0, m_size.x(), m_size.y()); if (child->visible()) child->draw(ctx); nvgRestore(ctx); if (m_child_preferred_height <= m_size.y()) return; NVGpaint paint = nvgBoxGradient( ctx, m_pos.x() + m_size.x() - 12 + 1, m_pos.y() + 4 + 1, 8, m_size.y() - 8, 3, 4, Color(0, 32), Color(0, 92)); nvgBeginPath(ctx); nvgRoundedRect(ctx, m_pos.x() + m_size.x() - 12, m_pos.y() + 4, 8, m_size.y() - 8, 3); nvgFillPaint(ctx, paint); nvgFill(ctx); paint = nvgBoxGradient( ctx, m_pos.x() + m_size.x() - 12 - 1, m_pos.y() + 4 + (m_size.y() - 8 - scrollh) * m_scroll - 1, 8, scrollh, 3, 4, Color(220, 100), Color(128, 100)); nvgBeginPath(ctx); nvgRoundedRect(ctx, m_pos.x() + m_size.x() - 12 + 1, m_pos.y() + 4 + 1 + (m_size.y() - 8 - scrollh) * m_scroll, 8 - 2, scrollh - 2, 2); nvgFillPaint(ctx, paint); nvgFill(ctx); }
void NanoVG::intersectScissor( float x, float y, float w, float h ) { nvgIntersectScissor( m_context(), x, y, w, h ); }
void drawUI(NVGcontext *vg, int item, int corners) { const UIData *head = (const UIData *)uiGetHandle(item); UIrect rect = uiGetRect(item); if (uiGetState(item) == UI_FROZEN) { nvgGlobalAlpha(vg, BND_DISABLED_ALPHA); } if (head) { switch(head->subtype) { default: { testrect(vg,rect); drawUIItems(vg,item,corners); } break; case ST_HBOX: { drawUIItemsHbox(vg, item); } break; case ST_VBOX: { drawUIItemsVbox(vg, item); } break; case ST_PANEL: { bndBevel(vg,rect.x,rect.y,rect.w,rect.h); drawUIItems(vg,item,corners); } break; case ST_LABEL: { assert(head); const UIButtonData *data = (UIButtonData*)head; bndLabel(vg,rect.x,rect.y,rect.w,rect.h, data->iconid,data->label); } break; case ST_BUTTON: { const UIButtonData *data = (UIButtonData*)head; bndToolButton(vg,rect.x,rect.y,rect.w,rect.h, corners,(BNDwidgetState)uiGetState(item), data->iconid,data->label); } break; case ST_CHECK: { const UICheckData *data = (UICheckData*)head; BNDwidgetState state = (BNDwidgetState)uiGetState(item); if (*data->option) state = BND_ACTIVE; bndOptionButton(vg,rect.x,rect.y,rect.w,rect.h, state, data->label); } break; case ST_RADIO:{ const UIRadioData *data = (UIRadioData*)head; BNDwidgetState state = (BNDwidgetState)uiGetState(item); if (*data->value == item) state = BND_ACTIVE; bndRadioButton(vg,rect.x,rect.y,rect.w,rect.h, corners,state, data->iconid,data->label); } break; case ST_SLIDER:{ const UISliderData *data = (UISliderData*)head; BNDwidgetState state = (BNDwidgetState)uiGetState(item); static char value[32]; sprintf(value,"%.0f%%",(*data->progress)*100.0f); bndSlider(vg,rect.x,rect.y,rect.w,rect.h, corners,state, *data->progress,data->label,value); } break; case ST_TEXT: { const UITextData *data = (UITextData*)head; BNDwidgetState state = (BNDwidgetState)uiGetState(item); int idx = strlen(data->text); bndTextField(vg,rect.x,rect.y,rect.w,rect.h, corners,state, -1, data->text, idx, idx); } break; case ST_DEMOSTUFF: { draw_demostuff(vg, rect.x, rect.y, rect.w, rect.h); } break; case ST_RECT: { const UIRectData *data = (UIRectData*)head; if (rect.w && rect.h) { BNDwidgetState state = (BNDwidgetState)uiGetState(item); nvgSave(vg); nvgStrokeColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.9f)); if (state != BND_DEFAULT) { nvgFillColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.5f)); } else { nvgFillColor(vg, nvgRGBAf(data->color.r,data->color.g,data->color.b,0.1f)); } nvgStrokeWidth(vg,2); nvgBeginPath(vg); #if 0 nvgRect(vg,rect.x,rect.y,rect.w,rect.h); #else nvgRoundedRect(vg,rect.x,rect.y,rect.w,rect.h,3); #endif nvgFill(vg); nvgStroke(vg); if (state != BND_DEFAULT) { nvgFillColor(vg, nvgRGBAf(0.0f,0.0f,0.0f,1.0f)); nvgFontSize(vg, 15.0f); nvgBeginPath(vg); nvgTextAlign(vg, NVG_ALIGN_TOP|NVG_ALIGN_CENTER); nvgTextBox(vg, rect.x, rect.y+rect.h*0.3f, rect.w, data->label, NULL); } nvgRestore(vg); } nvgSave(vg); nvgIntersectScissor(vg, rect.x, rect.y, rect.w, rect.h); drawUIItems(vg,item,corners); nvgRestore(vg); } break; } } else { testrect(vg,rect); drawUIItems(vg,item,corners); } if (uiGetState(item) == UI_FROZEN) { nvgGlobalAlpha(vg, 1.0); } }
void Window::draw(NVGcontext *ctx) { int ds = mTheme->mWindowDropShadowSize, cr = mTheme->mWindowCornerRadius; int hh = mTheme->mWindowHeaderHeight; /* Draw window */ nvgSave(ctx); nvgBeginPath(ctx); nvgRoundedRect(ctx, mPos.x(), mPos.y(), mSize.x(), mSize.y(), cr); nvgFillColor(ctx, mMouseFocus ? mTheme->mWindowFillFocused : mTheme->mWindowFillUnfocused); nvgFill(ctx); /* Draw a drop shadow */ NVGpaint shadowPaint = nvgBoxGradient( ctx, mPos.x(), mPos.y(), mSize.x(), mSize.y(), cr*2, ds*2, mTheme->mDropShadow, mTheme->mTransparent); nvgBeginPath(ctx); nvgRect(ctx, mPos.x()-ds,mPos.y()-ds, mSize.x()+2*ds, mSize.y()+2*ds); nvgRoundedRect(ctx, mPos.x(), mPos.y(), mSize.x(), mSize.y(), cr); nvgPathWinding(ctx, NVG_HOLE); nvgFillPaint(ctx, shadowPaint); nvgFill(ctx); if (!mTitle.empty()) { /* Draw header */ NVGpaint headerPaint = nvgLinearGradient( ctx, mPos.x(), mPos.y(), mPos.x(), mPos.y() + hh, mTheme->mWindowHeaderGradientTop, mTheme->mWindowHeaderGradientBot); nvgBeginPath(ctx); nvgRoundedRect(ctx, mPos.x(), mPos.y(), mSize.x(), hh, cr); nvgFillPaint(ctx, headerPaint); nvgFill(ctx); nvgBeginPath(ctx); nvgRoundedRect(ctx, mPos.x(), mPos.y(), mSize.x(), hh, cr); nvgStrokeColor(ctx, mTheme->mWindowHeaderSepTop); nvgSave(ctx); nvgIntersectScissor(ctx, mPos.x(), mPos.y(), mSize.x(), 0.5f); nvgStroke(ctx); nvgResetScissor(ctx); nvgRestore(ctx); nvgBeginPath(ctx); nvgMoveTo(ctx, mPos.x() + 0.5f, mPos.y() + hh - 1.5f); nvgLineTo(ctx, mPos.x() + mSize.x() - 0.5f, mPos.y() + hh - 1.5); nvgStrokeColor(ctx, mTheme->mWindowHeaderSepBot); nvgStroke(ctx); nvgFontSize(ctx, 18.0f); nvgFontFace(ctx, "sans-bold"); nvgTextAlign(ctx, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE); nvgFontBlur(ctx, 2); nvgFillColor(ctx, mTheme->mDropShadow); nvgText(ctx, mPos.x() + mSize.x() / 2, mPos.y() + hh / 2, mTitle.c_str(), nullptr); nvgFontBlur(ctx, 0); nvgFillColor(ctx, mFocused ? mTheme->mWindowTitleFocused : mTheme->mWindowTitleUnfocused); nvgText(ctx, mPos.x() + mSize.x() / 2, mPos.y() + hh / 2 - 1, mTitle.c_str(), nullptr); } nvgRestore(ctx); Widget::draw(ctx); }
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 if (mSpinnable && mMouseDownPos.x() != -1) nvgFillPaint(ctx, fg1); 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; } float spinArrowsWidth = 0.f; if (mSpinnable && !focused()) { spinArrowsWidth = 14.f; nvgFontFace(ctx, "icons"); nvgFontSize(ctx, ((mFontSize < 0) ? mTheme->mButtonFontSize : mFontSize) * 1.2f); bool spinning = mMouseDownPos.x() != -1; { bool hover = mMouseFocus && spinArea(mMousePos) == SpinArea::Top; nvgFillColor(ctx, (mEnabled && (hover || spinning)) ? mTheme->mTextColor : mTheme->mDisabledTextColor); auto icon = utf8(ENTYPO_ICON_CHEVRON_UP); nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); Vector2f iconPos(mPos.x() + 4.f, mPos.y() + mSize.y()/2.f - xSpacing/2.f); nvgText(ctx, iconPos.x(), iconPos.y(), icon.data(), nullptr); } { bool hover = mMouseFocus && spinArea(mMousePos) == SpinArea::Bottom; nvgFillColor(ctx, (mEnabled && (hover || spinning)) ? mTheme->mTextColor : mTheme->mDisabledTextColor); auto icon = utf8(ENTYPO_ICON_CHEVRON_DOWN); nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); Vector2f iconPos(mPos.x() + 4.f, mPos.y() + mSize.y()/2.f + xSpacing/2.f + 1.5f); nvgText(ctx, iconPos.x(), iconPos.y(), icon.data(), nullptr); } nvgFontSize(ctx, fontSize()); nvgFontFace(ctx, "sans"); } switch (mAlignment) { case Alignment::Left: nvgTextAlign(ctx, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE); drawPos.x() += xSpacing + spinArrowsWidth; 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 + spinArrowsWidth - 1.0f; float clipY = mPos.y() + 1.0f; float clipWidth = mSize.x() - unitWidth - spinArrowsWidth - 2 * xSpacing + 2.0f; float clipHeight = mSize.y() - 3.0f; nvgSave(ctx); nvgIntersectScissor(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); } } nvgRestore(ctx); }
JNIEXPORT void JNICALL Java_firststep_internal_NVG_intersectScissor (JNIEnv *e, jclass c, jlong ctx, jfloat x, jfloat y, jfloat w, jfloat h) { nvgIntersectScissor((NVGcontext*)ctx, x, y, w, h); }