Update widgets module. Raster example initial.
This commit is contained in:
parent
aa10424fbb
commit
90244934d9
48 changed files with 1169 additions and 530 deletions
|
|
@ -7,40 +7,15 @@ namespace tp {
|
|||
template <typename Events, typename Canvas>
|
||||
class ButtonWidget : public Widget<Events, Canvas> {
|
||||
public:
|
||||
ButtonWidget() {
|
||||
this->mArea = { 0, 0, 100, 100 };
|
||||
this->createConfig("Button");
|
||||
this->addColor("Pressed", "Action");
|
||||
this->addColor("Hovered", "Interaction");
|
||||
this->addColor("Default", "Accent");
|
||||
this->addValue("Rounding", "Rounding");
|
||||
}
|
||||
ButtonWidget() { this->mArea = { 0, 0, 100, 100 }; }
|
||||
|
||||
ButtonWidget(const std::string& label, const tp::RectF& aArea) {
|
||||
this->mArea = aArea;
|
||||
this->mLabel.mLabel = label;
|
||||
|
||||
this->createConfig("Button");
|
||||
this->addColor("Pressed", "Action");
|
||||
this->addColor("Hovered", "Interaction");
|
||||
this->addColor("Default", "Accent");
|
||||
this->addValue("Rounding", "Rounding");
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
mIsHover = false;
|
||||
|
||||
if (!areaParent.isOverlap(aArea)) {
|
||||
mIsReleased = false;
|
||||
mIsPressed = false;
|
||||
return;
|
||||
}
|
||||
|
||||
mIsHover = aArea.isInside(events.getPointer());
|
||||
void procBody(const Events& events) {
|
||||
mIsHover = this->mArea.isInside(events.getPointer());
|
||||
|
||||
if (events.isPressed(InputID::MOUSE1) && mIsHover) {
|
||||
mIsPressed = true;
|
||||
|
|
@ -53,26 +28,46 @@ namespace tp {
|
|||
|
||||
if (!mIsHover) mIsPressed = false;
|
||||
|
||||
mLabel.proc(events, aArea, aArea);
|
||||
mLabel.proc(events, this->mArea, this->mArea);
|
||||
}
|
||||
|
||||
void draw(Canvas& canvas) override {
|
||||
if (!this->mVisible) return;
|
||||
|
||||
void drawBody(Canvas& canvas) override {
|
||||
if (mIsPressed) {
|
||||
canvas.rect(this->mArea, this->getColor("Pressed"), this->getValue("Rounding"));
|
||||
canvas.rect(this->mArea, pressedColor, rounding);
|
||||
} else if (mIsHover) {
|
||||
canvas.rect(this->mArea, this->getColor("Hovered"), this->getValue("Rounding"));
|
||||
canvas.rect(this->mArea, hoveredColor, rounding);
|
||||
} else {
|
||||
canvas.rect(this->mArea, this->getColor("Default"), this->getValue("Rounding"));
|
||||
canvas.rect(this->mArea, accentColor, rounding);
|
||||
}
|
||||
mLabel.draw(canvas);
|
||||
}
|
||||
|
||||
public:
|
||||
void updateConfigCache(WidgetManager& wm) override {
|
||||
wm.setActiveId("Button");
|
||||
|
||||
pressedColor = wm.getColor("Pressed", "Action");
|
||||
hoveredColor = wm.getColor("Hovered", "Interaction");
|
||||
accentColor = wm.getColor("Default", "Accent");
|
||||
rounding = wm.getNumber("Rounding", "Rounding");
|
||||
|
||||
// mPressEvent = wm.getEventState("Activate", { { InputID::MOUSE1, InputState::PRESSED } });
|
||||
|
||||
mLabel.updateConfigCache(wm);
|
||||
}
|
||||
|
||||
public:
|
||||
LabelWidget<Events, Canvas> mLabel;
|
||||
|
||||
bool mIsHover = false;
|
||||
bool mIsPressed = false;
|
||||
bool mIsReleased = false;
|
||||
|
||||
RGBA pressedColor;
|
||||
RGBA hoveredColor;
|
||||
RGBA accentColor;
|
||||
halnf rounding = 0;
|
||||
|
||||
InputState mPressEvent;
|
||||
};
|
||||
}
|
||||
|
|
@ -6,33 +6,26 @@ namespace tp {
|
|||
template <typename Events, typename Canvas>
|
||||
class LabelWidget : public Widget<Events, Canvas> {
|
||||
public:
|
||||
LabelWidget() {
|
||||
this->createConfig("Label");
|
||||
this->addValue("Size", "FontSize");
|
||||
this->addValue("Padding", "Padding");
|
||||
this->addColor("Default", "Front");
|
||||
LabelWidget() = default;
|
||||
|
||||
void drawBody(Canvas& canvas) override {
|
||||
canvas.text(mLabel.c_str(), this->mArea, fontSize, Canvas::CC, padding, fontColor);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
public:
|
||||
void updateConfigCache(WidgetManager& wm) override {
|
||||
wm.setActiveId("Label");
|
||||
|
||||
void draw(Canvas& canvas) override {
|
||||
if (!this->mVisible) return;
|
||||
|
||||
canvas.text(
|
||||
mLabel.c_str(),
|
||||
this->mArea,
|
||||
this->getValue("Size"),
|
||||
Canvas::CC,
|
||||
this->getValue("Padding"),
|
||||
this->getColor("Default")
|
||||
);
|
||||
fontSize = wm.getNumber("Size", "FontSize");
|
||||
padding = wm.getNumber("Padding", "Padding");
|
||||
fontColor = wm.getColor("Default", "Front");
|
||||
}
|
||||
|
||||
public:
|
||||
std::string mLabel = "Label";
|
||||
|
||||
halnf fontSize = 10;
|
||||
halnf padding = 0;
|
||||
RGBA fontColor = { 1, 1, 1, 1 };
|
||||
};
|
||||
}
|
||||
|
|
@ -8,17 +8,7 @@ namespace tp {
|
|||
template <typename Events, typename Canvas>
|
||||
class ScrollBarWidget : public Widget<Events, Canvas> {
|
||||
public:
|
||||
ScrollBarWidget() {
|
||||
this->createConfig("ScrollBar");
|
||||
this->addColor("Default", "Base");
|
||||
this->addColor("Handle", "Accent");
|
||||
this->addColor("Hovered", "Interaction");
|
||||
this->addColor("Scrolling", "Action");
|
||||
this->addValue("Padding", "Padding");
|
||||
this->addValue("HandleSize", 20.f);
|
||||
this->addValue("MinSize", 20.f);
|
||||
this->addValue("Rounding", "Rounding");
|
||||
}
|
||||
ScrollBarWidget() = default;
|
||||
|
||||
// takes whole area
|
||||
void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) override {
|
||||
|
|
@ -79,28 +69,22 @@ namespace tp {
|
|||
if (mSizeFraction > 1.f) return;
|
||||
// if (!areaParent.isOverlap(getHandle())) return;
|
||||
|
||||
tp::RGBA col = this->getColor("Handle");
|
||||
tp::RGBA col = mHandleColor;
|
||||
|
||||
if (mIsScrolling) {
|
||||
col = this->getColor("Scrolling");
|
||||
col = mScrollingColor;
|
||||
} else if (mHovered) {
|
||||
col = this->getColor("Hovered");
|
||||
col = mHoveredColor;
|
||||
}
|
||||
|
||||
canvas.rect(area, this->getColor("Default"), this->getValue("Rounding"));
|
||||
canvas.rect(area, mDefaultColor, mRounding);
|
||||
|
||||
canvas.rect(getHandleHandle(), col, this->getValue("Rounding"));
|
||||
canvas.rect(getHandleHandle(), col, mRounding);
|
||||
}
|
||||
|
||||
RectF getHandleHandle() const {
|
||||
auto minSize = this->getValue("MinSize");
|
||||
if (mIsScrolling) {
|
||||
minSize = this->getValue("MinSize") * 2;
|
||||
} else if (mHovered) {
|
||||
minSize = this->getValue("MinSize") * 2;
|
||||
}
|
||||
auto area = getHandle();
|
||||
auto sliderSize = tp::clamp(area.w * mSizeFraction, minSize, area.w);
|
||||
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 };
|
||||
}
|
||||
|
|
@ -109,14 +93,28 @@ namespace tp {
|
|||
if (mSizeFraction > 1.f) {
|
||||
return this->mArea;
|
||||
}
|
||||
return { this->mArea.x, this->mArea.y, this->mArea.z - this->getValue("HandleSize"), this->mArea.w };
|
||||
return { this->mArea.x, this->mArea.y, this->mArea.z - mHandleSize, this->mArea.w };
|
||||
}
|
||||
|
||||
RectF getHandle() const {
|
||||
return { this->mArea.x + this->mArea.z - this->getValue("HandleSize") + this->getValue("Padding"),
|
||||
this->mArea.y + this->getValue("Padding"),
|
||||
this->getValue("HandleSize") - this->getValue("Padding") * 2,
|
||||
this->mArea.w - this->getValue("Padding") * 2 };
|
||||
return { this->mArea.x + this->mArea.z - mHandleSize + mPadding,
|
||||
this->mArea.y + mPadding,
|
||||
mHandleSize - mPadding * 2,
|
||||
this->mArea.w - mPadding * 2 };
|
||||
}
|
||||
|
||||
public:
|
||||
void updateConfigCache(WidgetManager& wm) override {
|
||||
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");
|
||||
}
|
||||
|
||||
public:
|
||||
|
|
@ -126,29 +124,29 @@ namespace tp {
|
|||
halnf mSizeFraction = 1.f;
|
||||
halnf mPositionFraction = 0.f;
|
||||
bool mHovered = false;
|
||||
|
||||
RGBA mDefaultColor;
|
||||
RGBA mHandleColor;
|
||||
RGBA mHoveredColor;
|
||||
RGBA mScrollingColor;
|
||||
halnf mPadding = 0;
|
||||
halnf mHandleSize = 10;
|
||||
halnf mMinSize = 10;
|
||||
halnf mRounding = 10;
|
||||
};
|
||||
|
||||
template <typename Events, typename Canvas>
|
||||
class ScrollableWindow : public Widget<Events, Canvas> {
|
||||
public:
|
||||
ScrollableWindow() {
|
||||
this->createConfig("ScrollableWindow");
|
||||
this->addColor("Default", "Base");
|
||||
this->addValue("Padding", "Padding");
|
||||
}
|
||||
|
||||
ScrollableWindow() = default;
|
||||
~ScrollableWindow() = 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 procBody(const Events& events) override {
|
||||
updateContents();
|
||||
updateContentSize();
|
||||
|
||||
const auto padding = this->getValue("Padding");
|
||||
const auto padding = mPadding;
|
||||
|
||||
mScroller.mSizeFraction = this->mArea.w / mContentSize;
|
||||
mScroller.proc(events, this->mArea, this->mArea);
|
||||
|
|
@ -168,9 +166,7 @@ namespace tp {
|
|||
}
|
||||
}
|
||||
|
||||
void draw(Canvas& canvas) override {
|
||||
if (!this->mVisible) return;
|
||||
|
||||
void drawBody(Canvas& canvas) override {
|
||||
mScroller.draw(canvas);
|
||||
|
||||
canvas.pushClamp(this->mArea);
|
||||
|
|
@ -180,16 +176,29 @@ namespace tp {
|
|||
canvas.popClamp();
|
||||
}
|
||||
|
||||
public:
|
||||
void updateConfigCache(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 auto padding = this->getValue("Padding");
|
||||
const halnf offset = mContents.first()->mArea.y + padding;
|
||||
const halnf offset = mContents.first()->mArea.y + mPadding;
|
||||
|
||||
halnf start = 0;
|
||||
for (auto widget : mContents) {
|
||||
widget->mArea.y = start;
|
||||
start += widget->mArea.w + padding;
|
||||
start += widget->mArea.w + mPadding;
|
||||
}
|
||||
|
||||
for (auto widget : mContents) {
|
||||
|
|
@ -201,17 +210,15 @@ namespace tp {
|
|||
void updateContentSize() {
|
||||
mContentSize = 0;
|
||||
if (mContents.size()) {
|
||||
const auto padding = this->getValue("Padding");
|
||||
mContentSize = mContents.last()->mArea.y - mContents.first()->mArea.y;
|
||||
mContentSize += mContents.last()->mArea.w;
|
||||
mContentSize += 2 * padding;
|
||||
mContentSize += 2 * mPadding;
|
||||
}
|
||||
}
|
||||
|
||||
void setOffset(const halnf offset) {
|
||||
if (!mContents.size()) return;
|
||||
const auto padding = this->getValue("Padding");
|
||||
auto newOffset = offset - mContents.first()->mArea.y + padding;
|
||||
auto newOffset = offset - mContents.first()->mArea.y + mPadding;
|
||||
for (auto widget : mContents) {
|
||||
widget->mArea.y += newOffset;
|
||||
}
|
||||
|
|
@ -219,7 +226,11 @@ namespace tp {
|
|||
|
||||
public:
|
||||
halnf mContentSize = 0;
|
||||
|
||||
Buffer<Widget<Events, Canvas>*> mContents;
|
||||
ScrollBarWidget<Events, Canvas> mScroller;
|
||||
|
||||
RGBA mDefaultColor;
|
||||
halnf mPadding = 0;
|
||||
};
|
||||
}
|
||||
|
|
@ -7,23 +7,9 @@ namespace tp {
|
|||
template <typename Events, typename Canvas>
|
||||
class SliderWidget : public Widget<Events, Canvas> {
|
||||
public:
|
||||
SliderWidget() {
|
||||
this->createConfig("SliderWidget");
|
||||
this->addColor("Default", "Base");
|
||||
this->addColor("Handle", "Accent");
|
||||
this->addColor("Hovered", "Interaction");
|
||||
this->addColor("Scrolling", "Action");
|
||||
this->addValue("Padding", "Padding");
|
||||
this->addValue("HandleSize", 20.f);
|
||||
this->addValue("MinSize", 20.f);
|
||||
this->addValue("Rounding", "Rounding");
|
||||
}
|
||||
|
||||
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;
|
||||
SliderWidget() = default;
|
||||
|
||||
void procBody(const Events& events) override {
|
||||
if (events.isPressed(InputID::MOUSE1) && this->mArea.isInside(events.getPointer())) {
|
||||
mIsSliding = true;
|
||||
} else if (events.isReleased(InputID::MOUSE1)) {
|
||||
|
|
@ -31,44 +17,50 @@ namespace tp {
|
|||
}
|
||||
|
||||
if (mIsSliding) {
|
||||
const auto handleSize = this->getValue("HandleSize");
|
||||
mFactor = (events.getPointer().x - this->mArea.x - handleSize / 2.f) / (this->mArea.z - handleSize);
|
||||
}
|
||||
|
||||
mFactor = tp::clamp(mFactor, 0.f, 1.f);
|
||||
}
|
||||
|
||||
void draw(Canvas& canvas) override {
|
||||
if (!this->mVisible) return;
|
||||
canvas.rect(this->mArea, this->getColor("Default"), this->getValue("Rounding"));
|
||||
canvas.rect(getHandle(), this->getColor("Handle"), this->getValue("Rounding"));
|
||||
void drawBody(Canvas& canvas) override {
|
||||
canvas.rect(this->mArea, defaultColor, rounding);
|
||||
canvas.rect(getHandle(), handleColor, rounding);
|
||||
}
|
||||
|
||||
RectF getHandle() const {
|
||||
const auto handle = this->getValue("HandleSize");
|
||||
const auto halfHandle = handle / 2.f;
|
||||
const auto left = this->mArea.x + (this->mArea.z - handle) * mFactor;
|
||||
return { left, this->mArea.y, handle, this->mArea.w };
|
||||
const auto left = this->mArea.x + (this->mArea.z - handleSize) * mFactor;
|
||||
return { left, this->mArea.y, handleSize, this->mArea.w };
|
||||
}
|
||||
|
||||
public:
|
||||
void updateConfigCache(WidgetManager& wm) override {
|
||||
wm.setActiveId("Slider");
|
||||
defaultColor = wm.getColor("Default", "Base");
|
||||
handleColor = wm.getColor("Handle", "Accent");
|
||||
handleSize = wm.getNumber("HandleSize", 20.f);
|
||||
rounding = wm.getNumber("Rounding", "Rounding");
|
||||
}
|
||||
|
||||
public:
|
||||
halnf mFactor = 0.f;
|
||||
bool mIsSliding = false;
|
||||
|
||||
RGBA defaultColor;
|
||||
RGBA handleColor;
|
||||
halnf handleSize = 0;
|
||||
halnf rounding = 0;
|
||||
};
|
||||
|
||||
template <typename Events, typename Canvas>
|
||||
class NamedSliderWidget : public Widget<Events, Canvas> {
|
||||
public:
|
||||
NamedSliderWidget(const char* name = "Value") {
|
||||
explicit NamedSliderWidget(const char* name = "Value") {
|
||||
mLabel.mLabel = name;
|
||||
this->mArea = { 0, 0, 100, 30 };
|
||||
}
|
||||
|
||||
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 procBody(const Events& events) override {
|
||||
const auto widthFirst = this->mArea.z * mFactor;
|
||||
const auto widthSecond = this->mArea.z * (1.f - mFactor);
|
||||
|
||||
|
|
@ -83,12 +75,17 @@ namespace tp {
|
|||
mSlider.proc(events, this->mArea, rec);
|
||||
}
|
||||
|
||||
void draw(Canvas& canvas) override {
|
||||
if (!this->mVisible) return;
|
||||
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);
|
||||
}
|
||||
|
||||
public:
|
||||
SliderWidget<Events, Canvas> mSlider;
|
||||
LabelWidget<Events, Canvas> mLabel;
|
||||
|
|
|
|||
|
|
@ -6,24 +6,9 @@ namespace tp {
|
|||
template <typename Events, typename Canvas>
|
||||
class SplitView : public Widget<Events, Canvas> {
|
||||
public:
|
||||
SplitView() {
|
||||
this->createConfig("SplitView");
|
||||
this->addColor("Handle", "Accent");
|
||||
this->addColor("Hovered", "Interaction");
|
||||
this->addColor("Resizing", "Action");
|
||||
this->addValue("Min", 200.f);
|
||||
this->addValue("HandleSize", 7.f);
|
||||
}
|
||||
|
||||
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) {
|
||||
mResizeInProcess = false;
|
||||
return;
|
||||
}
|
||||
SplitView() = default;
|
||||
|
||||
void procBody(const Events& events) override {
|
||||
mIsHover = getHandle().isInside(events.getPointer());
|
||||
|
||||
if (events.isPressed(InputID::MOUSE1) && mIsHover) {
|
||||
|
|
@ -38,45 +23,55 @@ namespace tp {
|
|||
mFactor += diff / this->mArea.z;
|
||||
}
|
||||
|
||||
mFactor = tp::clamp(mFactor, this->getValue("Min") / this->mArea.z, 1 - this->getValue("Min") / this->mArea.z);
|
||||
mFactor = tp::clamp(mFactor, mMinSize / this->mArea.z, 1 - mMinSize / this->mArea.z);
|
||||
|
||||
if (this->getValue("Min") * 2.f > this->mArea.z) {
|
||||
if (mMinSize * 2.f > this->mArea.z) {
|
||||
mFactor = 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
// takes whole area
|
||||
void draw(Canvas& canvas) override {
|
||||
if (!this->mVisible) return;
|
||||
|
||||
if (mResizeInProcess) canvas.rect(getHandle(), this->getColor("Resizing"));
|
||||
else if (mIsHover) canvas.rect(getHandle(), this->getColor("Hovered"));
|
||||
else canvas.rect(getHandle(), this->getColor("Handle"));
|
||||
void drawBody(Canvas& canvas) override {
|
||||
if (mResizeInProcess) canvas.rect(getHandle(), mResizingColor);
|
||||
else if (mIsHover) canvas.rect(getHandle(), mHoveredColor);
|
||||
else canvas.rect(getHandle(), mHandleColor);
|
||||
}
|
||||
|
||||
RectF getFirst() const {
|
||||
return {
|
||||
this->mArea.x, this->mArea.y, mFactor * this->mArea.z - this->getValue("HandleSize") / 2.f, this->mArea.w
|
||||
};
|
||||
return { this->mArea.x, this->mArea.y, mFactor * this->mArea.z - mHandleSize / 2.f, this->mArea.w };
|
||||
}
|
||||
|
||||
RectF getSecond() const {
|
||||
return { this->mArea.x + mFactor * this->mArea.z + this->getValue("HandleSize") / 2.f,
|
||||
return { this->mArea.x + mFactor * this->mArea.z + mHandleSize / 2.f,
|
||||
this->mArea.y,
|
||||
(1.f - mFactor) * this->mArea.z - this->getValue("HandleSize") / 2.f,
|
||||
(1.f - mFactor) * this->mArea.z - mHandleSize / 2.f,
|
||||
this->mArea.w };
|
||||
}
|
||||
|
||||
RectF getHandle() const {
|
||||
return { this->mArea.x + mFactor * this->mArea.z - this->getValue("HandleSize") / 2.f,
|
||||
this->mArea.y,
|
||||
this->getValue("HandleSize"),
|
||||
this->mArea.w };
|
||||
return { this->mArea.x + mFactor * this->mArea.z - mHandleSize / 2.f, this->mArea.y, mHandleSize, this->mArea.w };
|
||||
}
|
||||
|
||||
public:
|
||||
void updateConfigCache(WidgetManager& wm) override {
|
||||
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);
|
||||
}
|
||||
|
||||
public:
|
||||
halnf mFactor = 0.7f;
|
||||
bool mResizeInProcess = false;
|
||||
bool mIsHover = false;
|
||||
|
||||
RGBA mHandleColor;
|
||||
RGBA mHoveredColor;
|
||||
RGBA mResizingColor;
|
||||
halnf mMinSize = 0;
|
||||
halnf mHandleSize = 0;
|
||||
};
|
||||
}
|
||||
|
|
@ -9,28 +9,13 @@ namespace tp {
|
|||
template <typename Events, typename Canvas>
|
||||
class TextInputWidget : public Widget<Events, Canvas> {
|
||||
public:
|
||||
TextInputWidget() {
|
||||
this->createConfig("TextInput");
|
||||
this->addColor("Accent", "Accent");
|
||||
this->addColor("Base", "Base");
|
||||
this->addValue("Rounding", "Rounding");
|
||||
this->addColor("Hovered", "Interaction");
|
||||
this->addValue("Padding", "Padding");
|
||||
}
|
||||
|
||||
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 draw(Canvas& canvas) override {
|
||||
if (!this->mVisible) return;
|
||||
TextInputWidget() = default;
|
||||
|
||||
void drawBody(Canvas& canvas) override {
|
||||
nChanged = false;
|
||||
|
||||
const auto col = this->getColor("Accent");
|
||||
const auto colSel = this->getColor("Hovered");
|
||||
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 };
|
||||
|
|
@ -38,8 +23,8 @@ namespace tp {
|
|||
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, this->getValue("Rounding") * 1.5f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { this->getValue("Padding"), this->getValue("Padding") });
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, mRounding * 1.5f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, { mPadding, mPadding });
|
||||
|
||||
// ImGui::PushID((int) alni(this));
|
||||
ImGui::Begin(
|
||||
|
|
@ -65,11 +50,29 @@ namespace tp {
|
|||
ImGui::PopStyleVar(3);
|
||||
}
|
||||
|
||||
public:
|
||||
void updateConfigCache(WidgetManager& wm) override {
|
||||
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");
|
||||
}
|
||||
|
||||
public:
|
||||
enum { mMaxBufferSize = 512 };
|
||||
char mBuff[mMaxBufferSize] = "";
|
||||
bool nChanged = false;
|
||||
std::string mValue;
|
||||
std::string mId = "id";
|
||||
bool mMultiline = false;
|
||||
|
||||
RGBA mAccentColor;
|
||||
RGBA mHoveredColor;
|
||||
RGBA mBaseColor;
|
||||
halnf mRounding = 0;
|
||||
halnf mPadding = 0;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,46 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "WidgetConfig.hpp"
|
||||
#include "EventHandler.hpp"
|
||||
#include "WidgetManager.hpp"
|
||||
|
||||
namespace tp {
|
||||
|
||||
template <typename Events, typename Canvas>
|
||||
class Widget {
|
||||
public:
|
||||
Widget() {
|
||||
this->mArea = { 0, 0, 100, 100 };
|
||||
}
|
||||
|
||||
[[nodiscard]] const RGBA& getColor(const std::string& name) const {
|
||||
const auto& node = cfg->values.get(name);
|
||||
if (node.type == WidgetConfig::Node::REF) {
|
||||
return globalCfg->configs.get(node.refGroup).values.get(node.refName).color;
|
||||
}
|
||||
return cfg->values.get(name).color;
|
||||
}
|
||||
|
||||
[[nodiscard]] halnf getValue(const std::string& name) const {
|
||||
const auto& node = cfg->values.get(name);
|
||||
if (node.type == WidgetConfig::Node::REF) {
|
||||
return globalCfg->configs.get(node.refGroup).values.get(node.refName).value;
|
||||
}
|
||||
return cfg->values.get(name).value;
|
||||
}
|
||||
|
||||
void addColor(const std::string& name, const RGBA& val) { cfg->values.put(name, WidgetConfig::Node(val)); }
|
||||
void addValue(const std::string& name, halnf val) { cfg->values.put(name, WidgetConfig::Node(val)); }
|
||||
|
||||
void addColor(const std::string& name, const std::string& presetName) {
|
||||
cfg->values.put(name, WidgetConfig::Node(presetName));
|
||||
}
|
||||
void addValue(const std::string& name, const std::string& presetName) {
|
||||
cfg->values.put(name, WidgetConfig::Node(presetName));
|
||||
}
|
||||
|
||||
void createConfig(const std::string& name) {
|
||||
globalCfg->configs.put(name, {});
|
||||
cfg = &globalCfg->configs.get(name);
|
||||
}
|
||||
Widget() { this->mArea = { 0, 0, 100, 100 }; }
|
||||
|
||||
virtual void proc(const Events& events, const tp::RectF& areaParent, const tp::RectF& aArea) {
|
||||
mVisible = areaParent.isOverlap(aArea);
|
||||
|
|
@ -49,18 +17,27 @@ namespace tp {
|
|||
}
|
||||
|
||||
this->mArea = aArea;
|
||||
this->mAreaParent = areaParent;
|
||||
|
||||
procBody(events);
|
||||
}
|
||||
|
||||
virtual void draw(Canvas& canvas) {
|
||||
if (!mVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
drawBody(canvas);
|
||||
}
|
||||
|
||||
virtual void procBody(const Events& events) {}
|
||||
virtual void drawBody(Canvas& canvas) {}
|
||||
|
||||
virtual void updateConfigCache(WidgetManager& wm) {}
|
||||
|
||||
public:
|
||||
GlobalGUIConfig* globalCfg = gGlobalGUIConfig;
|
||||
WidgetConfig* cfg = nullptr;
|
||||
RectF mArea;
|
||||
RectF mAreaParent;
|
||||
bool mVisible = false;
|
||||
};
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "Animations.hpp"
|
||||
#include "Map.hpp"
|
||||
#include "Rect.hpp"
|
||||
|
||||
#include "InputCodes.hpp"
|
||||
|
||||
namespace tp {
|
||||
|
||||
struct WidgetConfig {
|
||||
struct Node {
|
||||
enum Type { NONE, VAL, COL, REF };
|
||||
|
||||
halnf value = 0.f;
|
||||
RGBA color = {};
|
||||
|
||||
Type type = NONE;
|
||||
|
||||
std::string refGroup;
|
||||
std::string refName;
|
||||
|
||||
Node() = default;
|
||||
|
||||
explicit Node(halnf val) {
|
||||
type = VAL;
|
||||
value = val;
|
||||
}
|
||||
|
||||
explicit Node(const RGBA& val) {
|
||||
type = COL;
|
||||
color = val;
|
||||
}
|
||||
|
||||
explicit Node(const std::string& val) {
|
||||
refGroup = "Presets";
|
||||
refName = val;
|
||||
type = REF;
|
||||
}
|
||||
};
|
||||
|
||||
Map<std::string, Node> values;
|
||||
};
|
||||
|
||||
struct GlobalGUIConfig {
|
||||
GlobalGUIConfig() {
|
||||
configs.put("Presets", {});
|
||||
auto& presets = configs.get("Presets");
|
||||
|
||||
presets.values.put("FontSize", WidgetConfig::Node(15.f));
|
||||
presets.values.put("FontSizeDim", WidgetConfig::Node(12.f));
|
||||
presets.values.put("Rounding", WidgetConfig::Node(5.f));
|
||||
presets.values.put("Padding", WidgetConfig::Node(5.f));
|
||||
presets.values.put("HandleSize", WidgetConfig::Node(5.f));
|
||||
|
||||
presets.values.put("Background", WidgetConfig::Node(RGBA{ 0.03f, 0.03f, 0.03f, 1.f }));
|
||||
presets.values.put("Base", WidgetConfig::Node(RGBA{ 0.07f, 0.07f, 0.07f, 1.f }));
|
||||
presets.values.put("Accent", WidgetConfig::Node(RGBA{ 0.13f, 0.13f, 0.13f, 1.f }));
|
||||
presets.values.put("Interaction", WidgetConfig::Node(RGBA{ 0.33f, 0.33f, 0.3f, 1.f }));
|
||||
presets.values.put("Action", WidgetConfig::Node(RGBA{ 0.44f, 0.44f, 0.4f, 1.f }));
|
||||
presets.values.put("Front", WidgetConfig::Node(RGBA{ 1.f, 1.f, 1.f, 1.f }));
|
||||
presets.values.put("FrontDim", WidgetConfig::Node(RGBA{ 0.7f, 0.7f, 0.7f, 1.f }));
|
||||
}
|
||||
|
||||
Map<std::string, WidgetConfig> configs;
|
||||
|
||||
~GlobalGUIConfig() {
|
||||
configs.removeAll();
|
||||
}
|
||||
};
|
||||
|
||||
extern GlobalGUIConfig* gGlobalGUIConfig;
|
||||
}
|
||||
144
Widgets/public/WidgetManager.hpp
Normal file
144
Widgets/public/WidgetManager.hpp
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
#pragma once
|
||||
|
||||
#include "Animations.hpp"
|
||||
#include "Map.hpp"
|
||||
#include "Rect.hpp"
|
||||
|
||||
#include "InputCodes.hpp"
|
||||
#include "Buffer.hpp"
|
||||
|
||||
namespace tp {
|
||||
|
||||
struct WidgetConfig {
|
||||
|
||||
struct Shortcut {
|
||||
struct Condition {
|
||||
std::string name;
|
||||
std::string state;
|
||||
};
|
||||
|
||||
std::string callbackName;
|
||||
|
||||
Shortcut() = default;
|
||||
Shortcut(const InitialierList<Condition>&) {}
|
||||
};
|
||||
|
||||
struct Parameter {
|
||||
enum Type { NONE, VAL, COL };
|
||||
|
||||
halnf value = 0.f;
|
||||
RGBA color = {};
|
||||
Type type = NONE;
|
||||
bool globalReference = false;
|
||||
std::string globalId;
|
||||
|
||||
Parameter() = default;
|
||||
|
||||
explicit Parameter(halnf val) {
|
||||
type = VAL;
|
||||
value = val;
|
||||
}
|
||||
|
||||
explicit Parameter(const RGBA& val) {
|
||||
type = COL;
|
||||
color = val;
|
||||
}
|
||||
|
||||
explicit Parameter(const std::string& id, const Type& referenceType) {
|
||||
type = referenceType;
|
||||
globalId = id;
|
||||
globalReference = true;
|
||||
}
|
||||
};
|
||||
|
||||
Map<std::string, Parameter> mParameters;
|
||||
Buffer<Shortcut> mShortcuts;
|
||||
};
|
||||
|
||||
class WidgetManager {
|
||||
public:
|
||||
using Parameter = WidgetConfig::Parameter;
|
||||
|
||||
public:
|
||||
WidgetManager() { initGlobalParameters(); }
|
||||
~WidgetManager() { mConfigurations.removeAll(); }
|
||||
|
||||
const RGBA& getColor(const std::string& parameterId, const RGBA& defaultValue) {
|
||||
WidgetConfig& config = getWidgetConfig(mActiveId);
|
||||
Parameter& parameter = getParameter(config, parameterId, Parameter(defaultValue));
|
||||
return parameter.color;
|
||||
}
|
||||
|
||||
const RGBA& 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 getNumber(const std::string& parameterId, halnf defaultValue) {
|
||||
WidgetConfig& config = getWidgetConfig(mActiveId);
|
||||
Parameter& parameter = getParameter(config, parameterId, Parameter(defaultValue));
|
||||
return parameter.value;
|
||||
}
|
||||
|
||||
halnf 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 setActiveId(const std::string& id) { mActiveId = id; }
|
||||
|
||||
private:
|
||||
WidgetConfig& getWidgetConfig(const std::string& id) {
|
||||
auto idx = mConfigurations.presents(id);
|
||||
if (idx) return mConfigurations.getSlotVal(idx);
|
||||
mConfigurations.put(id, {});
|
||||
return mConfigurations.get(id);
|
||||
}
|
||||
|
||||
Parameter& 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 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 }));
|
||||
}
|
||||
|
||||
private:
|
||||
Map<std::string, WidgetConfig> mConfigurations;
|
||||
WidgetConfig mGlobalConfig;
|
||||
|
||||
RGBA mErrorColor = { 0, 0, 0, 1 };
|
||||
halnf mErrorNumber = 0;
|
||||
|
||||
std::string mActiveId;
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue