How do I get a Selectable to fill a table cell/row height?
Version/Branch of Dear ImGui:
1.92.0 WIP
Back-ends:
any
Compiler, OS:
any
Full config/build information:
No response
Details:
My Question:
I have a table with texts and selectables. I want:
- The selectable must always fill the full row height exactly, no matter the current CellPadding (or ItemSpacing)
- The selectable text must still align vertically with normal text on the row.
In my example I explicitly call TableNextRow() with a height because I sometimes don't have anything to render on certain lines and I want the line heights to be consistent (for clipper etc.)
This is a simplified example of what I'm trying to do, in reality I may not even know in my table loop whether I am rendering a selectable or text (that is determined in a called module).
Screenshots/Video:
No response
Minimal, Complete and Verifiable Example code:
void test()
{
ImGui::Begin("Test", nullptr, LocalConfig::ViewportWindowFlags());
ImGui::BeginTable("Test", 2, ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders);
const float rowHeight = ImGui::GetTextLineHeight() + ImGui::GetStyle().CellPadding.y * 2; // force height, even if we don't have text
for (int i = 0; i < 10; i++)
{
ImGui::TableNextRow(ImGuiTableRowFlags_None, rowHeight);
ImGui::PushID(i);
ImGui::TableNextColumn();
ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.5f, 0.f));
ImGui::Selectable("Selectable", false, ImGuiSelectableFlags_SpanAllColumns);
ImGui::PopStyleVar();
ImGui::TableNextColumn();
ImGui::Text("Text");
ImGui::PopID();
}
ImGui::EndTable();
ImGui::End();
}
Out of curiosity are you using the Selectable() only for highlight or as a clicking device?
We ought to add a ImGuiTableFlags_HighlightHoveredRow (#8498) but you could technically use TableSetBgColor().
The selectable text must still align vertically with normal text on the row.
For this, in case you end up manually submitting a Selectable() from the top of the cell, the simpler may be to submit a Selectable() with no label, and the Text() separately.
But we ought to aim to support that a little better, e.g. hypothetically a ImGuiSelectableFlags_SpanAllRow could alter Y1/Y2 of the selectable.
I use it mostly as buttons but with variations.
Sometimes we:
- Show selection state,
- Right click context
- Left click to select or execute (sometimes also double click)
- Sometimes we span all columns, and other times not.
- (or combintations of these)
What I want is a way to fill the entire cell/row with the selection, up to the edges (ignoring frame/item/cell-padding whaever it is at the time)
Not this:
I have found ways to do it, but then I have text alignment issues (which I then need to solve by just writing text and using a blank selection overlay). But I would prefer to avoid this. For now it's purely aesthetic, not a big problem.
My hack for aligned selectable, as someone might find it useful till a proper solution arrives. The sgr object is a RAII wrapper for styling, and Color class inherits from ImColor
const ImGuiSelectableFlags sflags =
ImGuiSelectableFlags_SpanAllColumns
| ImGuiSelectableFlags_AllowItemOverlap
| ImGuiSelectableFlags_AllowDoubleClick;
// Disable selectables interaction styling, we're going to fake draw it ourselves using ImGuiTableBgTarget_RowBg0
sgr.PushColor( ImGuiCol_Header, Colors::Transparent );
sgr.PushColor( ImGuiCol_HeaderHovered, Colors::Transparent );
sgr.PushColor( ImGuiCol_HeaderActive, Colors::Transparent );
ImGuiTable * imtable = GetCurrentTable();
BOOST_ASSERT_MSG( imtable, "Expected valid ImGuiTable in DrawSingleRowList" );
AlignTextToFramePadding();
// Hack for selectable to fill entire cell; https://github.com/ocornut/imgui/issues/5615
sgr.PushStyleVar( &ImGuiStyle::ItemSpacing, ImVec2{ sgr->ItemSpacing.x, sgr->CellPadding.y * 4.f } );
const bool activated = Selectable( first_label.c_str(), selected, sflags );
const bool hovered = IsItemHovered();
const bool held = IsItemActive();
// Copy and paste color selection logic from selectable widget
if ( hovered || selected )
{
Color col;
if ( selected && !hovered )
{
col = ImLerp( Colors::editor::SchemaRowSelection * Colors::Transparent40,
Colors::editor::SchemaRowHover * Colors::Transparent30,
0.5f );
}
else
{
col = ( held && hovered ) ? ( Colors::editor::SchemaRowSelection * Colors::Transparent60 )
: hovered ? ( Colors::editor::SchemaRowHover * Colors::Transparent40 )
: ( Colors::editor::SchemaRowSelection * Colors::Transparent10 );
}
// actually set the color for an entire row
TableSetBgColor( ImGuiTableBgTarget_RowBg0, col, -1 );
}
results in following, the bar on the left is not included :)