awidgets
This commit is contained in:
parent
c87e5a25d5
commit
a55a5ec5cc
7 changed files with 151 additions and 51 deletions
|
|
@ -50,13 +50,21 @@ void Canvas::rect(const RectF& rec, const RGBA& col, halnf round) {
|
|||
nvgFill(mContext->vg);
|
||||
}
|
||||
|
||||
void Canvas::circle(const Vec2F& pos, halnf size, const RGBA& col) {
|
||||
nvgBeginPath(mContext->vg);
|
||||
nvgCircle(mContext->vg, pos.x, pos.y, size);
|
||||
|
||||
nvgFillColor(mContext->vg, { col.r, col.g, col.b, col.a });
|
||||
nvgFill(mContext->vg);
|
||||
}
|
||||
|
||||
void Canvas::pushClamp(const RectF& rec) {
|
||||
RectF intersection = rec;
|
||||
if (mScissors.size()) {
|
||||
mScissors.last().calcIntersection(rec, intersection);
|
||||
}
|
||||
nvgScissor(mContext->vg, intersection.x, intersection.y, intersection.z, intersection.w);
|
||||
mScissors.append(rec);
|
||||
mScissors.append(intersection);
|
||||
}
|
||||
|
||||
void Canvas::popClamp() {
|
||||
|
|
|
|||
|
|
@ -58,6 +58,7 @@ namespace tp {
|
|||
void pushClamp(const RectF& rec);
|
||||
void popClamp();
|
||||
void rect(const RectF& rec, const RGBA& col, halnf round = 0);
|
||||
void circle(const Vec2F& pos, halnf size, const RGBA& col);
|
||||
void text(const char*, const RectF&, halnf size, Align, halnf padding, const RGBA&);
|
||||
|
||||
ImageHandle createImageFromTextId(ualni id, Vec2F size);
|
||||
|
|
|
|||
|
|
@ -374,8 +374,8 @@ namespace tp {
|
|||
}
|
||||
|
||||
void clamp(const Vec& min, const Vec& max) {
|
||||
tp::clamp(x, min.x, max.x);
|
||||
tp::clamp(y, min.y, max.y);
|
||||
x = tp::clamp(x, min.x, max.x);
|
||||
y = tp::clamp(y, min.y, max.y);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -3,29 +3,23 @@
|
|||
namespace tp {
|
||||
|
||||
template <typename Events, typename Canvas>
|
||||
class SimpleWidget : public ScrollableWindow<Events, Canvas> {
|
||||
class SimpleWidget : public CollapsableMenu<Events, Canvas> {
|
||||
public:
|
||||
SimpleWidget() {
|
||||
this->addWidget(&mLabel);
|
||||
this->addWidget(&mButton);
|
||||
this->addWidget(&mSlider);
|
||||
this->addWidget(&mCollapsableMenu);
|
||||
this->addWidgetToMenu(&mInMenuButton1);
|
||||
this->addWidgetToMenu(&mInMenuButton2);
|
||||
|
||||
mCollapsableMenu.addWidgetToMenu(&mInMenuButton1);
|
||||
mCollapsableMenu.addWidgetToMenu(&mInMenuButton2);
|
||||
this->addWidgetToMenu(&mLabel);
|
||||
this->addWidgetToMenu(&mSlider);
|
||||
|
||||
mInMenuButton1.mLabel.mLabel = "Button1";
|
||||
mInMenuButton2.mLabel.mLabel = "Button2";
|
||||
|
||||
this->mArea.size = { 500, 500 };
|
||||
}
|
||||
|
||||
private:
|
||||
CollapsableMenu<Events, Canvas> mCollapsableMenu;
|
||||
ButtonWidget<EventHandler, Canvas> mInMenuButton1;
|
||||
ButtonWidget<EventHandler, Canvas> mInMenuButton2;
|
||||
|
||||
ButtonWidget<EventHandler, Canvas> mButton;
|
||||
LabelWidget<EventHandler, Canvas> mLabel;
|
||||
NamedSliderWidget<EventHandler, Canvas> mSlider;
|
||||
};
|
||||
|
|
@ -36,10 +30,17 @@ namespace tp {
|
|||
SimpleWidget2() {
|
||||
this->mChildWidgets.pushBack(&mFloating);
|
||||
mFloating.addWidgetToMenu(&mWidget);
|
||||
mFloating.addWidgetToMenu(&mWidget2);
|
||||
|
||||
// this->mChildWidgets.pushBack(&mFloating2);
|
||||
// mFloating2.addWidgetToMenu(&mWidget2);
|
||||
}
|
||||
|
||||
private:
|
||||
FloatingWidget<EventHandler, Canvas> mFloating;
|
||||
SimpleWidget<EventHandler, Canvas> mWidget;
|
||||
|
||||
FloatingWidget<EventHandler, Canvas> mFloating2;
|
||||
SimpleWidget<EventHandler, Canvas> mWidget2;
|
||||
};
|
||||
}
|
||||
|
|
@ -15,18 +15,10 @@ namespace tp {
|
|||
|
||||
void eventProcess(const Events&) override {
|
||||
if (mHeader.isReleased()) {
|
||||
mCollapsed = !mCollapsed;
|
||||
toggleCollapsed();
|
||||
}
|
||||
|
||||
mHeader.setArea(getHeaderRect());
|
||||
|
||||
mBody.mEnable = !mCollapsed;
|
||||
if (mCollapsed) {
|
||||
this->mArea.size.y = headerHeight;
|
||||
} else {
|
||||
this->mArea.size.y = headerHeight + getBodyRect().size.y + mPadding * 2;
|
||||
mBody.setArea(getBodyRect());
|
||||
}
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void eventDraw(Canvas& canvas) override {
|
||||
|
|
@ -43,6 +35,36 @@ namespace tp {
|
|||
mHeader.mLabel = string;
|
||||
}
|
||||
|
||||
void toggleCollapsed() {
|
||||
setCollapsed(!getCollapsed());
|
||||
}
|
||||
|
||||
void setCollapsed(bool collapsed) {
|
||||
if (mLocked) return;
|
||||
if (collapsed && !mCollapsed) mPrevHeight = this->mArea.size.y;
|
||||
if (!collapsed && mCollapsed) this->mArea.size.y = mPrevHeight;
|
||||
mCollapsed = collapsed;
|
||||
}
|
||||
|
||||
[[nodiscard]] bool getCollapsed() const{
|
||||
return mCollapsed;
|
||||
}
|
||||
|
||||
void updateGeometry() {
|
||||
mHeader.setArea(getHeaderRect());
|
||||
|
||||
mBody.mEnable = !mCollapsed;
|
||||
if (mCollapsed) {
|
||||
this->mArea.size.y = headerHeight;
|
||||
} else {
|
||||
if (mAdjustHeight) {
|
||||
this->mArea.size.y = headerHeight + getBodyRect().size.y + mPadding * 2;
|
||||
}
|
||||
|
||||
mBody.setArea(getBodyRect());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
RectF getHeaderRect() {
|
||||
RectF out = { this->mArea.pos, { this->mArea.size.x, headerHeight } };
|
||||
|
|
@ -51,9 +73,13 @@ namespace tp {
|
|||
|
||||
RectF getBodyRect() {
|
||||
RectF out = { { this->mArea.pos.x, this->mArea.pos.y + headerHeight },
|
||||
{ this->mArea.size.x, mBody.getContentSize() }
|
||||
{ this->mArea.size.x, this->mArea.size.y - headerHeight - mPadding }
|
||||
};
|
||||
|
||||
out.size.y -= mBorderSize * 2;
|
||||
|
||||
if (mAdjustHeight) out.size.y = mBody.getContentSize();
|
||||
|
||||
if (mBody.getContentSize()) {
|
||||
out = out.shrink(mPadding);
|
||||
out.size.y += mPadding * 2 + 1;
|
||||
|
|
@ -86,6 +112,10 @@ namespace tp {
|
|||
halnf mBorderSize = 0;
|
||||
halnf mPadding = 0;
|
||||
|
||||
halnf mPrevHeight = 200;
|
||||
|
||||
bool mCollapsed = true;
|
||||
bool mLocked = false;
|
||||
bool mAdjustHeight = true;
|
||||
};
|
||||
}
|
||||
|
|
@ -8,39 +8,90 @@ namespace tp {
|
|||
public:
|
||||
FloatingWidget() {
|
||||
this->mArea = { 0, 0, 300, 300 };
|
||||
}
|
||||
|
||||
virtual void procWrapper(const Events& events, const RectF& parentArea) override {
|
||||
if (!this->mEnable) return;
|
||||
|
||||
this->checkVisibility(events, parentArea);
|
||||
|
||||
if (!this->mVisible) return;
|
||||
|
||||
this->checkFocus(events);
|
||||
|
||||
this->checkClicked(events);
|
||||
|
||||
mParentArea = parentArea;
|
||||
this->eventProcess(events);
|
||||
|
||||
for (auto child : this->mChildWidgets) {
|
||||
child->procWrapper(events, this->getArea());
|
||||
}
|
||||
this->mAdjustHeight = false;
|
||||
}
|
||||
|
||||
void eventProcess(const Events& events) override {
|
||||
checkFloating(events);
|
||||
checkResizing(events);
|
||||
|
||||
mActionStartRelativePos = events.getPointer() - this->mArea.pos;
|
||||
|
||||
CollapsableMenu<Events, Canvas>::eventProcess(events);
|
||||
|
||||
if (this->mHeader.isHolding()) {
|
||||
this->mArea.pos += events.getPointerDelta();
|
||||
if (!this->mArea.isEnclosedIn(mParentArea)) {
|
||||
this->mArea.pos -= events.getPointerDelta();
|
||||
}
|
||||
|
||||
void eventDraw(Canvas& canvas) override {
|
||||
CollapsableMenu<Events, Canvas>::eventDraw(canvas);
|
||||
|
||||
if (!this->getCollapsed()) {
|
||||
auto rect = getResizeHandle();
|
||||
canvas.rect(rect, mResizeHandleColor, 0);
|
||||
canvas.circle(rect.pos - this->mBorderSize, rect.w, this->mMenuColor);
|
||||
}
|
||||
}
|
||||
|
||||
RectF mParentArea;
|
||||
void eventUpdateConfiguration(WidgetManager& wm) override {
|
||||
CollapsableMenu<Events, Canvas>::eventUpdateConfiguration(wm);
|
||||
|
||||
wm.setActiveId("FloatingWidget");
|
||||
|
||||
mResizeHandleSize = wm.getNumber("ResizeHandleSize", 15);
|
||||
mResizeHandleColor = wm.getColor("ResizeHandleColor", RGBA(0.16, 0.16, 0.16, 1.f));
|
||||
}
|
||||
|
||||
private:
|
||||
void checkFloating(const Events& events) {
|
||||
if (this->mHeader.isHolding() && events.getPointerDelta().length2() > 4 ) {
|
||||
mFloating = true;
|
||||
}
|
||||
|
||||
if (mFloating && this->mHeader.isReleased()) {
|
||||
mFloating = false;
|
||||
this->mHeader.clearEvents();
|
||||
}
|
||||
|
||||
if (mFloating) {
|
||||
auto relativePos = events.getPointer() - this->mArea.pos;
|
||||
this->mArea.pos += relativePos - mActionStartRelativePos;
|
||||
}
|
||||
}
|
||||
|
||||
void checkResizing(const Events& events) {
|
||||
if (this->getCollapsed()) return;
|
||||
|
||||
if (events.isPressed(InputID::MOUSE1) && getResizeHandle().isInside(events.getPointer())) {
|
||||
mResizing = true;
|
||||
}
|
||||
|
||||
if (events.isReleased(InputID::MOUSE1)) {
|
||||
mResizing = false;
|
||||
}
|
||||
|
||||
if (mResizing) {
|
||||
auto relativePos = events.getPointer() - this->mArea.pos;
|
||||
this->mArea.size += relativePos - mActionStartRelativePos;
|
||||
}
|
||||
|
||||
if (!this->mCollapsed) {
|
||||
this->mArea.size.clamp(mMinSize, { FLT_MAX, FLT_MAX });
|
||||
}
|
||||
}
|
||||
|
||||
RectF getResizeHandle() {
|
||||
auto size = Vec2F(mResizeHandleSize);
|
||||
auto pos = this->mArea.pos + this->mArea.size - size;
|
||||
return { pos, size };
|
||||
}
|
||||
|
||||
private:
|
||||
Vec2F mMinSize = { 70, 70 };
|
||||
|
||||
halnf mResizeHandleSize = 10;
|
||||
RGBA mResizeHandleColor = {};
|
||||
|
||||
bool mFloating = false;
|
||||
bool mResizing = false;
|
||||
|
||||
Vec2F mActionStartRelativePos = {};
|
||||
};
|
||||
}
|
||||
|
|
@ -134,8 +134,15 @@ namespace tp {
|
|||
bool isReleased() const { return mReleased; }
|
||||
bool isHolding() const { return mHolding; }
|
||||
|
||||
void clearEvents() {
|
||||
mReleased = false;
|
||||
mPressed = false;
|
||||
mHolding = false;
|
||||
}
|
||||
|
||||
public:
|
||||
RectF mArea;
|
||||
|
||||
List<Widget<Events, Canvas>*> mChildWidgets;
|
||||
|
||||
bool mVisible = false;
|
||||
|
|
@ -145,5 +152,7 @@ namespace tp {
|
|||
bool mHolding = false;
|
||||
bool mPressed = false;
|
||||
bool mReleased = false;
|
||||
|
||||
// Vec2F mPressedRelativeLocation;
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue