update widgets
This commit is contained in:
parent
c41dcf9efa
commit
eb079e1386
24 changed files with 284 additions and 370 deletions
|
|
@ -7,14 +7,20 @@ namespace tp {
|
|||
template <typename Events, typename Canvas>
|
||||
class ButtonWidget : public Widget<Events, Canvas> {
|
||||
public:
|
||||
ButtonWidget() { this->mArea = { 0, 0, 100, 100 }; }
|
||||
|
||||
ButtonWidget(const std::string& label, const tp::RectF& aArea) {
|
||||
this->mArea = aArea;
|
||||
this->mLabel.mLabel = label;
|
||||
ButtonWidget() {
|
||||
this->setArea({ 0, 0, 100, 100 });
|
||||
this->mChildWidgets.pushBack(&mLabel);
|
||||
}
|
||||
|
||||
void procBody(const Events& events) {
|
||||
ButtonWidget(const std::string& label, const tp::RectF& aArea) {
|
||||
this->setArea(aArea);
|
||||
mLabel.mLabel = label;
|
||||
this->mChildWidgets.pushBack(&mLabel);
|
||||
}
|
||||
|
||||
void procCallback(const Events& events) override {
|
||||
mLabel.setArea(this->mArea);
|
||||
|
||||
mIsHover = this->mArea.isInside(events.getPointer());
|
||||
|
||||
if (events.isPressed(InputID::MOUSE1) && mIsHover) {
|
||||
|
|
@ -27,11 +33,9 @@ namespace tp {
|
|||
}
|
||||
|
||||
if (!mIsHover) mIsPressed = false;
|
||||
|
||||
mLabel.proc(events, this->mArea, this->mArea);
|
||||
}
|
||||
|
||||
void drawBody(Canvas& canvas) override {
|
||||
void drawCallback(Canvas& canvas) override {
|
||||
if (mIsPressed) {
|
||||
canvas.rect(this->mArea, pressedColor, rounding);
|
||||
} else if (mIsHover) {
|
||||
|
|
@ -39,11 +43,10 @@ namespace tp {
|
|||
} else {
|
||||
canvas.rect(this->mArea, accentColor, rounding);
|
||||
}
|
||||
mLabel.draw(canvas);
|
||||
}
|
||||
|
||||
public:
|
||||
void updateConfigCache(WidgetManager& wm) override {
|
||||
void updateConfigCallback(WidgetManager& wm) override {
|
||||
wm.setActiveId("Button");
|
||||
|
||||
pressedColor = wm.getColor("Pressed", "Action");
|
||||
|
|
@ -52,8 +55,6 @@ namespace tp {
|
|||
rounding = wm.getNumber("Rounding", "Rounding");
|
||||
|
||||
// mPressEvent = wm.getEventState("Activate", { { InputID::MOUSE1, InputState::PRESSED } });
|
||||
|
||||
mLabel.updateConfigCache(wm);
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -68,6 +69,6 @@ namespace tp {
|
|||
RGBA accentColor;
|
||||
halnf rounding = 0;
|
||||
|
||||
InputState mPressEvent;
|
||||
// InputState mPressEvent;
|
||||
};
|
||||
}
|
||||
|
|
@ -8,12 +8,12 @@ namespace tp {
|
|||
public:
|
||||
LabelWidget() = default;
|
||||
|
||||
void drawBody(Canvas& canvas) override {
|
||||
void drawCallback(Canvas& canvas) override {
|
||||
canvas.text(mLabel.c_str(), this->mArea, fontSize, Canvas::CC, padding, fontColor);
|
||||
}
|
||||
|
||||
public:
|
||||
void updateConfigCache(WidgetManager& wm) override {
|
||||
void updateConfigCallback(WidgetManager& wm) override {
|
||||
wm.setActiveId("Label");
|
||||
|
||||
fontSize = wm.getNumber("Size", "FontSize");
|
||||
|
|
|
|||
|
|
@ -11,11 +11,7 @@ namespace tp {
|
|||
ScrollBarWidget() = default;
|
||||
|
||||
// takes whole area
|
||||
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override {
|
||||
this->mArea = aArea;
|
||||
this->mVisible = areaParent.isOverlap(aArea);
|
||||
if (!this->mVisible) return;
|
||||
|
||||
void procCallback(const Events& events) override {
|
||||
auto area = getHandle();
|
||||
mHovered = getHandleHandle().isInside(events.getPointer());
|
||||
|
||||
|
|
@ -24,12 +20,7 @@ namespace tp {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!areaParent.isOverlap(area)) {
|
||||
mIsScrolling = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (events.getScrollY() != 0 && areaParent.isInside(events.getPointer())) {
|
||||
if (events.getScrollY() != 0) {
|
||||
auto offset = events.getScrollY() < 0 ? 1.0f : -1.0f;
|
||||
if (scrollInertia * offset > 0) {
|
||||
scrollInertia += offset;
|
||||
|
|
@ -61,9 +52,7 @@ namespace tp {
|
|||
mPositionFraction = tp::clamp(mPositionFraction, 0.f, 1.f - mSizeFraction);
|
||||
}
|
||||
|
||||
void draw(Canvas& canvas) override {
|
||||
if (!this->mVisible) return;
|
||||
|
||||
void drawCallback(Canvas& canvas) override {
|
||||
auto area = getHandle();
|
||||
|
||||
if (mSizeFraction > 1.f) return;
|
||||
|
|
@ -78,7 +67,6 @@ namespace tp {
|
|||
}
|
||||
|
||||
canvas.rect(area, mDefaultColor, mRounding);
|
||||
|
||||
canvas.rect(getHandleHandle(), col, mRounding);
|
||||
}
|
||||
|
||||
|
|
@ -104,7 +92,7 @@ namespace tp {
|
|||
}
|
||||
|
||||
public:
|
||||
void updateConfigCache(WidgetManager& wm) override {
|
||||
void updateConfigCallback(WidgetManager& wm) override {
|
||||
wm.setActiveId("Scrollbar");
|
||||
|
||||
mDefaultColor = wm.getColor("Default", "Base");
|
||||
|
|
@ -138,99 +126,89 @@ namespace tp {
|
|||
template <typename Events, typename Canvas>
|
||||
class ScrollableWindow : public Widget<Events, Canvas> {
|
||||
public:
|
||||
ScrollableWindow() = default;
|
||||
ScrollableWindow() {
|
||||
this->mChildWidgets.pushBack(&mScroller);
|
||||
this->mChildWidgets.pushBack(&mContentWidget);
|
||||
}
|
||||
|
||||
~ScrollableWindow() = default;
|
||||
|
||||
// takes whole area
|
||||
void procBody(const Events& events) override {
|
||||
updateContents();
|
||||
updateContentSize();
|
||||
void procCallback(const Events& events) override {
|
||||
List<Widget<Events, Canvas>*>& content = mContentWidget.mChildWidgets;
|
||||
|
||||
updateContents(content);
|
||||
updateContentSize(content);
|
||||
|
||||
const auto padding = mPadding;
|
||||
|
||||
mScroller.mSizeFraction = this->mArea.w / mContentSize;
|
||||
mScroller.proc(events, this->mArea, this->mArea);
|
||||
mScroller.mSizeFraction = mContentWidget.mArea.w / mContentSize;
|
||||
mScroller.setArea(this->mArea);
|
||||
mContentWidget.setArea(mScroller.getViewport());
|
||||
|
||||
if (mScroller.mSizeFraction > 1.f) {
|
||||
setOffset(0);
|
||||
setOffset(content, 0);
|
||||
} else {
|
||||
setOffset((-mScroller.mPositionFraction) * mContentSize);
|
||||
setOffset(content, (-mScroller.mPositionFraction) * mContentSize);
|
||||
}
|
||||
|
||||
for (auto widget : mContents) {
|
||||
widget->proc(
|
||||
events,
|
||||
this->mArea,
|
||||
{ this->mArea.x + padding, widget->mArea.y, mScroller.getViewport().z - padding * 2, widget->mArea.w }
|
||||
);
|
||||
for (auto widget : content) {
|
||||
widget->setArea({ mContentWidget.mArea.x + padding,
|
||||
widget->mArea.y,
|
||||
mScroller.getViewport().z - padding * 2,
|
||||
widget->mArea.w });
|
||||
}
|
||||
}
|
||||
|
||||
void drawBody(Canvas& canvas) override {
|
||||
mScroller.draw(canvas);
|
||||
void addWidget(Widget<Events, Canvas>* widget) { mContentWidget.mChildWidgets.pushBack(widget); }
|
||||
void clearContent() { mContentWidget.mChildWidgets.removeAll(); }
|
||||
List<Widget<Events, Canvas>*>& getContent() { return mContentWidget.mChildWidgets; }
|
||||
|
||||
canvas.pushClamp(this->mArea);
|
||||
for (auto widget : mContents) {
|
||||
widget->draw(canvas);
|
||||
}
|
||||
canvas.popClamp();
|
||||
}
|
||||
|
||||
public:
|
||||
void updateConfigCache(WidgetManager& wm) override {
|
||||
void updateConfigCallback(WidgetManager& wm) override {
|
||||
wm.setActiveId("ScrollableWidget");
|
||||
|
||||
mDefaultColor = wm.getColor("Default", "Base");
|
||||
mPadding = wm.getNumber("Padding", "Padding");
|
||||
|
||||
mScroller.updateConfigCache(wm);
|
||||
|
||||
for (auto item : mContents) {
|
||||
item->updateConfigCache(wm);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void updateContents() {
|
||||
if (mContents.size()) {
|
||||
const halnf offset = mContents.first()->mArea.y + mPadding;
|
||||
void updateContents(List<Widget<Events, Canvas>*>& contentWidgets) {
|
||||
if (contentWidgets.size()) {
|
||||
const halnf offset = contentWidgets.first()->mArea.y + mPadding;
|
||||
|
||||
halnf start = 0;
|
||||
for (auto widget : mContents) {
|
||||
for (auto widget : contentWidgets) {
|
||||
widget->mArea.y = start;
|
||||
start += widget->mArea.w + mPadding;
|
||||
}
|
||||
|
||||
for (auto widget : mContents) {
|
||||
for (auto widget : contentWidgets) {
|
||||
widget->mArea.y += offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateContentSize() {
|
||||
void updateContentSize(List<Widget<Events, Canvas>*>& contentWidgets) {
|
||||
mContentSize = 0;
|
||||
if (mContents.size()) {
|
||||
mContentSize = mContents.last()->mArea.y - mContents.first()->mArea.y;
|
||||
mContentSize += mContents.last()->mArea.w;
|
||||
if (contentWidgets.size()) {
|
||||
mContentSize = contentWidgets.last()->mArea.y - contentWidgets.first()->mArea.y;
|
||||
mContentSize += contentWidgets.last()->mArea.w;
|
||||
mContentSize += 2 * mPadding;
|
||||
}
|
||||
}
|
||||
|
||||
void setOffset(const halnf offset) {
|
||||
if (!mContents.size()) return;
|
||||
auto newOffset = offset - mContents.first()->mArea.y + mPadding;
|
||||
for (auto widget : mContents) {
|
||||
void setOffset(List<Widget<Events, Canvas>*>& contentWidgets, const halnf offset) {
|
||||
if (!contentWidgets.size()) return;
|
||||
auto newOffset = offset - contentWidgets.first()->mArea.y + mPadding;
|
||||
for (auto widget : contentWidgets) {
|
||||
widget->mArea.y += newOffset;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
halnf mContentSize = 0;
|
||||
|
||||
Buffer<Widget<Events, Canvas>*> mContents;
|
||||
private:
|
||||
Widget<Events, Canvas> mContentWidget;
|
||||
ScrollBarWidget<Events, Canvas> mScroller;
|
||||
|
||||
RGBA mDefaultColor;
|
||||
halnf mContentSize = 0;
|
||||
|
||||
halnf mPadding = 0;
|
||||
};
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ namespace tp {
|
|||
public:
|
||||
SliderWidget() = default;
|
||||
|
||||
void procBody(const Events& events) override {
|
||||
void procCallback(const Events& events) override {
|
||||
if (events.isPressed(InputID::MOUSE1) && this->mArea.isInside(events.getPointer())) {
|
||||
mIsSliding = true;
|
||||
} else if (events.isReleased(InputID::MOUSE1)) {
|
||||
|
|
@ -23,7 +23,7 @@ namespace tp {
|
|||
mFactor = tp::clamp(mFactor, 0.f, 1.f);
|
||||
}
|
||||
|
||||
void drawBody(Canvas& canvas) override {
|
||||
void drawCallback(Canvas& canvas) override {
|
||||
canvas.rect(this->mArea, defaultColor, rounding);
|
||||
canvas.rect(getHandle(), handleColor, rounding);
|
||||
}
|
||||
|
|
@ -34,7 +34,7 @@ namespace tp {
|
|||
}
|
||||
|
||||
public:
|
||||
void updateConfigCache(WidgetManager& wm) override {
|
||||
void updateConfigCallback(WidgetManager& wm) override {
|
||||
wm.setActiveId("Slider");
|
||||
defaultColor = wm.getColor("Default", "Base");
|
||||
handleColor = wm.getColor("Handle", "Accent");
|
||||
|
|
@ -58,32 +58,24 @@ namespace tp {
|
|||
explicit NamedSliderWidget(const char* name = "Value") {
|
||||
mLabel.mLabel = name;
|
||||
this->mArea = { 0, 0, 100, 30 };
|
||||
|
||||
this->mChildWidgets.pushBack(&mSlider);
|
||||
this->mChildWidgets.pushBack(&mLabel);
|
||||
}
|
||||
|
||||
void procBody(const Events& events) override {
|
||||
void procCallback(const Events& events) override {
|
||||
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.proc(events, this->mArea, rec);
|
||||
mLabel.setArea(rec);
|
||||
|
||||
rec.pos.x += widthFirst;
|
||||
rec.size.x = widthSecond;
|
||||
|
||||
mSlider.proc(events, this->mArea, rec);
|
||||
}
|
||||
|
||||
void drawBody(Canvas& canvas) override {
|
||||
mSlider.draw(canvas);
|
||||
mLabel.draw(canvas);
|
||||
}
|
||||
|
||||
virtual void updateConfigCache(WidgetManager& wm) {
|
||||
wm.setActiveId("NamedSlider");
|
||||
mSlider.updateConfigCache(wm);
|
||||
mLabel.updateConfigCache(wm);
|
||||
mSlider.setArea(rec);
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ namespace tp {
|
|||
public:
|
||||
SplitView() = default;
|
||||
|
||||
void procBody(const Events& events) override {
|
||||
// takes whole area
|
||||
void procCallback(const Events& events) override {
|
||||
mIsHover = getHandle().isInside(events.getPointer());
|
||||
|
||||
if (events.isPressed(InputID::MOUSE1) && mIsHover) {
|
||||
|
|
@ -30,8 +31,7 @@ namespace tp {
|
|||
}
|
||||
}
|
||||
|
||||
// takes whole area
|
||||
void drawBody(Canvas& canvas) override {
|
||||
void drawCallback(Canvas& canvas) override {
|
||||
if (mResizeInProcess) canvas.rect(getHandle(), mResizingColor);
|
||||
else if (mIsHover) canvas.rect(getHandle(), mHoveredColor);
|
||||
else canvas.rect(getHandle(), mHandleColor);
|
||||
|
|
@ -53,7 +53,7 @@ namespace tp {
|
|||
}
|
||||
|
||||
public:
|
||||
void updateConfigCache(WidgetManager& wm) override {
|
||||
void updateConfigCallback(WidgetManager& wm) override {
|
||||
wm.setActiveId("SplitView");
|
||||
|
||||
mHandleColor = wm.getColor("Handle", "Accent");
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ namespace tp {
|
|||
public:
|
||||
TextInputWidget() = default;
|
||||
|
||||
void drawBody(Canvas& canvas) override {
|
||||
void drawCallback(Canvas&) override {
|
||||
nChanged = false;
|
||||
|
||||
const auto col = mAccentColor;
|
||||
|
|
@ -51,7 +51,7 @@ namespace tp {
|
|||
}
|
||||
|
||||
public:
|
||||
void updateConfigCache(WidgetManager& wm) override {
|
||||
void updateConfigCallback(WidgetManager& wm) override {
|
||||
wm.setActiveId("TextInput");
|
||||
|
||||
mAccentColor = wm.getColor("Accent", "Accent");
|
||||
|
|
|
|||
|
|
@ -2,42 +2,69 @@
|
|||
|
||||
#include "EventHandler.hpp"
|
||||
#include "WidgetManager.hpp"
|
||||
#include "List.hpp"
|
||||
|
||||
namespace tp {
|
||||
|
||||
template <typename Events, typename Canvas>
|
||||
class Widget {
|
||||
public:
|
||||
Widget() { this->mArea = { 0, 0, 100, 100 }; }
|
||||
Widget() { mArea = { 0, 0, 100, 100 }; }
|
||||
|
||||
virtual void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) {
|
||||
mVisible = areaParent.isOverlap(aArea);
|
||||
if (!mVisible) {
|
||||
return;
|
||||
virtual ~Widget() = default;
|
||||
|
||||
virtual void procWrapper(const Events& events) {
|
||||
if (!mEnable) return;
|
||||
if (!mVisible) return;
|
||||
|
||||
procCallback(events);
|
||||
|
||||
for (auto child : mChildWidgets) {
|
||||
const bool isChildVisible = getArea().isOverlap(child->getArea());
|
||||
child->setVisible(isChildVisible);
|
||||
child->procWrapper(events);
|
||||
}
|
||||
|
||||
this->mArea = aArea;
|
||||
this->mAreaParent = areaParent;
|
||||
|
||||
procBody(events);
|
||||
}
|
||||
|
||||
virtual void draw(Canvas& canvas) {
|
||||
if (!mVisible) {
|
||||
return;
|
||||
virtual void drawWrapper(Canvas& canvas) {
|
||||
if (!mEnable) return;
|
||||
if (!mVisible) return;
|
||||
|
||||
drawCallback(canvas);
|
||||
|
||||
canvas.pushClamp(this->mArea);
|
||||
|
||||
for (auto child : mChildWidgets) {
|
||||
child->drawWrapper(canvas);
|
||||
}
|
||||
|
||||
drawBody(canvas);
|
||||
canvas.popClamp();
|
||||
}
|
||||
|
||||
virtual void procBody(const Events& events) {}
|
||||
virtual void drawBody(Canvas& canvas) {}
|
||||
virtual void updateConfigWrapper(WidgetManager& wm) {
|
||||
wm.setActiveId("Global");
|
||||
|
||||
virtual void updateConfigCache(WidgetManager& wm) {}
|
||||
updateConfigCallback(wm);
|
||||
|
||||
for (auto child : mChildWidgets) {
|
||||
child->updateConfigWrapper(wm);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void procCallback(const Events& events) {}
|
||||
virtual void drawCallback(Canvas& canvas) {}
|
||||
virtual void updateConfigCallback(WidgetManager& wm) {}
|
||||
|
||||
public:
|
||||
void setEnable(bool enable) { mEnable = enable; }
|
||||
void setVisible(bool visible) { mVisible = visible; }
|
||||
const RectF& getArea() const { return mArea; }
|
||||
void setArea(const RectF& area) { mArea = area; }
|
||||
|
||||
public:
|
||||
RectF mArea;
|
||||
RectF mAreaParent;
|
||||
List<Widget<Events, Canvas>*> mChildWidgets;
|
||||
bool mVisible = false;
|
||||
bool mEnable = true;
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue