reactphysics3d/testbed/nanogui/src/popup.cpp

104 lines
2.9 KiB
C++

/*
src/popup.cpp -- Simple popup widget which is attached to another given
window (can be nested)
NanoGUI was developed by Wenzel Jakob <wenzel.jakob@epfl.ch>.
The widget drawing code is based on the NanoVG demo application
by Mikko Mononen.
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE.txt file.
*/
#include <nanogui/popup.h>
#include <nanogui/theme.h>
#include <nanogui/opengl.h>
#include <nanogui/serializer/core.h>
NAMESPACE_BEGIN(nanogui)
Popup::Popup(Widget *parent, Window *parentWindow)
: Window(parent, ""), mParentWindow(parentWindow),
mAnchorPos(Vector2i::Zero()), mAnchorHeight(30), mSide(Side::Right) {
}
void Popup::performLayout(NVGcontext *ctx) {
if (mLayout || mChildren.size() != 1) {
Widget::performLayout(ctx);
} else {
mChildren[0]->setPosition(Vector2i::Zero());
mChildren[0]->setSize(mSize);
mChildren[0]->performLayout(ctx);
}
if (mSide == Side::Left)
mAnchorPos[0] -= size()[0];
}
void Popup::refreshRelativePlacement() {
mParentWindow->refreshRelativePlacement();
mVisible &= mParentWindow->visibleRecursive();
mPos = mParentWindow->position() + mAnchorPos - Vector2i(0, mAnchorHeight);
}
void Popup::draw(NVGcontext* ctx) {
refreshRelativePlacement();
if (!mVisible)
return;
int ds = mTheme->mWindowDropShadowSize, cr = mTheme->mWindowCornerRadius;
nvgSave(ctx);
nvgResetScissor(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);
/* Draw window */
nvgBeginPath(ctx);
nvgRoundedRect(ctx, mPos.x(), mPos.y(), mSize.x(), mSize.y(), cr);
Vector2i base = mPos + Vector2i(0, mAnchorHeight);
int sign = -1;
if (mSide == Side::Left) {
base.x() += mSize.x();
sign = 1;
}
nvgMoveTo(ctx, base.x() + 15*sign, base.y());
nvgLineTo(ctx, base.x() - 1*sign, base.y() - 15);
nvgLineTo(ctx, base.x() - 1*sign, base.y() + 15);
nvgFillColor(ctx, mTheme->mWindowPopup);
nvgFill(ctx);
nvgRestore(ctx);
Widget::draw(ctx);
}
void Popup::save(Serializer &s) const {
Window::save(s);
s.set("anchorPos", mAnchorPos);
s.set("anchorHeight", mAnchorHeight);
s.set("side", mSide);
}
bool Popup::load(Serializer &s) {
if (!Window::load(s)) return false;
if (!s.get("anchorPos", mAnchorPos)) return false;
if (!s.get("anchorHeight", mAnchorHeight)) return false;
if (!s.get("side", mSide)) return false;
return true;
}
NAMESPACE_END(nanogui)