Fixed dropdown

This commit is contained in:
Yousef Khadadeh 2026-04-01 18:00:22 +03:00
parent f944cb8a68
commit b50cab2d33
11 changed files with 135 additions and 96 deletions

View file

@ -18,22 +18,22 @@ template <typename T> void ColorPickerButton<T>::layout(const Clay_ElementId& id
}
});
if(isOpen) {
gui.zIndex++;
ElementHelpers::top_to_bottom_window_popup_layout(gui, "Color Picker", CLAY_SIZING_FIT(300), CLAY_SIZING_FIT(0), [&, val, data = data]() {
ElementHelpers::color_picker_items(gui, "c", val, {
.hasAlpha = data.hasAlpha,
.onEdit = data.onEdit
});
}, {
.mouseButton = [&](const InputManager::MouseButtonCallbackArgs& button, bool mouseHovering) {
if(!mouseHovering && button.button == InputManager::MouseButton::LEFT && button.down) {
isOpen = false;
gui.set_to_layout();
gui.set_z_index(gui.get_z_index() + 1, [&] {
ElementHelpers::top_to_bottom_window_popup_layout(gui, "Color Picker", CLAY_SIZING_FIT(300), CLAY_SIZING_FIT(0), [&, val, data = data]() {
ElementHelpers::color_picker_items(gui, "c", val, {
.hasAlpha = data.hasAlpha,
.onEdit = data.onEdit
});
}, {
.mouseButton = [&](const InputManager::MouseButtonCallbackArgs& button, bool mouseHovering) {
if(!mouseHovering && button.button == InputManager::MouseButton::LEFT && button.down) {
isOpen = false;
gui.set_to_layout();
}
return mouseHovering;
}
return mouseHovering;
}
});
});
gui.zIndex--;
}
}

View file

@ -19,6 +19,7 @@ template <typename T> class DropDown : public Element {
DropDown(GUIManager& gui): Element(gui) {}
void layout(const Clay_ElementId& id, T* data, const std::vector<std::string>& selections, const DropdownOptions& options = {}) {
opts = options;
d = data;
ElementHelpers::left_to_right_layout(gui, CLAY_SIZING_FIXED(opts.width), CLAY_SIZING_FIT(0), [&] {
gui.element<SelectableButton>("dropdown", SelectableButton::Data{
.drawType = SelectableButton::DrawType::FILLED,
@ -51,85 +52,93 @@ template <typename T> class DropDown : public Element {
});
if(isOpen) {
Clay_ElementId localID = CLAY_ID_LOCAL("DROPDOWN");
Clay_ElementData dropdownElemData = Clay_GetElementData(localID);
float calculatedDropdownMaxHeight = 0.0f;
if(dropdownElemData.found)
calculatedDropdownMaxHeight = std::max(gui.io.windowSize.y() - dropdownElemData.boundingBox.y - 2.0f, 0.0f);
CLAY(localID, {
.layout = {
.sizing = {.width = CLAY_SIZING_FIXED(opts.width), .height = CLAY_SIZING_FIT(0, calculatedDropdownMaxHeight)},
.childGap = 0
},
.backgroundColor = convert_vec4<Clay_Color>(gui.io.theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(4),
.floating = {
.offset = {
.y = 4
},
.attachPoints = {
.element = CLAY_ATTACH_POINT_LEFT_TOP,
.parent = CLAY_ATTACH_POINT_LEFT_BOTTOM
},
.attachTo = CLAY_ATTACH_TO_PARENT
},
.border = {
.color = convert_vec4<Clay_Color>(gui.io.theme->fillColor2),
.width = CLAY_BORDER_OUTSIDE(1)
}
}) {
ElementHelpers::scroll_area_many_entries(gui, "dropdown scroll area", {
.entryHeight = 18.0f,
.entryCount = selections.size(),
.clipHorizontal = true,
.elementContent = [&](size_t i) {
bool selectedEntry = static_cast<size_t>(*data) == i;
gui.element<LayoutElement>("elem", [&] (const Clay_ElementId& lId) {
CLAY(lId, {
.layout = {
.sizing = {.width = CLAY_SIZING_FIXED(250), .height = CLAY_SIZING_FIXED(18)},
.padding = CLAY_PADDING_ALL(0),
.childGap = 0,
.childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER},
.layoutDirection = CLAY_TOP_TO_BOTTOM
}
}) {
SkColor4f entryColor;
if(selectedEntry)
entryColor = gui.io.theme->backColor2;
else if(hoveringOver.has_value() && hoveringOver.value() == i)
entryColor = gui.io.theme->backColor2;
else
entryColor = gui.io.theme->backColor1;
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)},
.padding = {.left = 2, .right = 2, .top = 0, .bottom = 0},
.childGap = 0,
.childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}
},
.backgroundColor = convert_vec4<Clay_Color>(entryColor)
}) {
ElementHelpers::text_label(gui, selections[i]);
}
}
}, LayoutElement::Callbacks {
.mouseButton = [&, i](const InputManager::MouseButtonCallbackArgs& button, bool mouseHovering) {
update_hovering_over(i, mouseHovering);
if(mouseHovering && button.button == InputManager::MouseButton::LEFT && button.down) {
gui.set_post_callback_func([&] { opts.onClick(); });
gui.set_to_layout();
}
return mouseHovering;
gui.set_z_index(gui.get_z_index() + 1, [&] {
gui.element<LayoutElement>("DROPDOWN", [&](const Clay_ElementId& lId) {
Clay_ElementData dropdownElemData = Clay_GetElementData(lId);
float calculatedDropdownMaxHeight = 0.0f;
if(dropdownElemData.found)
calculatedDropdownMaxHeight = std::max(gui.io.windowSize.y() - dropdownElemData.boundingBox.y - 2.0f, 0.0f);
CLAY(lId, {
.layout = {
.sizing = {.width = CLAY_SIZING_FIXED(opts.width), .height = CLAY_SIZING_FIT(0, calculatedDropdownMaxHeight)},
.childGap = 0
},
.backgroundColor = convert_vec4<Clay_Color>(gui.io.theme->backColor1),
.cornerRadius = CLAY_CORNER_RADIUS(4),
.floating = {
.offset = {
.y = 4
},
.mouseMotion = [&, i](const InputManager::MouseMotionCallbackArgs& motion, bool mouseHovering) {
update_hovering_over(i, mouseHovering);
return mouseHovering;
.zIndex = gui.get_z_index(),
.attachPoints = {
.element = CLAY_ATTACH_POINT_LEFT_TOP,
.parent = CLAY_ATTACH_POINT_LEFT_BOTTOM
},
.attachTo = CLAY_ATTACH_TO_PARENT
},
.border = {
.color = convert_vec4<Clay_Color>(gui.io.theme->fillColor2),
.width = CLAY_BORDER_OUTSIDE(1)
}
}) {
ElementHelpers::scroll_area_many_entries(gui, "dropdown scroll area", {
.entryHeight = 18.0f,
.entryCount = selections.size(),
.clipHorizontal = true,
.elementContent = [&](size_t i) {
bool selectedEntry = static_cast<size_t>(*data) == i;
gui.element<LayoutElement>("elem", [&] (const Clay_ElementId& lId) {
CLAY(lId, {
.layout = {
.sizing = {.width = CLAY_SIZING_FIXED(250), .height = CLAY_SIZING_FIXED(18)},
.padding = CLAY_PADDING_ALL(0),
.childGap = 0,
.childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER},
.layoutDirection = CLAY_TOP_TO_BOTTOM
}
}) {
SkColor4f entryColor;
if(selectedEntry)
entryColor = gui.io.theme->backColor2;
else if(hoveringOver.has_value() && hoveringOver.value() == i)
entryColor = gui.io.theme->backColor2;
else
entryColor = gui.io.theme->backColor1;
CLAY_AUTO_ID({
.layout = {
.sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)},
.padding = {.left = 2, .right = 2, .top = 0, .bottom = 0},
.childGap = 0,
.childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}
},
.backgroundColor = convert_vec4<Clay_Color>(entryColor)
}) {
ElementHelpers::text_label(gui, selections[i]);
}
}
}, LayoutElement::Callbacks {
.mouseButton = [&, i](const InputManager::MouseButtonCallbackArgs& button, bool mouseHovering) {
update_hovering_over(i, mouseHovering);
if(mouseHovering && button.button == InputManager::MouseButton::LEFT && button.down) {
gui.set_post_callback_func([&, i] {
*d = i;
isOpen = false;
opts.onClick();
});
gui.set_to_layout();
}
return mouseHovering;
},
.mouseMotion = [&, i](const InputManager::MouseMotionCallbackArgs& motion, bool mouseHovering) {
update_hovering_over(i, mouseHovering);
return mouseHovering;
}
});
}
});
}
});
}
});
}
});
}

View file

@ -82,6 +82,9 @@ template <typename T> class NumberSlider : public Element {
}
virtual bool input_mouse_motion_callback(const InputManager::MouseMotionCallbackArgs& motion, bool mouseHovering) override {
isHovering = mouseHovering;
if(isHeld && boundingBox.has_value())
update_slider_pos(motion.pos);
return Element::input_mouse_motion_callback(motion, mouseHovering);
}

View file

@ -28,7 +28,7 @@ void PositionAdjustingPopupMenu::layout(const Clay_ElementId& id, Vector2f popup
.cornerRadius = CLAY_CORNER_RADIUS(gui.io.theme->windowCorners1),
.floating = {
.offset = {popupPos.x(), popupPos.y()},
.zIndex = gui.zIndex,
.zIndex = gui.get_z_index(),
.attachTo = CLAY_ATTACH_TO_ROOT
}
}) {