Cleanup widgets

This commit is contained in:
IlyaShurupov 2024-06-26 11:30:02 +03:00
parent 9e7704a446
commit bce1dbacc2
30 changed files with 705 additions and 654 deletions

View file

@ -17,8 +17,12 @@ void CollapsableMenu::eventProcess(const Events&) {
}
void CollapsableMenu::eventDraw(Canvas& canvas) {
canvas.rect(this->mArea, mBorderColor, rounding);
canvas.rect(this->mArea.shrink(mBorderSize), mMenuColor, rounding);
if (mBorders) {
canvas.rect(this->mArea, mBorderColor, rounding);
canvas.rect(this->mArea.shrink(mBorderSize), mMenuColor, rounding);
} else {
canvas.rect(this->mArea, mMenuColor, rounding);
}
}
void CollapsableMenu::addWidgetToMenu(Widget* widget) {
@ -60,7 +64,8 @@ void CollapsableMenu::updateGeometry() {
RectF CollapsableMenu::getHeaderRect() {
RectF out = { this->mArea.pos, { this->mArea.size.x, headerHeight } };
return out.shrink(mPadding);
if (mBorders) out = out.shrink(mPadding);
return out;
}
RectF CollapsableMenu::getBodyRect() {
@ -71,7 +76,7 @@ RectF CollapsableMenu::getBodyRect() {
if (mAdjustHeight) out.size.y = mBody.getContentSize();
if (mBody.getContentSize()) {
if (mBody.getContentSize() && mBorders) {
out = out.shrink(mPadding);
out.size.y += mPadding * 2 + 1;
}

View file

@ -1,249 +0,0 @@
#include "DockspaceWidget.hpp"
using namespace tp;
DockSpaceWidget::DockSpaceWidget() = default;
void DockSpaceWidget::addSideWidget(Widget* widget, Side side) {
if (mSideWidgets[side]) return;
mSideWidgets[side] = widget;
for (auto& order : mSideSplitOrder) {
if (order == -1) {
order = side;
break;
}
}
mChildWidgets.pushBack(widget);
widget->mIsDocked = true;
mSideHidden[side] = false;
}
void DockSpaceWidget::removeSideWidget(Side side) {
if (!mSideWidgets[side]) return;
bool removed = false;
for (ualni i = 0; i < 3; i++) {
if (mSideSplitOrder[i] == side) {
removed = true;
}
if (removed) {
mSideSplitOrder[i] = mSideSplitOrder[i + 1];
}
}
mSideSplitOrder[3] = -1;
auto widget = mSideWidgets[side];
mSideWidgets[side] = nullptr;
widget->mIsDocked = false;
mChildWidgets.removeNode(mChildWidgets.find(widget));
}
void DockSpaceWidget::setCenterWidget(Widget* widget) {
mChildWidgets.removeNode(mChildWidgets.find(mCenterWidget));
mCenterWidget = widget;
mChildWidgets.pushBack(mCenterWidget);
}
void DockSpaceWidget::toggleHiddenState(DockSpaceWidget::Side side) {
if (!isSideExists(side)) return;
mSideHidden[side] = !mSideHidden[side];
}
void DockSpaceWidget::eventProcess(const tp::Events& events) {
updateActiveWindow(events);
calculateSideAreas();
calculateResizeHandles();
// calculateHeaderAreas();
handleResizeEvents(events);
updateChildSideWidgets();
}
void DockSpaceWidget::eventDraw(Canvas& canvas) {
canvas.rect(this->mArea, mBackgroundColor, 0);
for (auto sizeHandle : mResizeHandles) {
if (sizeHandle->active) {
canvas.rect(sizeHandle->area.shrink(mPadding / 1.5f), mResizeHandleColorActive, 0);
} else if (sizeHandle->hover) {
canvas.rect(sizeHandle->area.shrink(mPadding / 1.5f), mResizeHandleColorHovered, 0);
}
}
for (auto& header : mSideHeaderAreas) {
canvas.rect(header, mResizeHandleColorActive, 0);
}
}
void DockSpaceWidget::updateActiveWindow(const tp::Events& events) {
if (this->mChildWidgets.size() > 1 && events.isPressed(InputID::MOUSE1)) {
Widget* activeChild = nullptr;
for (auto childNode = this->mChildWidgets.firstNode(); childNode; childNode = childNode->next) {
auto child = childNode->data;
if (child->mIsDocked) continue;
if (child->mArea.isInside(events.getPointer())) {
mChildWidgets.detach(childNode);
mChildWidgets.pushFront(childNode);
child->mHandlesEvents = true;
activeChild = child;
break;
}
}
if (activeChild) {
for (auto child : this->mChildWidgets) {
if (activeChild != child.data() && !child->mIsDocked) child->mHandlesEvents = false;
}
}
}
}
void DockSpaceWidget::calculateSideAreas() {
auto startArea = this->mArea;
for (ualni i = 0; i < 4; i++) {
const auto side = mSideSplitOrder[i];
if (side == -1) break;
if (mSideHidden[side]) continue;
bool vertical = side == TOP || side == BOTTOM;
bool opposite = side == BOTTOM || side == RIGHT;
const auto maxAbsoluteSize = startArea.size[vertical];
const auto paddingFactor = mSideSizePadding / maxAbsoluteSize;
mSideAbsoluteSize[side] =
clamp(mSideAbsoluteSize[side], maxAbsoluteSize * paddingFactor, maxAbsoluteSize * (1.f - paddingFactor));
auto factor = mSideAbsoluteSize[side] / startArea.size[vertical];
if (opposite) factor = factor * -1 + 1;
if (!vertical) {
const auto first = startArea.splitByFactorHL(factor);
const auto second = startArea.splitByFactorHR(factor);
mSideAreas[side] = side == LEFT ? first : second;
startArea = side == LEFT ? second : first;
} else {
const auto first = startArea.splitByFactorVT(factor);
const auto second = startArea.splitByFactorVB(factor);
mSideAreas[side] = side == TOP ? first : second;
startArea = side == TOP ? second : first;
}
mSideAreas[side] = mSideAreas[side].shrink(mPadding);
}
mCenterArea = startArea.shrink(mPadding);
}
void DockSpaceWidget::calculateResizeHandles() {
mResizeHandles.clear();
RectF rec;
if (isSideVisible(LEFT)) {
rec = { mSideAreas[LEFT].p4(), { mPadding * 2, mSideAreas[LEFT].size.y } };
mResizeHandles.append({ rec, LEFT, 0, mCenterArea.p3().x });
}
if (isSideVisible(RIGHT)) {
rec = { mSideAreas[RIGHT].p1(), { mPadding * 2, mSideAreas[RIGHT].size.y } };
rec.x -= mPadding * 2;
mResizeHandles.append({ rec, RIGHT, mCenterArea.p1().x, rec.p3().x });
}
if (isSideVisible(TOP)) {
rec = { mSideAreas[TOP].p2(), { mSideAreas[TOP].size.x, mPadding * 2 } };
mResizeHandles.append({ rec, TOP, 0, mCenterArea.p2().y });
}
if (isSideVisible(BOTTOM)) {
rec = { mSideAreas[BOTTOM].p1(), { mSideAreas[BOTTOM].size.x, mPadding * 2 } };
rec.y -= mPadding * 2;
mResizeHandles.append({ rec, BOTTOM, mCenterArea.p1().y, rec.p2().y });
}
}
void DockSpaceWidget::handleResizeEvents(const Events& events) {
for (auto resizeHandle : mResizeHandles) {
resizeHandle->hover = false;
if (resizeHandle->area.isInside(events.getPointerPrev())) {
resizeHandle->hover = true;
}
}
if (events.isDown(InputID::MOUSE1)) {
for (auto resizeHandle : mResizeHandles) {
resizeHandle->active = false;
if (resizeHandle->area.isInside(events.getPointerPrev())) {
auto factorDeltaVec = events.getPointerDelta();
halnf factorDelta = factorDeltaVec[(resizeHandle->side == TOP || resizeHandle->side == BOTTOM)];
if (resizeHandle->side == BOTTOM || resizeHandle->side == RIGHT) factorDelta *= -1;
mSideAbsoluteSize[resizeHandle->side] += factorDelta;
resizeHandle->active = true;
}
}
}
}
void DockSpaceWidget::updateChildSideWidgets() {
// Update Child Widgets
{
for (ualni i = 0; i < 4; i++) {
if (!isSideExists(Side(i))) continue;
if (!isSideVisible(Side(i))) {
mSideWidgets[i]->mEnable = false;
} else {
mSideWidgets[i]->setArea(mSideAreas[i]);
mSideWidgets[i]->mEnable = true;
}
}
if (mCenterWidget) mCenterWidget->setArea(mCenterArea);
}
// update depth order
/*
if (mChildWidgets.size() > 1) {
for (auto sideChild : mSideWidgets) {
if (!sideChild) continue;
for (auto childNode = mChildWidgets.firstNode(); childNode; childNode = childNode->next) {
if (childNode->data == sideChild) {
mChildWidgets.detach(childNode);
mChildWidgets.pushBack(childNode);
break;
}
}
}
}
*/
}
void DockSpaceWidget::calculateHeaderAreas() {
for (ualni i = 0; i < 4; i++) {
if (!isSideVisible(Side(i))) continue;
const auto factor = mHeaderSize / mSideAreas[i].size.y;
mSideHeaderAreas[i] = mSideAreas[i].splitByFactorVT(factor);
mSideAreas[i] = mSideAreas[i].splitByFactorVB(factor);
mSideHeaderAreas[i].size.y -= mPadding;
}
}
bool DockSpaceWidget::isSideVisible(DockSpaceWidget::Side side) { return mSideWidgets[side] && !mSideHidden[side]; }
bool DockSpaceWidget::isSideExists(DockSpaceWidget::Side side) { return mSideWidgets[side]; }
ualni DockSpaceWidget::getVisibleSidesSize() {
ualni out = 0;
for (ualni i = 0; i < 4; i++) {
if (isSideVisible(Side(i))) out++;
}
return out;
}

View file

@ -0,0 +1,47 @@
#include "FloatingLayoutWidget.hpp"
using namespace tp;
FloatingLayoutWidget::FloatingLayoutWidget() = default;
void FloatingLayoutWidget::eventProcess(const tp::Events& events) {
updateActiveWindow(events);
}
void FloatingLayoutWidget::updateActiveWindow(const tp::Events& events) {
mIsPassThrough = true;
for (auto childNode = this->mChildWidgets.firstNode(); childNode; childNode = childNode->next) {
auto child = childNode->data;
if (child->mArea.isInside(events.getPointer())) {
mIsPassThrough = false;
}
}
if (events.isPressed(InputID::MOUSE1)) {
Widget* activeChild = nullptr;
for (auto childNode = this->mChildWidgets.firstNode(); childNode; childNode = childNode->next) {
auto child = childNode->data;
if (child->mArea.isInside(events.getPointer())) {
mChildWidgets.detach(childNode);
mChildWidgets.pushFront(childNode);
child->mHandlesEvents = true;
activeChild = child;
break;
}
}
if (activeChild) {
for (auto child : this->mChildWidgets) {
if (activeChild != child.data() && !child->mIsDocked) child->mHandlesEvents = false;
}
}
}
}
bool FloatingLayoutWidget::handlesEvent() const { return !mIsPassThrough; }

View file

@ -12,7 +12,7 @@ void FloatingWidget::eventProcess(const Events& events) {
mActionStartRelativePos = events.getPointerPrev() - this->mArea.pos;
checkFloating(events);
checkResizing(events);
if (mResizable) checkResizing(events);
CollapsableMenu::eventProcess(events);
}
@ -20,7 +20,7 @@ void FloatingWidget::eventProcess(const Events& events) {
void FloatingWidget::eventDraw(Canvas& canvas) {
CollapsableMenu::eventDraw(canvas);
if (!this->getCollapsed()) {
if (!this->getCollapsed() && mResizable) {
auto rect = getResizeHandle();
canvas.rect(rect, mResizeHandleColor, 0);
canvas.circle(rect.pos - this->mBorderSize, rect.w, this->mMenuColor);
@ -78,3 +78,9 @@ RectF FloatingWidget::getResizeHandle() {
auto pos = this->mArea.pos + this->mArea.size - size;
return { pos, size };
}
bool FloatingWidget::isFloating() const { return mFloating; }
void FloatingWidget::stopFloating() {
mFloating = false;
}

View file

@ -0,0 +1,328 @@
#include "GridLayoutWidget.hpp"
using namespace tp;
GridLayoutWidget::GridLayoutWidget() {
mSideWidgets[0].side = LEFT;
mSideWidgets[1].side = TOP;
mSideWidgets[2].side = RIGHT;
mSideWidgets[3].side = BOTTOM;
}
void GridLayoutWidget::addSideWidget(Widget* widget, Side side) {
if (isSideExists(side)) return;
auto& sideWidget = mSideWidgets[side];
sideWidget.widget = widget;
for (auto& order : mSideWidgets) {
if (order.order == -1) {
order.order = side;
break;
}
}
sideWidget.hidden = false;
mChildWidgets.pushBack(widget);
widget->mIsDocked = true;
}
void GridLayoutWidget::removeSideWidget(Side side) {
if (!isSideExists(side)) return;
bool removed = false;
for (ualni i = 0; i < 3; i++) {
if (mSideWidgets[i].order == side) {
removed = true;
}
if (removed) {
swap(mSideWidgets[i].order, mSideWidgets[i + 1].order);
}
}
mSideWidgets[3].order = -1;
auto widget = mSideWidgets[side].widget;
widget->mIsDocked = false;
mChildWidgets.removeNode(mChildWidgets.find(widget));
mSideWidgets[side].widget = nullptr;
}
void GridLayoutWidget::setCenterWidget(Widget* widget) {
mChildWidgets.removeNode(mChildWidgets.find(mCenterWidget));
mCenterWidget = widget;
mChildWidgets.pushBack(mCenterWidget);
}
void GridLayoutWidget::toggleHiddenState(GridLayoutWidget::Side side) {
if (!isSideExists(side)) return;
mSideWidgets[side].hidden = !mSideWidgets[side].hidden;
}
void GridLayoutWidget::eventProcess(const tp::Events& events) {
calculateSideAreas();
calculateResizeHandles();
// calculateHeaderAreas();
handlePreview(events);
handleResizeEvents(events);
updateChildSideWidgets();
}
void GridLayoutWidget::eventDraw(Canvas& canvas) {
canvas.rect(this->mArea, mBackgroundColor, 0);
for (auto& sideWidget : mSideWidgets) {
if (!isSideVisible(sideWidget.side)) continue;
auto& handle = sideWidget.resizeHandle;
if (handle.active) {
canvas.rect(handle.area.shrink(mPadding / 1.5f), mResizeHandleColorActive, 0);
} else if (handle.hover) {
canvas.rect(handle.area.shrink(mPadding / 1.5f), mResizeHandleColorHovered, 0);
}
}
for (auto& sideWidget : mSideWidgets) {
if (!isSideVisible(sideWidget.side)) continue;
canvas.rect(sideWidget.headerArea, mResizeHandleColorActive, 0);
}
}
void GridLayoutWidget::eventDrawOver(Canvas& canvas) {
if (!mPreview) return;
if (mPreviewSide != NONE) canvas.rect(mPreviewArea.shrink(mPadding * 2), mPreviewColor, mRounding);
for (auto& sideWidget : mSideWidgets) {
if (sideWidget.widget) continue;
canvas.rect(sideWidget.previewHandleArea, mPreviewColor, mRounding);
}
}
void GridLayoutWidget::calculateSideAreas() {
auto startArea = this->mArea;
for (auto& sideWidget : mSideWidgets) {
const auto side = sideWidget.order;
if (side == -1) break;
if (!isSideVisible(Side(side))) continue;
bool vertical = side == TOP || side == BOTTOM;
bool opposite = side == BOTTOM || side == RIGHT;
auto& sideSize = mSideWidgets[side].absoluteSize;
auto factor = sideSize / startArea.size[vertical];
if (opposite) factor = factor * -1 + 1;
auto& area = mSideWidgets[side].area;
if (!vertical) {
const auto first = startArea.splitByFactorHL(factor);
const auto second = startArea.splitByFactorHR(factor);
area = side == LEFT ? first : second;
startArea = side == LEFT ? second : first;
} else {
const auto first = startArea.splitByFactorVT(factor);
const auto second = startArea.splitByFactorVB(factor);
area = side == TOP ? first : second;
startArea = side == TOP ? second : first;
}
area = area.shrink(mPadding);
}
mCenterArea = startArea.shrink(mPadding);
}
void GridLayoutWidget::calculateResizeHandles() {
RectF rec;
if (isSideVisible(LEFT)) {
auto& side = mSideWidgets[LEFT];
rec = { side.area.p4(), { mPadding * 2, side.area.size.y } };
side.resizeHandle = { rec, 0, mCenterArea.p3().x };
}
if (isSideVisible(RIGHT)) {
auto& side = mSideWidgets[RIGHT];
rec = { side.area.p1(), { mPadding * 2, side.area.size.y } };
rec.x -= mPadding * 2;
side.resizeHandle = { rec, 0, (this->mArea.p3() - mCenterArea.p1()).x };
}
if (isSideVisible(TOP)) {
auto& side = mSideWidgets[TOP];
rec = { side.area.p2(), { side.area.size.x, mPadding * 2 } };
side.resizeHandle = { rec, 0, mCenterArea.p2().y };
}
if (isSideVisible(BOTTOM)) {
auto& side = mSideWidgets[BOTTOM];
rec = { side.area.p1(), { side.area.size.x, mPadding * 2 } };
rec.y -= mPadding * 2;
side.resizeHandle = { rec, 0, (this->mArea.p3() - mCenterArea.p1()).y };
}
}
void GridLayoutWidget::handleResizeEvents(const Events& events) {
for (auto& sideWidget : mSideWidgets) {
auto& sideSize = sideWidget.absoluteSize;
auto& resizeHandle = sideWidget.resizeHandle;
if (resizeHandle.end < mSideSizePadding * 2) {
sideSize = resizeHandle.end / 2.f;
} else {
sideSize = clamp(sideSize, resizeHandle.start + mSideSizePadding, resizeHandle.end - mSideSizePadding);
}
}
for (auto& sideWidget : mSideWidgets) {
sideWidget.resizeHandle.hover = false;
if (sideWidget.resizeHandle.area.isInside(events.getPointerPrev())) {
sideWidget.resizeHandle.hover = true;
}
}
for (auto& sideWidget : mSideWidgets) {
sideWidget.resizeHandle.active = false;
}
if (mPreview) return;
auto resizeSideWidget = [&events](SideWidgetData& sideWidget, Vec2F deltaVec) {
halnf delta = deltaVec[(sideWidget.side == TOP || sideWidget.side == BOTTOM)];
if (sideWidget.side == BOTTOM || sideWidget.side == RIGHT) delta *= -1;
sideWidget.absoluteSize += delta;
sideWidget.resizeHandle.active = true;
};
if (events.isDown(InputID::MOUSE1)) {
for (auto& sideWidget : mSideWidgets) {
if (sideWidget.resizeHandle.area.isInside(events.getPointerPrev())) {
resizeSideWidget(sideWidget, events.getPointerDelta());
}
}
}
if (events.isDown(InputID::LEFT_ALT)) {
const auto pointer = events.getPointerPrev();
if (!mCenterArea.isInside(pointer)) return;
if (events.isPressed(InputID::MOUSE1)) {
for (auto i : { 0, 1 }) {
const auto step = mCenterArea.size[i] / 3.f;
const auto rec1 = mCenterArea.pos[i];
const auto pos = pointer[i];
if (pos > rec1 && pos < rec1 + step) resizeType[i] = 0;
if (pos > rec1 + step && pos < rec1 + step * 2) resizeType[i] = 1;
if (pos > rec1 + step * 2) resizeType[i] = 2;
}
} else if (events.isDown(InputID::MOUSE1)) {
const auto deltaVec = events.getPointerDelta();
if (resizeType[0] == 0) resizeSideWidget(mSideWidgets[LEFT], deltaVec);
if (resizeType[1] == 0) resizeSideWidget(mSideWidgets[TOP], deltaVec);
if (resizeType[0] == 2) resizeSideWidget(mSideWidgets[RIGHT], deltaVec);
if (resizeType[1] == 2) resizeSideWidget(mSideWidgets[BOTTOM], deltaVec);
}
}
}
void GridLayoutWidget::updateChildSideWidgets() {
// Update Child Widgets
{
for (ualni i = 0; i < 4; i++) {
if (!isSideExists(Side(i))) continue;
auto widget = mSideWidgets[i].widget;
if (!isSideVisible(Side(i))) {
widget->mEnable = false;
} else {
widget->setArea(mSideWidgets[i].area);
widget->mEnable = true;
}
}
if (mCenterWidget) mCenterWidget->setArea(mCenterArea);
}
// update depth order
/*
if (mChildWidgets.size() > 1) {
for (auto sideChild : mSideWidgets) {
if (!sideChild) continue;
for (auto childNode = mChildWidgets.firstNode(); childNode; childNode = childNode->next) {
if (childNode->data == sideChild) {
mChildWidgets.detach(childNode);
mChildWidgets.pushBack(childNode);
break;
}
}
}
}
*/
}
void GridLayoutWidget::calculateHeaderAreas() {
for (ualni i = 0; i < 4; i++) {
if (!isSideVisible(Side(i))) continue;
auto& area = mSideWidgets[i].area;
const auto factor = mHeaderSize / area.size.y;
mSideWidgets[i].headerArea = area.splitByFactorVT(factor);
area = area.splitByFactorVB(factor);
mSideWidgets[i].headerArea.size.y -= mPadding;
}
}
bool GridLayoutWidget::isSideVisible(GridLayoutWidget::Side side) {
return isSideExists(side) && !mSideWidgets[side].hidden;
}
bool GridLayoutWidget::isSideExists(GridLayoutWidget::Side side) { return mSideWidgets[side].widget; }
ualni GridLayoutWidget::getVisibleSidesSize() {
ualni out = 0;
for (ualni i = 0; i < 4; i++) {
if (isSideVisible(Side(i))) out++;
}
return out;
}
GridLayoutWidget::Side GridLayoutWidget::getPreviewSide() { return mPreviewSide; }
void GridLayoutWidget::handlePreview(const Events& events) {
if (!mPreview) {
mPreviewSide = NONE;
return;
}
const halnf factor = 0.3;
const halnf handleFactor = 0.1;
const auto handleSize = min(mCenterArea.size.x, mCenterArea.size.y) * handleFactor;
for (auto& sideWidget : mSideWidgets) {
if (sideWidget.widget) continue;
switch (sideWidget.side) {
case TOP: sideWidget.area = mCenterArea.splitByFactorVT(factor); break;
case BOTTOM: sideWidget.area = mCenterArea.splitByFactorVB(1 - factor); break;
case LEFT: sideWidget.area = mCenterArea.splitByFactorHL(factor); break;
case RIGHT: sideWidget.area = mCenterArea.splitByFactorHR(1 - factor); break;
default: break;
}
sideWidget.area = sideWidget.area.shrink(mPadding * 2);
sideWidget.previewHandleArea = sideWidget.area.getSizedFromCenter({ handleSize, handleSize });
}
mPreviewArea = {};
mPreviewSide = NONE;
for (auto& sideWidget : mSideWidgets) {
if (sideWidget.widget) continue;
if (sideWidget.previewHandleArea.isInside(events.getPointer())) {
mPreviewArea = sideWidget.area;
mPreviewSide = sideWidget.side;
}
}
}

View file

@ -13,7 +13,7 @@ void ScrollBarWidget::eventProcess(const Events& events) {
return;
}
if (events.getScrollY() != 0) {
if (events.getScrollY() != 0 && mArea.isInside(events.getPointer())) {
auto offset = events.getScrollY() < 0 ? 1.0f : -1.0f;
mPositionFraction += mSizeFraction * offset * 0.3f;
mPositionFraction = tp::clamp(mPositionFraction, 0.f, 1.f - mSizeFraction);
@ -98,7 +98,7 @@ void ScrollableWindow::eventProcess(const Events& events) {
// to account all changed geometry of child widgets
for (auto widget : content) {
widget->procWrapper(events, this->mArea);
widget->procWrapper(events, mContentWidget.mVisibleArea);
}
updateContents(content);

View file

@ -19,7 +19,8 @@ void SliderWidget::eventProcess(const Events& events) {
}
void SliderWidget::eventDraw(Canvas& canvas) {
canvas.rect(this->mArea, defaultColor, rounding);
canvas.rect(this->mArea, handleColor, rounding);
canvas.rect(this->mArea.shrink(borderSize), defaultColor, rounding);
canvas.rect(getHandle(), handleColor, rounding);
}
@ -31,8 +32,9 @@ RectF SliderWidget::getHandle() const {
void SliderWidget::eventUpdateConfiguration(WidgetManager& wm) {
wm.setActiveId("Slider");
defaultColor = wm.getColor("Default", "Base");
handleColor = wm.getColor("Handle", "Accent");
handleSize = wm.getNumber("HandleSize", 20.f);
handleColor = wm.getColor("Handle", RGBA(0.3f, 0.3f, 0.3f, 1.f));
borderSize = wm.getNumber("BorderSize", 2);
handleSize = wm.getNumber("HandleSize", 15.f);
rounding = wm.getNumber("Rounding", "Rounding");
}

View file

@ -1,135 +0,0 @@
#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);
}

View file

@ -22,7 +22,7 @@ void Widget::procWrapper(const Events& events, const RectF& parentArea) {
eventProcess(events);
for (auto child : mChildWidgets) {
child->procWrapper(events, getArea());
child->procWrapper(events, mVisibleArea);
}
}
}
@ -38,6 +38,8 @@ void Widget::drawWrapper(Canvas& canvas) {
child->data->drawWrapper(canvas);
}
canvas.popClamp();
eventDrawOver(canvas);
}
void Widget::updateConfigWrapper(WidgetManager& wm) {
@ -52,6 +54,7 @@ void Widget::updateConfigWrapper(WidgetManager& wm) {
void Widget::eventProcess(const Events& events) {}
void Widget::eventDraw(Canvas& canvas) {}
void Widget::eventDrawOver(Canvas& canvas) {}
void Widget::eventUpdateConfiguration(WidgetManager& wm) {}
void Widget::eventVisible(const Events& events) {}
@ -66,6 +69,8 @@ void Widget::eventReleased(const Events& events) {}
void Widget::checkVisibility(const Events& events, const RectF& parentArea) {
const bool currentVisibility = parentArea.isOverlap(getArea());
parentArea.calcIntersection(mArea, mVisibleArea);
if (currentVisibility != mVisible) {
if (currentVisibility) eventVisible(events);
else eventNotVisible(events);
@ -81,7 +86,7 @@ void Widget::checkVisibility(const Events& events, const RectF& parentArea) {
}
void Widget::checkFocus(const Events& events) {
const bool currentFocus = getArea().isInside(events.getPointer());
const bool currentFocus = mVisibleArea.isInside(events.getPointer());
if (currentFocus != mInFocus) {
if (currentFocus) eventFocusEnter(events);
@ -110,7 +115,7 @@ void Widget::checkClicked(const Events& events) {
mHolding = false;
}
} else {
if (events.isPressed(InputID::MOUSE1)) {
if (events.isPressed(InputID::MOUSE1) && mVisibleArea.isInside(events.getPointer())) {
eventPressed(events);
mHolding = true;
mPressed = true;

View file

@ -0,0 +1,72 @@
#include "WorkspaceWidget.hpp"
using namespace tp;
WorkspaceWidget::WorkspaceWidget() {
this->mChildWidgets.pushBack(&mFloatingLayer);
this->mChildWidgets.pushBack(&mDockSpace);
}
void WorkspaceWidget::eventProcess(const Events& events) {
mDockSpace.setArea(this->mArea);
mFloatingLayer.setArea(this->mArea);
mDockSpace.mPreview = false;
mDockSpace.mHandlesEvents = !mFloatingLayer.handlesEvent();
for (auto floatingChild : mFloatingLayer.mChildWidgets) {
auto widget = dynamic_cast<FloatingWidget*>(floatingChild.data());
if (!widget) continue;
if (widget->isFloating()) {
if (widget->isReleased()) {
auto side = mDockSpace.getPreviewSide();
if (side != GridLayoutWidget::NONE) {
mFloatingLayer.mChildWidgets.removeNode(mFloatingLayer.mChildWidgets.find(widget));
widget->setCollapsed(true);
widget->stopFloating();
mDockSpace.addSideWidget(widget, side);
}
} else {
mDockSpace.mHandlesEvents = true;
mDockSpace.mPreview = true;
}
}
}
for (auto& dockedChild : mDockSpace.mSideWidgets) {
auto widget = dynamic_cast<FloatingWidget*>(dockedChild.widget);
if (!widget) continue;
if (widget->isFloating()) {
mDockSpace.removeSideWidget(dockedChild.side);
mFloatingLayer.mChildWidgets.pushBack(widget);
widget->mArea.pos = events.getPointer() - 20;
widget->mArea.size = mDefaultFloatSize;
widget->mResizable = true;
// widget->mBorders = true;
}
}
// toggle hide state
if (events.isDown(InputID::LEFT_ALT)) {
if (events.isPressed(InputID::N1)) {
mDockSpace.toggleHiddenState(GridLayoutWidget::LEFT);
} else if (events.isPressed(InputID::N2)) {
mDockSpace.toggleHiddenState(GridLayoutWidget::TOP);
} else if (events.isPressed(InputID::N3)) {
mDockSpace.toggleHiddenState(GridLayoutWidget::RIGHT);
} else if (events.isPressed(InputID::N4)) {
mDockSpace.toggleHiddenState(GridLayoutWidget::BOTTOM);
}
}
for (auto& dockedChild : mDockSpace.mSideWidgets) {
auto widget = dynamic_cast<FloatingWidget*>(dockedChild.widget);
if (!widget) continue;
widget->setCollapsed(false);
widget->mResizable = false;
// widget->mBorders = false;
}
}