Added X scrollbar to scroll area, and added toolbar for phone drawing program
This commit is contained in:
parent
6a05026f85
commit
74bc17f570
11 changed files with 284 additions and 50 deletions
|
|
@ -398,6 +398,36 @@ void DrawingProgram::toolbar_gui(Toolbar& t) {
|
|||
});
|
||||
}
|
||||
|
||||
void DrawingProgram::phone_bottom_toolbar_gui(PhoneDrawingProgramScreen& t) {
|
||||
using namespace GUIStuff;
|
||||
using namespace ElementHelpers;
|
||||
|
||||
GUIManager& gui = world.main.g.gui;
|
||||
|
||||
auto tool_button = [&](const char* id, const std::string& svgPath, DrawingProgramToolType toolType) {
|
||||
svg_icon_button(gui, id, svgPath, {
|
||||
.drawType = SelectableButton::DrawType::TRANSPARENT_ALL,
|
||||
.isSelected = drawTool->get_type() == toolType,
|
||||
.onClick = [&, toolType] {
|
||||
switch_to_tool(toolType);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
tool_button("Brush Toolbar Button", "data/icons/brush.svg", DrawingProgramToolType::BRUSH);
|
||||
tool_button("Eraser Toolbar Button", "data/icons/eraser.svg", DrawingProgramToolType::ERASER);
|
||||
tool_button("Line Toolbar Button", "data/icons/line.svg", DrawingProgramToolType::LINE);
|
||||
tool_button("Text Toolbar Button", "data/icons/text.svg", DrawingProgramToolType::TEXTBOX);
|
||||
tool_button("Ellipse Toolbar Button", "data/icons/circle.svg", DrawingProgramToolType::ELLIPSE);
|
||||
tool_button("Rect Toolbar Button", "data/icons/rectangle.svg", DrawingProgramToolType::RECTANGLE);
|
||||
tool_button("RectSelect Toolbar Button", "data/icons/rectselect.svg", DrawingProgramToolType::RECTSELECT);
|
||||
tool_button("LassoSelect Toolbar Button", "data/icons/lassoselect.svg", DrawingProgramToolType::LASSOSELECT);
|
||||
tool_button("Edit Toolbar Button", "data/icons/cursor.svg", DrawingProgramToolType::EDIT);
|
||||
tool_button("Eyedropper Toolbar Button", "data/icons/eyedropper.svg", DrawingProgramToolType::EYEDROPPER);
|
||||
tool_button("Zoom Canvas Toolbar Button", "data/icons/zoom.svg", DrawingProgramToolType::ZOOM);
|
||||
tool_button("Pan Canvas Toolbar Button", "data/icons/hand.svg", DrawingProgramToolType::PAN);
|
||||
}
|
||||
|
||||
void DrawingProgram::right_click_popup_gui(Toolbar& t) {
|
||||
if(rightClickPopupLocation.has_value())
|
||||
drawTool->right_click_popup_gui(t, rightClickPopupLocation.value());
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
#include "DrawingProgramSelection.hpp"
|
||||
|
||||
class World;
|
||||
class PhoneDrawingProgramScreen;
|
||||
|
||||
class DrawingProgram {
|
||||
public:
|
||||
|
|
@ -28,6 +29,7 @@ class DrawingProgram {
|
|||
void toolbar_gui(Toolbar& t);
|
||||
void tool_options_gui(Toolbar& t);
|
||||
void right_click_popup_gui(Toolbar& t);
|
||||
void phone_bottom_toolbar_gui(PhoneDrawingProgramScreen& t);
|
||||
void update();
|
||||
void scale_up(const WorldScalar& scaleUpAmount);
|
||||
void draw(SkCanvas* canvas, const DrawData& drawData);
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ ScrollArea* scroll_area_many_entries(GUIManager& gui, const char* id, const Scro
|
|||
.scrollVertical = true,
|
||||
.clipHorizontal = options.clipHorizontal,
|
||||
.clipVertical = true,
|
||||
.showScrollbarY = true,
|
||||
.scrollbarY = options.scrollbar,
|
||||
.xAlign = options.xAlign,
|
||||
.yAlign = CLAY_ALIGN_Y_TOP,
|
||||
.innerContent = [&](const ScrollArea::InnerContentParameters& params) {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ struct ScrollBarManyEntriesOptions {
|
|||
bool growing = false; // If set to false, this element has a fixed size. Otherwise, is a growing element.
|
||||
Clay_LayoutAlignmentX xAlign = CLAY_ALIGN_X_LEFT;
|
||||
Clay_SizingAxis xElementSize = CLAY_SIZING_GROW(0);
|
||||
ScrollArea::ScrollbarType scrollbar = ScrollArea::ScrollbarType::NORMAL;
|
||||
std::function<void(size_t elementIndex)> elementContent;
|
||||
std::function<void(const ScrollArea::InnerContentParameters&)> innerContentExtraCallback;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ void GridScrollArea::layout(const Clay_ElementId& id, const Options& o) {
|
|||
size_t entriesPerRow = std::max<size_t>(rowWidth / options.entryWidth, 1);
|
||||
size_t rowCount = (options.entryCount + entriesPerRow - 1) / entriesPerRow;
|
||||
opts.entryCount = rowCount;
|
||||
opts.scrollbar = options.scrollbar;
|
||||
|
||||
uint16_t xPadding = 0;
|
||||
uint16_t xChildGap = 0;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ class GridScrollArea : public Element {
|
|||
float entryHeight;
|
||||
size_t entryCount;
|
||||
bool entryWidthIsMinimum = false;
|
||||
ScrollArea::ScrollbarType scrollbar = ScrollArea::ScrollbarType::NORMAL;
|
||||
std::function<void(size_t elementIndex)> elementContent;
|
||||
std::function<void(const ScrollArea::InnerContentParameters&)> innerContentExtraCallback;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@
|
|||
#include "../GUIManager.hpp"
|
||||
#include <Helpers/ConvertVec.hpp>
|
||||
#include <Helpers/Logger.hpp>
|
||||
#include "Helpers/MathExtras.hpp"
|
||||
#include "LayoutElement.hpp"
|
||||
|
||||
namespace GUIStuff {
|
||||
|
||||
constexpr float TOUCH_SCROLLER_WIDTH = 24.0f;
|
||||
constexpr float DESKTOP_SCROLLER_WIDTH = 12.0f;
|
||||
constexpr float SCROLL_WHEEL_SCROLL_SPEED = 20.0f;
|
||||
constexpr float SCROLL_DAMPING = 0.15f; // Damping on the scroll area velocity when its scrolling on its own
|
||||
constexpr float SCROLL_MINIMUM_MOTION = 0.15f; // When the scroll area is scrolling on its own, this is the minimum velocity required for it to continue
|
||||
constexpr float SCROLL_MAX_DAMPING = 0.0001f; // Damping on the scrollAreaMotionMax variable
|
||||
|
|
@ -33,7 +33,7 @@ void ScrollArea::layout(const Clay_ElementId& id, const Options& options) {
|
|||
auto& bb = boundingBox.value();
|
||||
clamp_scroll();
|
||||
|
||||
if(contentDimensions.y() > bb.height()) {
|
||||
if((contentDimensions.y() > bb.height() && opts.scrollVertical) || (contentDimensions.x() > bb.width() && opts.scrollHorizontal)) {
|
||||
gui.in_dynamic_area([&] {
|
||||
opts.innerContent({.contentDimensions = contentDimensions, .containerDimensions = bb.dim(), .scrollOffset = &scrollOffset});
|
||||
});
|
||||
|
|
@ -43,8 +43,19 @@ void ScrollArea::layout(const Clay_ElementId& id, const Options& options) {
|
|||
|
||||
clamp_scroll();
|
||||
|
||||
if(contentDimensions.y() > bb.height() && opts.showScrollbarY)
|
||||
if(contentDimensions.y() > bb.height() && opts.scrollVertical && opts.scrollbarY != ScrollbarType::NONE)
|
||||
y_scroll_bar();
|
||||
else {
|
||||
yScrollbar.scroller = nullptr;
|
||||
yScrollbar.scrollbar = nullptr;
|
||||
}
|
||||
|
||||
if(contentDimensions.x() > bb.width() && opts.scrollHorizontal && opts.scrollbarX != ScrollbarType::NONE)
|
||||
x_scroll_bar();
|
||||
else {
|
||||
xScrollbar.scroller = nullptr;
|
||||
xScrollbar.scrollbar = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -59,7 +70,7 @@ void ScrollArea::y_scroll_bar() {
|
|||
float areaAboveScrollerSize = scrollerPos * (sAreaDim - scrollerSize);
|
||||
|
||||
gui.set_z_index(gui.get_z_index() + 1, [&] {
|
||||
gui.element<LayoutElement>("y scroll bar", [&] (LayoutElement*, const Clay_ElementId& lId) {
|
||||
yScrollbar.scrollbar = gui.element<LayoutElement>("y scroll bar", [&] (LayoutElement*, const Clay_ElementId& lId) {
|
||||
CLAY(lId, {
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIXED(gui.io.isTouchDevice ? TOUCH_SCROLLER_WIDTH : DESKTOP_SCROLLER_WIDTH), .height = CLAY_SIZING_GROW(0)},
|
||||
|
|
@ -76,9 +87,9 @@ void ScrollArea::y_scroll_bar() {
|
|||
}
|
||||
}) {
|
||||
SkColor4f scrollerColor;
|
||||
if(isScrollbarHeldY)
|
||||
if(yScrollbar.isScrollbarHeld)
|
||||
scrollerColor = gui.io.theme->fillColor1;
|
||||
else if(isScrollbarHoveredY)
|
||||
else if(yScrollbar.isScrollbarHovered)
|
||||
scrollerColor = gui.io.theme->fillColor1;
|
||||
else
|
||||
scrollerColor = gui.io.theme->fillColor2;
|
||||
|
|
@ -89,7 +100,7 @@ void ScrollArea::y_scroll_bar() {
|
|||
}
|
||||
}) {}
|
||||
|
||||
scrollerY = gui.element<LayoutElement>("scroller", [&] (LayoutElement*, const Clay_ElementId& lId2) {
|
||||
yScrollbar.scroller = gui.element<LayoutElement>("scroller", [&] (LayoutElement*, const Clay_ElementId& lId2) {
|
||||
CLAY(lId2, {
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(scrollerSize)},
|
||||
|
|
@ -101,7 +112,7 @@ void ScrollArea::y_scroll_bar() {
|
|||
.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}
|
||||
}) {}
|
||||
float scrollerWidthPercent = 0.0f;
|
||||
bool highlighted = isHoveringOverScrollerY || isScrollbarHeldY;
|
||||
bool highlighted = yScrollbar.isHoveringOverScroller || yScrollbar.isScrollbarHeld || (!gui.io.isTouchDevice && yScrollbar.isScrollbarHovered);
|
||||
if(gui.io.isTouchDevice)
|
||||
scrollerWidthPercent = highlighted ? 0.6f : 0.2f;
|
||||
else
|
||||
|
|
@ -118,55 +129,55 @@ void ScrollArea::y_scroll_bar() {
|
|||
}
|
||||
}, LayoutElement::Callbacks{
|
||||
.onClick = [&, scrollPosMax, sAreaStart, sAreaDim, scrollerSize, areaAboveScrollerSize](LayoutElement* t, const InputManager::MouseButtonCallbackArgs& button) {
|
||||
bool newIsHoveringOverScrollerY = scrollerY->mouseHovering && (button.deviceType != InputManager::MouseDeviceType::TOUCH || button.down);
|
||||
bool newIsScrollbarHoveredY = t->mouseHovering && (button.deviceType != InputManager::MouseDeviceType::TOUCH || button.down);
|
||||
if(isHoveringOverScrollerY != newIsHoveringOverScrollerY) {
|
||||
isHoveringOverScrollerY = newIsHoveringOverScrollerY;
|
||||
bool newIsHoveringOverScroller = yScrollbar.scroller->mouseHovering && (button.deviceType != InputManager::MouseDeviceType::TOUCH || button.down);
|
||||
bool newIsScrollbarHovered = t->mouseHovering && (button.deviceType != InputManager::MouseDeviceType::TOUCH || button.down);
|
||||
if(yScrollbar.isHoveringOverScroller != newIsHoveringOverScroller) {
|
||||
yScrollbar.isHoveringOverScroller = newIsHoveringOverScroller;
|
||||
gui.set_to_layout();
|
||||
}
|
||||
if(isScrollbarHoveredY != newIsScrollbarHoveredY) {
|
||||
isScrollbarHoveredY = newIsScrollbarHoveredY;
|
||||
if(yScrollbar.isScrollbarHovered != newIsScrollbarHovered) {
|
||||
yScrollbar.isScrollbarHovered = newIsScrollbarHovered;
|
||||
gui.set_to_layout();
|
||||
}
|
||||
if(button.button == InputManager::MouseButton::LEFT) {
|
||||
if(button.down && isScrollbarHoveredY) {
|
||||
isScrollbarHeldY = true;
|
||||
if(isHoveringOverScrollerY)
|
||||
scrollerStartPosY = sAreaStart + areaAboveScrollerSize + scrollerSize * 0.5f;
|
||||
if(button.down && yScrollbar.isScrollbarHovered) {
|
||||
yScrollbar.isScrollbarHeld = true;
|
||||
if(yScrollbar.isHoveringOverScroller)
|
||||
yScrollbar.scrollerStartPos = sAreaStart + areaAboveScrollerSize + scrollerSize * 0.5f;
|
||||
else
|
||||
scrollerStartPosY = std::clamp(button.pos.y(), sAreaStart + scrollerSize * 0.5f, sAreaStart + sAreaDim - scrollerSize * 0.5f);
|
||||
mouseStartPosY = button.pos.y();
|
||||
yScrollbar.scrollerStartPos = std::clamp(button.pos.y(), sAreaStart + scrollerSize * 0.5f, sAreaStart + sAreaDim - scrollerSize * 0.5f);
|
||||
yScrollbar.mouseStartPos = button.pos.y();
|
||||
|
||||
float newScrollPosFrac;
|
||||
newScrollPosFrac = std::clamp((scrollerStartPosY - (mouseStartPosY - button.pos.y()) - sAreaStart - scrollerSize * 0.5f) / (sAreaDim - scrollerSize), 0.0f, 1.0f);
|
||||
newScrollPosFrac = std::clamp((yScrollbar.scrollerStartPos - (yScrollbar.mouseStartPos - button.pos.y()) - sAreaStart - scrollerSize * 0.5f) / (sAreaDim - scrollerSize), 0.0f, 1.0f);
|
||||
scrollOffset.y() = newScrollPosFrac * (-scrollPosMax);
|
||||
clamp_scroll();
|
||||
scrollAreaMotionMax = scrollAreaMotion = {0.0f, 0.0f};
|
||||
gui.set_to_layout();
|
||||
}
|
||||
else if(isScrollbarHeldY) {
|
||||
isScrollbarHeldY = false;
|
||||
else if(yScrollbar.isScrollbarHeld) {
|
||||
yScrollbar.isScrollbarHeld = false;
|
||||
scrollAreaMotionMax = scrollAreaMotion = {0.0f, 0.0f};
|
||||
gui.set_to_layout();
|
||||
}
|
||||
}
|
||||
},
|
||||
.onMotion = [&, scrollPosMax, sAreaStart, sAreaDim, scrollerSize](LayoutElement* t, const InputManager::MouseMotionCallbackArgs& motion) {
|
||||
bool newIsHoveringOverScrollerY = scrollerY->mouseHovering && motion.deviceType != InputManager::MouseDeviceType::TOUCH;
|
||||
bool newIsScrollbarHoveredY = t->mouseHovering && motion.deviceType != InputManager::MouseDeviceType::TOUCH;
|
||||
if(isHoveringOverScrollerY != newIsHoveringOverScrollerY) {
|
||||
isHoveringOverScrollerY = newIsHoveringOverScrollerY;
|
||||
bool newIsHoveringOverScroller = yScrollbar.scroller->mouseHovering && motion.deviceType != InputManager::MouseDeviceType::TOUCH;
|
||||
bool newIsScrollbarHovered = t->mouseHovering && motion.deviceType != InputManager::MouseDeviceType::TOUCH;
|
||||
if(yScrollbar.isHoveringOverScroller != newIsHoveringOverScroller) {
|
||||
yScrollbar.isHoveringOverScroller = newIsHoveringOverScroller;
|
||||
gui.set_to_layout();
|
||||
}
|
||||
if(isScrollbarHoveredY != newIsScrollbarHoveredY) {
|
||||
isScrollbarHoveredY = newIsScrollbarHoveredY;
|
||||
if(yScrollbar.isScrollbarHovered != newIsScrollbarHovered) {
|
||||
yScrollbar.isScrollbarHovered = newIsScrollbarHovered;
|
||||
gui.set_to_layout();
|
||||
}
|
||||
if(isScrollbarHeldY) {
|
||||
if(yScrollbar.isScrollbarHeld) {
|
||||
float oldScrollOffset = scrollOffset.y();
|
||||
|
||||
float newScrollPosFrac;
|
||||
newScrollPosFrac = std::clamp((scrollerStartPosY - (mouseStartPosY - motion.pos.y()) - sAreaStart - scrollerSize * 0.5f) / (sAreaDim - scrollerSize), 0.0f, 1.0f);
|
||||
newScrollPosFrac = std::clamp((yScrollbar.scrollerStartPos - (yScrollbar.mouseStartPos - motion.pos.y()) - sAreaStart - scrollerSize * 0.5f) / (sAreaDim - scrollerSize), 0.0f, 1.0f);
|
||||
scrollOffset.y() = newScrollPosFrac * (-scrollPosMax);
|
||||
clamp_scroll();
|
||||
scrollAreaMotionMax = scrollAreaMotion = {0.0f, 0.0f};
|
||||
|
|
@ -178,6 +189,135 @@ void ScrollArea::y_scroll_bar() {
|
|||
});
|
||||
}
|
||||
|
||||
void ScrollArea::x_scroll_bar() {
|
||||
float sAreaDim = boundingBox.value().width();
|
||||
float sAreaStart = boundingBox.value().min.x();
|
||||
float contDim = contentDimensions.x();
|
||||
float scrollerSize = (sAreaDim / contDim) * sAreaDim;
|
||||
float scrollPosMax = contDim - sAreaDim;
|
||||
float scrollerPos = std::fabs(scrollOffset.x() / scrollPosMax);
|
||||
float areaAboveScrollerSize = scrollerPos * (sAreaDim - scrollerSize);
|
||||
|
||||
gui.set_z_index(gui.get_z_index() + 1, [&] {
|
||||
xScrollbar.scrollbar = gui.element<LayoutElement>("x scroll bar", [&] (LayoutElement*, const Clay_ElementId& lId) {
|
||||
CLAY(lId, {
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(gui.io.isTouchDevice ? TOUCH_SCROLLER_WIDTH : DESKTOP_SCROLLER_WIDTH)},
|
||||
.childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_TOP},
|
||||
.layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
},
|
||||
.floating = {
|
||||
.zIndex = gui.get_z_index(),
|
||||
.attachPoints = {
|
||||
.element = CLAY_ATTACH_POINT_LEFT_BOTTOM,
|
||||
.parent = CLAY_ATTACH_POINT_LEFT_BOTTOM
|
||||
},
|
||||
.attachTo = CLAY_ATTACH_TO_PARENT,
|
||||
}
|
||||
}) {
|
||||
SkColor4f scrollerColor;
|
||||
if(xScrollbar.isScrollbarHeld)
|
||||
scrollerColor = gui.io.theme->fillColor1;
|
||||
else if(xScrollbar.isScrollbarHovered)
|
||||
scrollerColor = gui.io.theme->fillColor1;
|
||||
else
|
||||
scrollerColor = gui.io.theme->fillColor2;
|
||||
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIXED(areaAboveScrollerSize), .height = CLAY_SIZING_GROW(0)}
|
||||
}
|
||||
}) {}
|
||||
|
||||
xScrollbar.scroller = gui.element<LayoutElement>("scroller", [&] (LayoutElement*, const Clay_ElementId& lId2) {
|
||||
CLAY(lId2, {
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIXED(scrollerSize), .height = CLAY_SIZING_GROW(0)},
|
||||
.childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_TOP},
|
||||
.layoutDirection = CLAY_TOP_TO_BOTTOM,
|
||||
}
|
||||
}) {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}
|
||||
}) {}
|
||||
float scrollerWidthPercent = 0.0f;
|
||||
bool highlighted = xScrollbar.isHoveringOverScroller || xScrollbar.isScrollbarHeld || (!gui.io.isTouchDevice && xScrollbar.isScrollbarHovered);
|
||||
if(gui.io.isTouchDevice)
|
||||
scrollerWidthPercent = highlighted ? 0.6f : 0.2f;
|
||||
else
|
||||
scrollerWidthPercent = highlighted ? 1.0f : 0.5f;
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_PERCENT(scrollerWidthPercent)}},
|
||||
.backgroundColor = convert_vec4<Clay_Color>(highlighted ? gui.io.theme->fillColor1 : gui.io.theme->fillColor2),
|
||||
.cornerRadius = CLAY_CORNER_RADIUS(3),
|
||||
}) {}
|
||||
}
|
||||
});
|
||||
|
||||
CLAY_AUTO_ID({ .layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}}) {}
|
||||
}
|
||||
}, LayoutElement::Callbacks{
|
||||
.onClick = [&, scrollPosMax, sAreaStart, sAreaDim, scrollerSize, areaAboveScrollerSize](LayoutElement* t, const InputManager::MouseButtonCallbackArgs& button) {
|
||||
bool newIsHoveringOverScroller = xScrollbar.scroller->mouseHovering && (button.deviceType != InputManager::MouseDeviceType::TOUCH || button.down);
|
||||
bool newIsScrollbarHovered = t->mouseHovering && (button.deviceType != InputManager::MouseDeviceType::TOUCH || button.down);
|
||||
if(xScrollbar.isHoveringOverScroller != newIsHoveringOverScroller) {
|
||||
xScrollbar.isHoveringOverScroller = newIsHoveringOverScroller;
|
||||
gui.set_to_layout();
|
||||
}
|
||||
if(xScrollbar.isScrollbarHovered != newIsScrollbarHovered) {
|
||||
xScrollbar.isScrollbarHovered = newIsScrollbarHovered;
|
||||
gui.set_to_layout();
|
||||
}
|
||||
if(button.button == InputManager::MouseButton::LEFT) {
|
||||
if(button.down && xScrollbar.isScrollbarHovered) {
|
||||
xScrollbar.isScrollbarHeld = true;
|
||||
if(xScrollbar.isHoveringOverScroller)
|
||||
xScrollbar.scrollerStartPos = sAreaStart + areaAboveScrollerSize + scrollerSize * 0.5f;
|
||||
else
|
||||
xScrollbar.scrollerStartPos = std::clamp(button.pos.x(), sAreaStart + scrollerSize * 0.5f, sAreaStart + sAreaDim - scrollerSize * 0.5f);
|
||||
xScrollbar.mouseStartPos = button.pos.x();
|
||||
|
||||
float newScrollPosFrac;
|
||||
newScrollPosFrac = std::clamp((xScrollbar.scrollerStartPos - (xScrollbar.mouseStartPos - button.pos.x()) - sAreaStart - scrollerSize * 0.5f) / (sAreaDim - scrollerSize), 0.0f, 1.0f);
|
||||
scrollOffset.x() = newScrollPosFrac * (-scrollPosMax);
|
||||
clamp_scroll();
|
||||
scrollAreaMotionMax = scrollAreaMotion = {0.0f, 0.0f};
|
||||
gui.set_to_layout();
|
||||
}
|
||||
else if(xScrollbar.isScrollbarHeld) {
|
||||
xScrollbar.isScrollbarHeld = false;
|
||||
scrollAreaMotionMax = scrollAreaMotion = {0.0f, 0.0f};
|
||||
gui.set_to_layout();
|
||||
}
|
||||
}
|
||||
},
|
||||
.onMotion = [&, scrollPosMax, sAreaStart, sAreaDim, scrollerSize](LayoutElement* t, const InputManager::MouseMotionCallbackArgs& motion) {
|
||||
bool newIsHoveringOverScroller = xScrollbar.scroller->mouseHovering && motion.deviceType != InputManager::MouseDeviceType::TOUCH;
|
||||
bool newIsScrollbarHovered = t->mouseHovering && motion.deviceType != InputManager::MouseDeviceType::TOUCH;
|
||||
if(xScrollbar.isHoveringOverScroller != newIsHoveringOverScroller) {
|
||||
xScrollbar.isHoveringOverScroller = newIsHoveringOverScroller;
|
||||
gui.set_to_layout();
|
||||
}
|
||||
if(xScrollbar.isScrollbarHovered != newIsScrollbarHovered) {
|
||||
xScrollbar.isScrollbarHovered = newIsScrollbarHovered;
|
||||
gui.set_to_layout();
|
||||
}
|
||||
if(xScrollbar.isScrollbarHeld) {
|
||||
float oldScrollOffset = scrollOffset.x();
|
||||
|
||||
float newScrollPosFrac;
|
||||
newScrollPosFrac = std::clamp((xScrollbar.scrollerStartPos - (xScrollbar.mouseStartPos - motion.pos.x()) - sAreaStart - scrollerSize * 0.5f) / (sAreaDim - scrollerSize), 0.0f, 1.0f);
|
||||
scrollOffset.x() = newScrollPosFrac * (-scrollPosMax);
|
||||
clamp_scroll();
|
||||
scrollAreaMotionMax = scrollAreaMotion = {0.0f, 0.0f};
|
||||
if(oldScrollOffset != scrollOffset.x())
|
||||
gui.set_to_layout();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void ScrollArea::reset_scroll() {
|
||||
scrollAreaMotion = scrollAreaMotionMax = scrollOffset = {0.0f, 0.0f};
|
||||
}
|
||||
|
|
@ -210,13 +350,17 @@ void ScrollArea::update() {
|
|||
}
|
||||
|
||||
void ScrollArea::input_mouse_wheel_callback(const InputManager::MouseWheelCallbackArgs& wheel) {
|
||||
if(mouseHovering) {
|
||||
if(mouseHovering || (xScrollbar.scrollbar && xScrollbar.scrollbar->mouseHovering) || (yScrollbar.scrollbar && yScrollbar.scrollbar->mouseHovering)) {
|
||||
Vector2f oldScrollOffset = scrollOffset;
|
||||
|
||||
if(opts.scrollVertical)
|
||||
scrollOffset.y() = scrollOffset.y() + wheel.amount.y() * 10.0f;
|
||||
if(opts.scrollHorizontal)
|
||||
scrollOffset.y() = scrollOffset.x() + wheel.amount.x() * 10.0f;
|
||||
if(opts.scrollVertical) {
|
||||
scrollOffset.y() += wheel.amount.y() * SCROLL_WHEEL_SCROLL_SPEED;
|
||||
if(opts.scrollHorizontal)
|
||||
scrollOffset.x() += wheel.amount.x() * SCROLL_WHEEL_SCROLL_SPEED;
|
||||
}
|
||||
else if(opts.scrollHorizontal)
|
||||
scrollOffset.x() += wheel.amount.y() * SCROLL_WHEEL_SCROLL_SPEED;
|
||||
|
||||
clamp_scroll();
|
||||
|
||||
if(oldScrollOffset != scrollOffset)
|
||||
|
|
|
|||
|
|
@ -14,13 +14,19 @@ class ScrollArea : public Element {
|
|||
Vector2f* scrollOffset;
|
||||
};
|
||||
|
||||
enum class ScrollbarType {
|
||||
NONE,
|
||||
NO_INTERACTION,
|
||||
NORMAL
|
||||
};
|
||||
|
||||
struct Options {
|
||||
bool scrollVertical = false;
|
||||
bool scrollHorizontal = false;
|
||||
bool clipHorizontal = false;
|
||||
bool clipVertical = false;
|
||||
bool showScrollbarX = false;
|
||||
bool showScrollbarY = false;
|
||||
ScrollbarType scrollbarX = ScrollbarType::NONE;
|
||||
ScrollbarType scrollbarY = ScrollbarType::NONE;
|
||||
Clay_LayoutDirection layoutDirection = CLAY_TOP_TO_BOTTOM;
|
||||
Clay_LayoutAlignmentX xAlign = CLAY_ALIGN_X_LEFT;
|
||||
Clay_LayoutAlignmentY yAlign = CLAY_ALIGN_Y_TOP;
|
||||
|
|
@ -43,13 +49,21 @@ class ScrollArea : public Element {
|
|||
Vector2f scrollAreaMotion = {0.0f, 0.0f};
|
||||
Vector2f scrollAreaMotionMax = {0.0f, 0.0f};
|
||||
|
||||
bool isScrollbarHeldY = false;
|
||||
bool isScrollbarHoveredY = false;
|
||||
bool isHoveringOverScrollerY = false;
|
||||
Element* scrollerY = nullptr;
|
||||
float scrollerStartPosY;
|
||||
float mouseStartPosY;
|
||||
struct ScrollbarData {
|
||||
bool isScrollbarHeld = false;
|
||||
bool isScrollbarHovered = false;
|
||||
bool isHoveringOverScroller = false;
|
||||
Element* scroller = nullptr;
|
||||
Element* scrollbar = nullptr;
|
||||
float scrollerStartPos;
|
||||
float mouseStartPos;
|
||||
};
|
||||
|
||||
ScrollbarData xScrollbar;
|
||||
ScrollbarData yScrollbar;
|
||||
|
||||
void y_scroll_bar();
|
||||
void x_scroll_bar();
|
||||
|
||||
Vector2f contentDimensions = {0.0f, 0.0f};
|
||||
Vector2f scrollOffset = {0.0f, 0.0f};
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@ void PhoneDrawingProgramScreen::main_display() {
|
|||
},
|
||||
}) {
|
||||
top_toolbar();
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}}
|
||||
}) {}
|
||||
bottom_toolbar();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -66,6 +70,42 @@ void PhoneDrawingProgramScreen::top_toolbar() {
|
|||
});
|
||||
}
|
||||
|
||||
void PhoneDrawingProgramScreen::bottom_toolbar() {
|
||||
auto& gui = main.g.gui;
|
||||
auto& io = gui.io;
|
||||
auto& drawProg = main.world->drawProg;
|
||||
window_fill_side_bar(gui, "bottom toolbar", {
|
||||
.dir = WindowFillSideBarConfig::Direction::BOTTOM,
|
||||
.backgroundColor = io.theme->backColor1
|
||||
}, [&] {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) },
|
||||
.childAlignment = { .x = CLAY_ALIGN_X_CENTER, .y = CLAY_ALIGN_Y_CENTER},
|
||||
.layoutDirection = CLAY_LEFT_TO_RIGHT
|
||||
}
|
||||
}) {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
.sizing = {.width = CLAY_SIZING_FIT(0), .height = CLAY_SIZING_FIT(0) }
|
||||
}
|
||||
}) {
|
||||
gui.element<ScrollArea>("tools scroll", ScrollArea::Options{
|
||||
.scrollHorizontal = true,
|
||||
.clipHorizontal = true,
|
||||
.scrollbarX = ScrollArea::ScrollbarType::NONE,
|
||||
.layoutDirection = CLAY_LEFT_TO_RIGHT,
|
||||
.xAlign = CLAY_ALIGN_X_LEFT,
|
||||
.yAlign = CLAY_ALIGN_Y_CENTER,
|
||||
.innerContent = [&](auto&) {
|
||||
drawProg.phone_bottom_toolbar_gui(*this);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void PhoneDrawingProgramScreen::input_global_back_button_callback() {
|
||||
main.world->save_to_file(main.world->filePath);
|
||||
main.set_tab_to_close(main.world.get());
|
||||
|
|
|
|||
|
|
@ -12,5 +12,6 @@ class PhoneDrawingProgramScreen : public DrawingProgramScreen {
|
|||
private:
|
||||
void save_files();
|
||||
void top_toolbar();
|
||||
void bottom_toolbar();
|
||||
void main_display();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -291,7 +291,7 @@ void Toolbar::close_popup_gui() {
|
|||
gui.clipping_element<ScrollArea>("close file popup gui scroll area", ScrollArea::Options{
|
||||
.scrollVertical = true,
|
||||
.clipVertical = true,
|
||||
.showScrollbarY = true,
|
||||
.scrollbarY = ScrollArea::ScrollbarType::NORMAL,
|
||||
.innerContent = [&](const ScrollArea::InnerContentParameters&) {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
|
|
@ -1236,7 +1236,7 @@ void Toolbar::color_palette(const char* id, Vector4f* color, const std::function
|
|||
gui.element<ScrollArea>("color palette scroll area", ScrollArea::Options{
|
||||
.scrollVertical = true,
|
||||
.clipVertical = true,
|
||||
.showScrollbarY = true,
|
||||
.scrollbarY = ScrollArea::ScrollbarType::NORMAL,
|
||||
.innerContent = [&](const ScrollArea::InnerContentParameters&) {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
|
|
@ -1683,7 +1683,7 @@ void Toolbar::general_settings_inner_gui() {
|
|||
gui.clipping_element<ScrollArea>("general settings scroll area", ScrollArea::Options{
|
||||
.scrollVertical = true,
|
||||
.clipVertical = true,
|
||||
.showScrollbarY = true,
|
||||
.scrollbarY = ScrollArea::ScrollbarType::NORMAL,
|
||||
.innerContent = [&, innerContent](const ScrollArea::InnerContentParameters&) {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
|
|
@ -1911,7 +1911,7 @@ void Toolbar::about_menu_inner_gui() {
|
|||
gui.clipping_element<ScrollArea>("About Menu Selector Scroll Area", ScrollArea::Options{
|
||||
.scrollVertical = true,
|
||||
.clipVertical = true,
|
||||
.showScrollbarY = true,
|
||||
.scrollbarY = ScrollArea::ScrollbarType::NORMAL,
|
||||
.innerContent = [&](const ScrollArea::InnerContentParameters&) {
|
||||
CLAY_AUTO_ID({
|
||||
.layout = {
|
||||
|
|
@ -1953,7 +1953,7 @@ void Toolbar::about_menu_inner_gui() {
|
|||
gui.clipping_element<ScrollArea>("About Menu Text Scroll Area", ScrollArea::Options{
|
||||
.scrollVertical = true,
|
||||
.clipVertical = true,
|
||||
.showScrollbarY = true,
|
||||
.scrollbarY = ScrollArea::ScrollbarType::NORMAL,
|
||||
.innerContent = [&](const ScrollArea::InnerContentParameters&) {
|
||||
text_label_size(gui, (selectedLicense == -1) ? main.conf.ownLicenseText : main.conf.thirdPartyLicenses[selectedLicense].second, 0.8f);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue