gui updates
This commit is contained in:
parent
a55a5ec5cc
commit
4a557d7e5c
42 changed files with 1179 additions and 962 deletions
40
Widgets/private/ButtonWidget.cpp
Normal file
40
Widgets/private/ButtonWidget.cpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
#include "ButtonWidget.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
ButtonWidget::ButtonWidget() {
|
||||
this->setArea({ 0, 0, 100, 30 });
|
||||
this->mChildWidgets.pushBack(&mLabel);
|
||||
}
|
||||
|
||||
ButtonWidget::ButtonWidget(const std::string& label, const tp::RectF& aArea) {
|
||||
this->setArea(aArea);
|
||||
mLabel.mLabel = label;
|
||||
this->mChildWidgets.pushBack(&mLabel);
|
||||
}
|
||||
|
||||
bool ButtonWidget::isFired() { return this->isReleased(); }
|
||||
|
||||
void ButtonWidget::eventProcess(const Events&) { mLabel.setArea(this->mArea); }
|
||||
|
||||
void ButtonWidget::eventDraw(Canvas& canvas) {
|
||||
if (this->isHolding()) {
|
||||
canvas.rect(this->mArea, pressedColor, rounding);
|
||||
} else if (this->isFocus()) {
|
||||
canvas.rect(this->mArea, hoveredColor, rounding);
|
||||
} else {
|
||||
canvas.rect(this->mArea, accentColor, rounding);
|
||||
}
|
||||
}
|
||||
|
||||
void ButtonWidget::setLabel(const std::string& string) { mLabel.mLabel = string; }
|
||||
|
||||
void ButtonWidget::eventUpdateConfiguration(WidgetManager& wm) {
|
||||
wm.setActiveId("Button");
|
||||
|
||||
pressedColor = wm.getColor("Pressed", "Action");
|
||||
hoveredColor = wm.getColor("Hovered", "Interaction");
|
||||
accentColor = wm.getColor("Default", "Accent");
|
||||
rounding = wm.getNumber("Rounding", "Rounding");
|
||||
}
|
||||
84
Widgets/private/CollapsableMenu.cpp
Normal file
84
Widgets/private/CollapsableMenu.cpp
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
|
||||
#include "CollapsableMenu.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
CollapsableMenu::CollapsableMenu() {
|
||||
this->mChildWidgets.pushBack(&mHeader);
|
||||
this->mChildWidgets.pushBack(&mBody);
|
||||
}
|
||||
|
||||
void CollapsableMenu::eventProcess(const Events&) {
|
||||
if (mHeader.isReleased()) {
|
||||
toggleCollapsed();
|
||||
}
|
||||
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void CollapsableMenu::eventDraw(Canvas& canvas) {
|
||||
canvas.rect(this->mArea, mBorderColor, rounding);
|
||||
canvas.rect(this->mArea.shrink(mBorderSize), mMenuColor, rounding);
|
||||
}
|
||||
|
||||
void CollapsableMenu::addWidgetToMenu(Widget* widget) { mBody.addWidget(widget); }
|
||||
|
||||
void CollapsableMenu::setLabel(const std::string& string) { mHeader.mLabel = string; }
|
||||
|
||||
void CollapsableMenu::toggleCollapsed() { setCollapsed(!getCollapsed()); }
|
||||
|
||||
void CollapsableMenu::setCollapsed(bool collapsed) {
|
||||
if (mLocked) return;
|
||||
if (collapsed && !mCollapsed) mPrevHeight = this->mArea.size.y;
|
||||
if (!collapsed && mCollapsed) this->mArea.size.y = mPrevHeight;
|
||||
mCollapsed = collapsed;
|
||||
}
|
||||
|
||||
bool CollapsableMenu::getCollapsed() const { return mCollapsed; }
|
||||
|
||||
void CollapsableMenu::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());
|
||||
}
|
||||
}
|
||||
|
||||
RectF CollapsableMenu::getHeaderRect() {
|
||||
RectF out = { this->mArea.pos, { this->mArea.size.x, headerHeight } };
|
||||
return out.shrink(mPadding);
|
||||
}
|
||||
|
||||
RectF CollapsableMenu::getBodyRect() {
|
||||
RectF out = { { this->mArea.pos.x, this->mArea.pos.y + headerHeight },
|
||||
{ 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;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void CollapsableMenu::eventUpdateConfiguration(WidgetManager& wm) {
|
||||
wm.setActiveId("CollapsableMenu");
|
||||
|
||||
headerHeight = wm.getNumber("HeaderHeight", 35);
|
||||
mMenuColor = wm.getColor("MenuColor", RGBA(0, 0, 0, 1.f));
|
||||
rounding = wm.getNumber("Rounding", "Rounding");
|
||||
mBorderColor = wm.getColor("BorderColor", RGBA(0.16, 0.16, 0.16, 1.f));
|
||||
mBorderSize = wm.getNumber("BorderSize", 2.f);
|
||||
mPadding = wm.getNumber("Padding", "Padding");
|
||||
}
|
||||
80
Widgets/private/FloatingWidget.cpp
Normal file
80
Widgets/private/FloatingWidget.cpp
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
|
||||
#include "FloatingWidget.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
FloatingWidget::FloatingWidget() {
|
||||
this->mArea = { 0, 0, 300, 300 };
|
||||
this->mAdjustHeight = false;
|
||||
}
|
||||
|
||||
void FloatingWidget::eventProcess(const Events& events) {
|
||||
checkFloating(events);
|
||||
checkResizing(events);
|
||||
|
||||
mActionStartRelativePos = events.getPointer() - this->mArea.pos;
|
||||
|
||||
CollapsableMenu::eventProcess(events);
|
||||
}
|
||||
|
||||
void FloatingWidget::eventDraw(Canvas& canvas) {
|
||||
CollapsableMenu::eventDraw(canvas);
|
||||
|
||||
if (!this->getCollapsed()) {
|
||||
auto rect = getResizeHandle();
|
||||
canvas.rect(rect, mResizeHandleColor, 0);
|
||||
canvas.circle(rect.pos - this->mBorderSize, rect.w, this->mMenuColor);
|
||||
}
|
||||
}
|
||||
|
||||
void FloatingWidget::eventUpdateConfiguration(WidgetManager& wm) {
|
||||
CollapsableMenu::eventUpdateConfiguration(wm);
|
||||
|
||||
wm.setActiveId("FloatingWidget");
|
||||
|
||||
mResizeHandleSize = wm.getNumber("ResizeHandleSize", 15);
|
||||
mResizeHandleColor = wm.getColor("ResizeHandleColor", RGBA(0.16, 0.16, 0.16, 1.f));
|
||||
}
|
||||
|
||||
void FloatingWidget::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 FloatingWidget::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 FloatingWidget::getResizeHandle() {
|
||||
auto size = Vec2F(mResizeHandleSize);
|
||||
auto pos = this->mArea.pos + this->mArea.size - size;
|
||||
return { pos, size };
|
||||
}
|
||||
17
Widgets/private/LabelWidget.cpp
Normal file
17
Widgets/private/LabelWidget.cpp
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
#include "LabelWidget.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
LabelWidget::LabelWidget() { this->mArea = { 0, 0, 100, 30 }; }
|
||||
|
||||
void LabelWidget::eventDraw(Canvas& canvas) {
|
||||
canvas.text(mLabel.c_str(), this->mArea, fontSize, Canvas::LC, padding, fontColor);
|
||||
}
|
||||
|
||||
void LabelWidget::eventUpdateConfiguration(WidgetManager& wm) {
|
||||
wm.setActiveId("Label");
|
||||
|
||||
fontSize = wm.getNumber("Size", "FontSize");
|
||||
padding = wm.getNumber("Padding", "Padding");
|
||||
fontColor = wm.getColor("Default", "Front");
|
||||
}
|
||||
166
Widgets/private/ScrollableWidget.cpp
Normal file
166
Widgets/private/ScrollableWidget.cpp
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
#include "ScrollableWidget.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
ScrollBarWidget::ScrollBarWidget() = default;
|
||||
|
||||
void ScrollBarWidget::eventProcess(const Events& events) {
|
||||
auto area = getHandle();
|
||||
mHovered = getHandleHandle().isInside(events.getPointer());
|
||||
|
||||
if (mSizeFraction > 1.f) {
|
||||
mPositionFraction = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (events.getScrollY() != 0) {
|
||||
auto offset = events.getScrollY() < 0 ? 1.0f : -1.0f;
|
||||
mPositionFraction += mSizeFraction * offset * 0.3f;
|
||||
mPositionFraction = tp::clamp(mPositionFraction, 0.f, 1.f - mSizeFraction);
|
||||
}
|
||||
|
||||
if (events.isPressed(InputID::MOUSE1) && area.isInside(events.getPointer())) {
|
||||
mIsScrolling = true;
|
||||
} else if (events.isReleased(InputID::MOUSE1)) {
|
||||
mIsScrolling = false;
|
||||
}
|
||||
|
||||
if (mIsScrolling) {
|
||||
tp::halnf pos = events.getPointer().y;
|
||||
pos = (pos - area.y - mSizeFraction * area.w / 2.f) / area.w;
|
||||
mPositionFraction = tp::clamp(pos, 0.f, 1.f - mSizeFraction);
|
||||
}
|
||||
|
||||
mPositionFraction = tp::clamp(mPositionFraction, 0.f, 1.f - mSizeFraction);
|
||||
}
|
||||
|
||||
void ScrollBarWidget::eventDraw(Canvas& canvas) {
|
||||
auto area = getHandle();
|
||||
|
||||
if (mSizeFraction > 1.f) return;
|
||||
// if (!areaParent.isOverlap(getHandle())) return;
|
||||
|
||||
tp::RGBA col = mHandleColor;
|
||||
|
||||
if (mIsScrolling) {
|
||||
col = mScrollingColor;
|
||||
} else if (mHovered) {
|
||||
col = mHoveredColor;
|
||||
}
|
||||
|
||||
canvas.rect(area, mDefaultColor, mRounding);
|
||||
canvas.rect(getHandleHandle(), col, mRounding);
|
||||
}
|
||||
|
||||
RectF ScrollBarWidget::getHandleHandle() const {
|
||||
auto area = getHandle();
|
||||
auto sliderSize = tp::clamp(area.w * mSizeFraction, mMinSize * 2, area.w);
|
||||
auto diffSize = sliderSize - area.w * mSizeFraction;
|
||||
return { area.x, area.y + (area.w - diffSize) * mPositionFraction, area.z, sliderSize };
|
||||
}
|
||||
|
||||
RectF ScrollBarWidget::getViewport() const {
|
||||
if (mSizeFraction > 1.f) {
|
||||
return this->mArea;
|
||||
}
|
||||
return { this->mArea.x, this->mArea.y, this->mArea.z - mHandleSize, this->mArea.w };
|
||||
}
|
||||
|
||||
RectF ScrollBarWidget::getHandle() const {
|
||||
return { this->mArea.x + this->mArea.z - mHandleSize + mPadding,
|
||||
this->mArea.y + mPadding,
|
||||
mHandleSize - mPadding * 2,
|
||||
this->mArea.w - mPadding * 2 };
|
||||
}
|
||||
|
||||
void ScrollBarWidget::eventUpdateConfiguration(WidgetManager& wm) {
|
||||
wm.setActiveId("Scrollbar");
|
||||
|
||||
mDefaultColor = wm.getColor("Default", "Base");
|
||||
mHandleColor = wm.getColor("Handle", "Accent");
|
||||
mHoveredColor = wm.getColor("Hovered", "Interaction");
|
||||
mScrollingColor = wm.getColor("Scrolling", "Action");
|
||||
mPadding = wm.getNumber("Padding", "Padding");
|
||||
mHandleSize = wm.getNumber("HandleSize", 20.f);
|
||||
mMinSize = wm.getNumber("MinSize", 20.f);
|
||||
mRounding = wm.getNumber("Rounding", "Rounding");
|
||||
}
|
||||
|
||||
ScrollableWindow::ScrollableWindow() {
|
||||
this->mChildWidgets.pushBack(&mScroller);
|
||||
this->mChildWidgets.pushBack(&mContentWidget);
|
||||
}
|
||||
|
||||
ScrollableWindow::~ScrollableWindow() = default;
|
||||
|
||||
void ScrollableWindow::eventProcess(const Events& events) {
|
||||
List<Widget*>& content = mContentWidget.mChildWidgets;
|
||||
|
||||
updateContents(content);
|
||||
updateContentSize(content);
|
||||
|
||||
const auto padding = mPadding;
|
||||
|
||||
mScroller.mSizeFraction = mContentWidget.mArea.w / mContentSize;
|
||||
mScroller.setArea(this->mArea);
|
||||
mContentWidget.setArea(mScroller.getViewport());
|
||||
|
||||
if (mScroller.mSizeFraction > 1.f) {
|
||||
setOffset(content, 0);
|
||||
} else {
|
||||
setOffset(content, (-mScroller.mPositionFraction) * mContentSize);
|
||||
}
|
||||
|
||||
for (auto widget : content) {
|
||||
widget->setArea({ mContentWidget.mArea.x + padding,
|
||||
mContentWidget.mArea.y + widget->mArea.y,
|
||||
mScroller.getViewport().z - padding * 2,
|
||||
widget->mArea.w });
|
||||
}
|
||||
}
|
||||
|
||||
void ScrollableWindow::addWidget(Widget* widget) { mContentWidget.mChildWidgets.pushBack(widget); }
|
||||
void ScrollableWindow::clearContent() { mContentWidget.mChildWidgets.removeAll(); }
|
||||
List<Widget*>& ScrollableWindow::getContent() { return mContentWidget.mChildWidgets; }
|
||||
|
||||
void ScrollableWindow::eventUpdateConfiguration(WidgetManager& wm) {
|
||||
wm.setActiveId("ScrollableWidget");
|
||||
mPadding = wm.getNumber("Padding", "Padding");
|
||||
}
|
||||
|
||||
[[nodiscard]] halnf ScrollableWindow::getContentSize() const { return mContentSize; }
|
||||
|
||||
void ScrollableWindow::updateContents(List<Widget*>& contentWidgets) {
|
||||
if (!contentWidgets.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const halnf offset = contentWidgets.first()->mArea.y + mPadding;
|
||||
|
||||
halnf start = 0;
|
||||
for (auto widget : contentWidgets) {
|
||||
widget->mArea.y = start;
|
||||
start += widget->mArea.w + mPadding;
|
||||
}
|
||||
|
||||
for (auto widget : contentWidgets) {
|
||||
widget->mArea.y += offset;
|
||||
}
|
||||
}
|
||||
|
||||
void ScrollableWindow::updateContentSize(List<Widget*>& contentWidgets) {
|
||||
mContentSize = 0;
|
||||
if (contentWidgets.size()) {
|
||||
mContentSize = contentWidgets.last()->mArea.y - contentWidgets.first()->mArea.y;
|
||||
mContentSize += contentWidgets.last()->mArea.w;
|
||||
mContentSize += 2 * mPadding;
|
||||
}
|
||||
}
|
||||
|
||||
void ScrollableWindow::setOffset(List<Widget*>& contentWidgets, const halnf offset) {
|
||||
if (!contentWidgets.size()) return;
|
||||
auto newOffset = offset - contentWidgets.first()->mArea.y + mPadding;
|
||||
for (auto widget : contentWidgets) {
|
||||
widget->mArea.y += newOffset;
|
||||
}
|
||||
}
|
||||
60
Widgets/private/SliderWidget.cpp
Normal file
60
Widgets/private/SliderWidget.cpp
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#include "SliderWidget.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
SliderWidget::SliderWidget() = default;
|
||||
|
||||
void SliderWidget::eventProcess(const Events& events) {
|
||||
if (this->isPressed()) {
|
||||
mIsSliding = true;
|
||||
} else if (events.isReleased(InputID::MOUSE1)) {
|
||||
mIsSliding = false;
|
||||
}
|
||||
|
||||
if (mIsSliding) {
|
||||
mFactor = (events.getPointer().x - this->mArea.x - handleSize / 2.f) / (this->mArea.z - handleSize);
|
||||
}
|
||||
|
||||
mFactor = tp::clamp(mFactor, 0.f, 1.f);
|
||||
}
|
||||
|
||||
void SliderWidget::eventDraw(Canvas& canvas) {
|
||||
canvas.rect(this->mArea, defaultColor, rounding);
|
||||
canvas.rect(getHandle(), handleColor, rounding);
|
||||
}
|
||||
|
||||
RectF SliderWidget::getHandle() const {
|
||||
const auto left = this->mArea.x + (this->mArea.z - handleSize) * mFactor;
|
||||
return { left, this->mArea.y, handleSize, this->mArea.w };
|
||||
}
|
||||
|
||||
void SliderWidget::eventUpdateConfiguration(WidgetManager& wm) {
|
||||
wm.setActiveId("Slider");
|
||||
defaultColor = wm.getColor("Default", "Base");
|
||||
handleColor = wm.getColor("Handle", "Accent");
|
||||
handleSize = wm.getNumber("HandleSize", 20.f);
|
||||
rounding = wm.getNumber("Rounding", "Rounding");
|
||||
}
|
||||
|
||||
NamedSliderWidget::NamedSliderWidget(const char* name) {
|
||||
mLabel.mLabel = name;
|
||||
this->mArea = { 0, 0, 100, 30 };
|
||||
|
||||
this->mChildWidgets.pushBack(&mSlider);
|
||||
this->mChildWidgets.pushBack(&mLabel);
|
||||
}
|
||||
|
||||
void NamedSliderWidget::eventProcess(const Events& events) {
|
||||
const auto widthFirst = this->mArea.z * mFactor;
|
||||
const auto widthSecond = this->mArea.z * (1.f - mFactor);
|
||||
|
||||
RectF rec = this->mArea;
|
||||
rec.size.x = widthFirst;
|
||||
|
||||
mLabel.setArea(rec);
|
||||
|
||||
rec.pos.x += widthFirst;
|
||||
rec.size.x = widthSecond;
|
||||
|
||||
mSlider.setArea(rec);
|
||||
}
|
||||
135
Widgets/private/SplitViewWidget.cpp
Normal file
135
Widgets/private/SplitViewWidget.cpp
Normal file
|
|
@ -0,0 +1,135 @@
|
|||
#include "SplitViewWidget.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
SplitView::SplitView() {
|
||||
mLeftLabel.mLabel = "Left";
|
||||
mRightLabel.mLabel = "Right";
|
||||
|
||||
this->mChildWidgets.pushBack(&mLeftLabel);
|
||||
this->mChildWidgets.pushBack(&mRightLabel);
|
||||
}
|
||||
|
||||
void SplitView::eventProcess(const Events& events) {
|
||||
mIsHover = getHandle().isInside(events.getPointer());
|
||||
|
||||
if (events.isPressed(InputID::MOUSE1) && mIsHover) {
|
||||
mResizeInProcess = true;
|
||||
} else if (events.isReleased(InputID::MOUSE1)) {
|
||||
mResizeInProcess = false;
|
||||
}
|
||||
|
||||
if (mResizeInProcess) {
|
||||
halnf pos = events.getPointer().x;
|
||||
auto diff = pos - (this->mArea.x + mFactor * this->mArea.z);
|
||||
mFactor += diff / this->mArea.z;
|
||||
}
|
||||
|
||||
mFactor = tp::clamp(mFactor, mMinSize / this->mArea.z, 1 - mMinSize / this->mArea.z);
|
||||
|
||||
if (mMinSize * 2.f > this->mArea.z) {
|
||||
mFactor = 0.5f;
|
||||
}
|
||||
|
||||
mLeftLabel.mEnable = mHeaders && mCollapsedSide != LEFT;
|
||||
mRightLabel.mEnable = mHeaders && mCollapsedSide != RIGHT;
|
||||
|
||||
if (mHeaders) {
|
||||
mLeftLabel.setArea(getFirstHeader());
|
||||
mRightLabel.setArea(getSecondHeader());
|
||||
}
|
||||
|
||||
if (mLeftLabel.isReleased()) {
|
||||
mCollapsedSide = (mCollapsedSide == NONE) ? RIGHT : NONE;
|
||||
}
|
||||
|
||||
if (mRightLabel.isReleased()) {
|
||||
mCollapsedSide = (mCollapsedSide == NONE) ? LEFT : NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void SplitView::eventDraw(Canvas& canvas) {
|
||||
if (mResizeInProcess) canvas.rect(getHandle(), mResizingColor);
|
||||
else if (mIsHover) canvas.rect(getHandle(), mHoveredColor);
|
||||
else canvas.rect(getHandle(), mHandleColor);
|
||||
}
|
||||
|
||||
bool SplitView::getFirstEnabled() const { return mCollapsedSide != CollapsedSize::LEFT; }
|
||||
|
||||
bool SplitView::getSecondEnabled() const { return mCollapsedSide != CollapsedSize::RIGHT; }
|
||||
|
||||
RectF SplitView::getFirst() const {
|
||||
Rect out = { this->mArea.x, this->mArea.y, mFactor * this->mArea.z - mHandleSize / 2.f, this->mArea.w };
|
||||
|
||||
if (mCollapsedSide == RIGHT) {
|
||||
out.pos.x = this->mArea.pos.x;
|
||||
out.size.x = this->mArea.size.x;
|
||||
}
|
||||
|
||||
if (mHeaders) {
|
||||
out.pos.y += mHeaderSize;
|
||||
out.size.y -= mHeaderSize;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
RectF SplitView::getFirstHeader() const {
|
||||
Rect out = { this->mArea.x, this->mArea.y, mFactor * this->mArea.z - mHandleSize / 2.f, mHeaderSize };
|
||||
|
||||
if (mCollapsedSide == RIGHT) {
|
||||
out.pos.x = this->mArea.pos.x;
|
||||
out.size.x = this->mArea.size.x;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
RectF SplitView::getSecondHeader() const {
|
||||
RectF out = { this->mArea.x + mFactor * this->mArea.z + mHandleSize / 2.f,
|
||||
this->mArea.y,
|
||||
(1.f - mFactor) * this->mArea.z - mHandleSize / 2.f,
|
||||
mHeaderSize };
|
||||
|
||||
if (mCollapsedSide == LEFT) {
|
||||
out.pos.x = this->mArea.pos.x;
|
||||
out.size.x = this->mArea.size.x;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
RectF SplitView::getSecond() const {
|
||||
RectF out = { this->mArea.x + mFactor * this->mArea.z + mHandleSize / 2.f,
|
||||
this->mArea.y,
|
||||
(1.f - mFactor) * this->mArea.z - mHandleSize / 2.f,
|
||||
this->mArea.w };
|
||||
|
||||
if (mCollapsedSide == LEFT) {
|
||||
out.pos.x = this->mArea.pos.x;
|
||||
out.size.x = this->mArea.size.x;
|
||||
}
|
||||
|
||||
if (mHeaders) {
|
||||
out.pos.y += mHeaderSize;
|
||||
out.size.y -= mHeaderSize;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
RectF SplitView::getHandle() const {
|
||||
if (mCollapsedSide != NONE) return {};
|
||||
return { this->mArea.x + mFactor * this->mArea.z - mHandleSize / 2.f, this->mArea.y, mHandleSize, this->mArea.w };
|
||||
}
|
||||
|
||||
void SplitView::eventUpdateConfiguration(WidgetManager& wm) {
|
||||
wm.setActiveId("SplitView");
|
||||
|
||||
mHandleColor = wm.getColor("Handle", "Accent");
|
||||
mHoveredColor = wm.getColor("Hovered", "Interaction");
|
||||
mResizingColor = wm.getColor("Resizing", "Action");
|
||||
mMinSize = wm.getNumber("Min", 200.f);
|
||||
mHandleSize = wm.getNumber("HandleSize", 7.f);
|
||||
mHeaderSize = wm.getNumber("HeaderSize", 30.f);
|
||||
}
|
||||
57
Widgets/private/TextInputWidget.cpp
Normal file
57
Widgets/private/TextInputWidget.cpp
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#include "TextInputWidget.hpp"
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_internal.h"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
TextInputWidget::TextInputWidget() = default;
|
||||
|
||||
void TextInputWidget::eventDraw(Canvas&) {
|
||||
nChanged = false;
|
||||
|
||||
const auto col = mAccentColor;
|
||||
const auto colSel = mHoveredColor;
|
||||
|
||||
ImGui::GetStyle().Colors[ImGuiCol_FrameBg] = { col.r, col.g, col.b, col.a };
|
||||
ImGui::GetStyle().Colors[ImGuiCol_TextSelectedBg] = { colSel.r, colSel.g, colSel.b, colSel.a };
|
||||
|
||||
ImGui::SetNextWindowPos({ this->mArea.x, this->mArea.y });
|
||||
ImGui::SetNextWindowSize({ this->mArea.z, this->mArea.w });
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 0, 0 });
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, mRounding * 1.5f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { mPadding, mPadding });
|
||||
|
||||
// ImGui::PushID((int) alni(this));
|
||||
ImGui::Begin(
|
||||
mId.c_str(),
|
||||
0,
|
||||
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoBackground |
|
||||
ImGuiWindowFlags_NoResize
|
||||
);
|
||||
|
||||
if (mMultiline) {
|
||||
if (ImGui::InputTextMultiline("input", mBuff, mMaxBufferSize, { this->mArea.z, this->mArea.w })) {
|
||||
mValue = mBuff;
|
||||
nChanged = true;
|
||||
}
|
||||
} else {
|
||||
if (ImGui::InputTextEx("input", mId.c_str(), mBuff, mMaxBufferSize, { this->mArea.z, this->mArea.w }, 0)) {
|
||||
mValue = mBuff;
|
||||
nChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar(3);
|
||||
}
|
||||
|
||||
void TextInputWidget::eventUpdateConfiguration(WidgetManager& wm) {
|
||||
wm.setActiveId("TextInput");
|
||||
|
||||
mAccentColor = wm.getColor("Accent", "Accent");
|
||||
mBaseColor = wm.getColor("Base", "Base");
|
||||
mRounding = wm.getNumber("Rounding", "Rounding");
|
||||
mHoveredColor = wm.getColor("Hovered", "Accent");
|
||||
mPadding = wm.getNumber("Padding", "Padding");
|
||||
}
|
||||
132
Widgets/private/WidgetBase.cpp
Normal file
132
Widgets/private/WidgetBase.cpp
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
#include "WidgetBase.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
Widget::Widget() { mArea = { 0, 0, 100, 100 }; }
|
||||
|
||||
Widget::~Widget() = default;
|
||||
|
||||
void Widget::procWrapper(const Events& events, const RectF& parentArea) {
|
||||
if (!mEnable) return;
|
||||
|
||||
checkVisibility(events, parentArea);
|
||||
|
||||
if (!mVisible) return;
|
||||
|
||||
checkFocus(events);
|
||||
|
||||
checkClicked(events);
|
||||
|
||||
eventProcess(events);
|
||||
|
||||
for (auto child : mChildWidgets) {
|
||||
child->procWrapper(events, getArea());
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::drawWrapper(Canvas& canvas) {
|
||||
if (!mEnable || !mVisible) return;
|
||||
|
||||
eventDraw(canvas);
|
||||
|
||||
// draw child widgets
|
||||
canvas.pushClamp(this->mArea);
|
||||
for (auto child : mChildWidgets) {
|
||||
child->drawWrapper(canvas);
|
||||
}
|
||||
canvas.popClamp();
|
||||
}
|
||||
|
||||
void Widget::updateConfigWrapper(WidgetManager& wm) {
|
||||
wm.setActiveId("Global");
|
||||
|
||||
eventUpdateConfiguration(wm);
|
||||
|
||||
for (auto child : mChildWidgets) {
|
||||
child->updateConfigWrapper(wm);
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::eventProcess(const Events& events) {}
|
||||
void Widget::eventDraw(Canvas& canvas) {}
|
||||
void Widget::eventUpdateConfiguration(WidgetManager& wm) {}
|
||||
|
||||
void Widget::eventVisible(const Events& events) {}
|
||||
void Widget::eventNotVisible(const Events& events) {}
|
||||
|
||||
void Widget::eventFocusEnter(const Events& events) {}
|
||||
void Widget::eventFocusLeave(const Events& events) {}
|
||||
|
||||
void Widget::eventPressed(const Events& events) {}
|
||||
void Widget::eventReleased(const Events& events) {}
|
||||
|
||||
void Widget::checkVisibility(const Events& events, const RectF& parentArea) {
|
||||
const bool currentVisibility = parentArea.isOverlap(getArea());
|
||||
|
||||
if (currentVisibility != mVisible) {
|
||||
if (currentVisibility) eventVisible(events);
|
||||
else eventNotVisible(events);
|
||||
}
|
||||
|
||||
mVisible = currentVisibility;
|
||||
|
||||
if (!mVisible) {
|
||||
mHolding = false;
|
||||
mPressed = false;
|
||||
mReleased = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::checkFocus(const Events& events) {
|
||||
const bool currentFocus = getArea().isInside(events.getPointer());
|
||||
|
||||
if (currentFocus != mInFocus) {
|
||||
if (currentFocus) eventFocusEnter(events);
|
||||
else eventFocusLeave(events);
|
||||
}
|
||||
|
||||
mInFocus = currentFocus;
|
||||
|
||||
if (!mInFocus) {
|
||||
mHolding = false;
|
||||
mPressed = false;
|
||||
mReleased = false;
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::checkClicked(const Events& events) {
|
||||
mPressed = false;
|
||||
mReleased = false;
|
||||
|
||||
if (!mInFocus) return;
|
||||
|
||||
if (mHolding) {
|
||||
if (events.isReleased(InputID::MOUSE1)) {
|
||||
eventReleased(events);
|
||||
mReleased = true;
|
||||
mHolding = false;
|
||||
}
|
||||
} else {
|
||||
if (events.isPressed(InputID::MOUSE1)) {
|
||||
eventPressed(events);
|
||||
mHolding = true;
|
||||
mPressed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::setEnable(bool enable) { mEnable = enable; }
|
||||
void Widget::setVisible(bool visible) { mVisible = visible; }
|
||||
void Widget::setArea(const RectF& area) { mArea = area; }
|
||||
|
||||
const RectF& Widget::getArea() const { return mArea; }
|
||||
bool Widget::isFocus() const { return mInFocus; }
|
||||
bool Widget::isPressed() const { return mPressed; }
|
||||
bool Widget::isReleased() const { return mReleased; }
|
||||
bool Widget::isHolding() const { return mHolding; }
|
||||
|
||||
void Widget::clearEvents() {
|
||||
mReleased = false;
|
||||
mPressed = false;
|
||||
mHolding = false;
|
||||
}
|
||||
74
Widgets/private/WidgetManager.cpp
Normal file
74
Widgets/private/WidgetManager.cpp
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#include "WidgetManager.hpp"
|
||||
|
||||
using namespace tp;
|
||||
|
||||
WidgetManager::WidgetManager() { initGlobalParameters(); }
|
||||
WidgetManager::~WidgetManager() { mConfigurations.removeAll(); }
|
||||
|
||||
const RGBA& WidgetManager::getColor(const std::string& parameterId, const RGBA& defaultValue) {
|
||||
WidgetConfig& config = getWidgetConfig(mActiveId);
|
||||
Parameter& parameter = getParameter(config, parameterId, Parameter(defaultValue));
|
||||
return parameter.color;
|
||||
}
|
||||
|
||||
const RGBA& WidgetManager::getColor(const std::string& parameterId, const char* globalRef) {
|
||||
WidgetConfig& config = getWidgetConfig(mActiveId);
|
||||
Parameter& parameter = getParameter(config, parameterId, Parameter(globalRef, Parameter::COL));
|
||||
return parameter.color;
|
||||
}
|
||||
|
||||
halnf WidgetManager::getNumber(const std::string& parameterId, halnf defaultValue) {
|
||||
WidgetConfig& config = getWidgetConfig(mActiveId);
|
||||
Parameter& parameter = getParameter(config, parameterId, Parameter(defaultValue));
|
||||
return parameter.value;
|
||||
}
|
||||
|
||||
halnf WidgetManager::getNumber(const std::string& parameterId, const char* globalRef) {
|
||||
WidgetConfig& config = getWidgetConfig(mActiveId);
|
||||
Parameter& parameter = getParameter(config, parameterId, Parameter(globalRef, Parameter::VAL));
|
||||
return parameter.value;
|
||||
}
|
||||
|
||||
void WidgetManager::setActiveId(const std::string& id) { mActiveId = id; }
|
||||
|
||||
WidgetConfig& WidgetManager::getWidgetConfig(const std::string& id) {
|
||||
auto idx = mConfigurations.presents(id);
|
||||
if (idx) return mConfigurations.getSlotVal(idx);
|
||||
mConfigurations.put(id, {});
|
||||
return mConfigurations.get(id);
|
||||
}
|
||||
|
||||
WidgetManager::Parameter& WidgetManager::getParameter(WidgetConfig& config, const std::string& id, const Parameter& defaultValue) {
|
||||
auto idx = config.mParameters.presents(id);
|
||||
|
||||
if (!idx) {
|
||||
config.mParameters.put(id, defaultValue);
|
||||
}
|
||||
|
||||
Parameter& parameter = config.mParameters.get(id);
|
||||
|
||||
if (parameter.globalReference) {
|
||||
return mGlobalConfig.mParameters.get(parameter.globalId);
|
||||
} else {
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
|
||||
void WidgetManager::initGlobalParameters() {
|
||||
auto& params = mGlobalConfig.mParameters;
|
||||
|
||||
params.put("FontSize", Parameter(15.f));
|
||||
|
||||
params.put("FontSizeDim", Parameter(12.f));
|
||||
params.put("Rounding", Parameter(5.f));
|
||||
params.put("Padding", Parameter(5.f));
|
||||
params.put("HandleSize", Parameter(5.f));
|
||||
|
||||
params.put("Background", Parameter(RGBA{ 0.03f, 0.03f, 0.03f, 1.f }));
|
||||
params.put("Base", Parameter(RGBA{ 0.07f, 0.07f, 0.07f, 1.f }));
|
||||
params.put("Accent", Parameter(RGBA{ 0.13f, 0.13f, 0.13f, 1.f }));
|
||||
params.put("Interaction", Parameter(RGBA{ 0.33f, 0.33f, 0.3f, 1.f }));
|
||||
params.put("Action", Parameter(RGBA{ 0.44f, 0.44f, 0.4f, 1.f }));
|
||||
params.put("Front", Parameter(RGBA{ 1.f, 1.f, 1.f, 1.f }));
|
||||
params.put("FrontDim", Parameter(RGBA{ 0.7f, 0.7f, 0.7f, 1.f }));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue