-
-
Notifications
You must be signed in to change notification settings - Fork 11.1k
Open
Labels
Description
I have created a generic Box component (inspired by jetpack compose) for the purpose of:
- having padding (top/right/bottom/left)
- background color
- border
It works great as can be seen in this image
Here is the code I have:
struct Modifier
{
ImVec4 fPadding{};
ImU32 fBackgroundColor{};
ImU32 fBorderColor{};
constexpr Modifier &padding(float iTop, float iRight, float iBottom, float iLeft) { fPadding = {iTop, iRight, iBottom, iLeft}; return *this; } // x/y/z/w
constexpr Modifier &padding(float iPadding) { return padding(iPadding, iPadding, iPadding, iPadding); }
constexpr Modifier &padding(float iHorizontalPadding, float iVerticalPadding) { return padding(iVerticalPadding, iHorizontalPadding, iVerticalPadding, iHorizontalPadding); }
constexpr Modifier &backgroundColor(ImU32 iColor) { fBackgroundColor = iColor; return *this; }
constexpr Modifier &borderColor(ImU32 iColor) { fBorderColor = iColor; return *this; }
};
// note that I use ImVec2 math in this code
void Box(Modifier const &iModifier, std::function<void()> const &iBoxContent)
{
// split draw list in 2
ImDrawListSplitter splitter{};
splitter.Split(ImGui::GetWindowDrawList(), 2);
// first we draw in channel 1 to render iBoxContent (will be on top)
splitter.SetCurrentChannel(ImGui::GetWindowDrawList(), 1);
ImGui::BeginGroup();
{
auto position = ImGui::GetCursorPos();
// account for padding left/top
ImGui::SetCursorPos(position + ImVec2{iModifier.fPadding.w, iModifier.fPadding.x});
iBoxContent();
ImGui::EndGroup();
}
auto min = ImGui::GetItemRectMin();
// account for padding right/bottom
auto max = ImGui::GetItemRectMax() + ImVec2{iModifier.fPadding.y, iModifier.fPadding.z};
// second we draw the rectangle and border in channel 0 (will be below)
splitter.SetCurrentChannel(ImGui::GetWindowDrawList(), 0);
// draw the background
if(!ColorIsTransparent(iModifier.fBackgroundColor))
ImGui::GetWindowDrawList()->AddRectFilled(min, max, iModifier.fBackgroundColor);
// draw the border
if(!ColorIsTransparent(iModifier.fBorderColor))
ImGui::GetWindowDrawList()->AddRect(min, max, iModifier.fBorderColor);
// merge the 2 draw lists
splitter.Merge(ImGui::GetWindowDrawList());
// reposition the cursor (top left) and render a "dummy" box of the correct size so that it occupies
// the proper amount of space
ImGui::SetCursorScreenPos(min);
ImGui::Dummy(max - min);
}
It works great, but of course it is a very different api style from the rest of ImGui. I should have instead a BeginBox(Modifier)
and EndBox()
api instead. The reason why I was not able to follow the same API is that in the EndBox()
call I need information that is provided in the BeginBox
call (like the colors and padding). Is there any recommended way on how I could do that (I guess I would need some form of "generic" PushMyVar api)?
n08i40k