Skip to content

Commit 26df0f6

Browse files
committed
[ADD] : add the column type (for have type sorting, column can be hidden btw)
1 parent e0bb604 commit 26df0f6

3 files changed

Lines changed: 117 additions & 51 deletions

File tree

ImGuiFileDialog.cpp

Lines changed: 112 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@ namespace IGFD
152152
#ifndef tableHeaderFileNameString
153153
#define tableHeaderFileNameString "File name"
154154
#endif // tableHeaderFileNameString
155+
#ifndef tableHeaderFileTypeString
156+
#define tableHeaderFileTypeString "Type"
157+
#endif // tableHeaderFileTypeString
155158
#ifndef tableHeaderFileSizeString
156159
#define tableHeaderFileSizeString "Size"
157160
#endif // tableHeaderFileSizeString
@@ -512,7 +515,7 @@ namespace IGFD
512515
//////////////////////////////////////////////////////////////////////////////////////////////////
513516
///// CUSTOM SELECTABLE (Flashing Support) ///////////////////////////////////////////////////////
514517
//////////////////////////////////////////////////////////////////////////////////////////////////
515-
518+
516519
#ifdef USE_EXPLORATION_BY_KEYS
517520
bool IGFD::FileDialog::FlashableSelectable(const char* label, bool selected,
518521
ImGuiSelectableFlags flags, bool vFlashing, const ImVec2& size_arg)
@@ -526,62 +529,79 @@ namespace IGFD
526529
ImGuiContext& g = *GImGui;
527530
const ImGuiStyle& style = g.Style;
528531

529-
if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns) // FIXME-OPT: Avoid if vertically clipped.
530-
PushColumnsBackground();
531-
532532
// Submit label or explicit size to ItemSize(), whereas ItemAdd() will submit a larger/spanning rectangle.
533533
ImGuiID id = window->GetID(label);
534534
ImVec2 label_size = CalcTextSize(label, NULL, true);
535-
ImVec2 size(
536-
IS_FLOAT_DIFFERENT(size_arg.x, 0.0f) ? size_arg.x : label_size.x,
537-
IS_FLOAT_DIFFERENT(size_arg.y, 0.0f) ? size_arg.y : label_size.y
538-
);
535+
ImVec2 size(size_arg.x != 0.0f ? size_arg.x : label_size.x, size_arg.y != 0.0f ? size_arg.y : label_size.y);
539536
ImVec2 pos = window->DC.CursorPos;
540537
pos.y += window->DC.CurrLineTextBaseOffset;
541538
ItemSize(size, 0.0f);
542539

543540
// Fill horizontal space
544-
const float min_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? window->ContentRegionRect.Min.x : pos.x;
545-
const float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? window->ContentRegionRect.Max.x : GetContentRegionMaxAbs().x;
546-
if (IS_FLOAT_DIFFERENT(size_arg.x, 0.0f) || (flags & ImGuiSelectableFlags_SpanAvailWidth))
541+
// We don't support (size < 0.0f) in Selectable() because the ItemSpacing extension would make explicitely right-aligned sizes not visibly match other widgets.
542+
const bool span_all_columns = (flags & ImGuiSelectableFlags_SpanAllColumns) != 0;
543+
const float min_x = span_all_columns ? window->ParentWorkRect.Min.x : pos.x;
544+
const float max_x = span_all_columns ? window->ParentWorkRect.Max.x : window->WorkRect.Max.x;
545+
if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_SpanAvailWidth))
547546
size.x = ImMax(label_size.x, max_x - min_x);
548547

549548
// Text stays at the submission position, but bounding box may be extended on both sides
550549
const ImVec2 text_min = pos;
551550
const ImVec2 text_max(min_x + size.x, pos.y + size.y);
552551

553552
// Selectables are meant to be tightly packed together with no click-gap, so we extend their box to cover spacing between selectable.
554-
ImRect bb_enlarged(min_x, pos.y, text_max.x, text_max.y);
555-
const float spacing_x = style.ItemSpacing.x;
556-
const float spacing_y = style.ItemSpacing.y;
557-
const float spacing_L = IM_FLOOR(spacing_x * 0.50f);
558-
const float spacing_U = IM_FLOOR(spacing_y * 0.50f);
559-
bb_enlarged.Min.x -= spacing_L;
560-
bb_enlarged.Min.y -= spacing_U;
561-
bb_enlarged.Max.x += (spacing_x - spacing_L);
562-
bb_enlarged.Max.y += (spacing_y - spacing_U);
563-
//if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb_align.Min, bb_align.Max, IM_COL32(255, 0, 0, 255)); }
564-
//if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb_enlarged.Min, bb_enlarged.Max, IM_COL32(0, 255, 0, 255)); }
553+
ImRect bb(min_x, pos.y, text_max.x, text_max.y);
554+
if ((flags & ImGuiSelectableFlags_NoPadWithHalfSpacing) == 0)
555+
{
556+
const float spacing_x = span_all_columns ? 0.0f : style.ItemSpacing.x;
557+
const float spacing_y = style.ItemSpacing.y;
558+
const float spacing_L = IM_FLOOR(spacing_x * 0.50f);
559+
const float spacing_U = IM_FLOOR(spacing_y * 0.50f);
560+
bb.Min.x -= spacing_L;
561+
bb.Min.y -= spacing_U;
562+
bb.Max.x += (spacing_x - spacing_L);
563+
bb.Max.y += (spacing_y - spacing_U);
564+
}
565+
//if (g.IO.KeyCtrl) { GetForegroundDrawList()->AddRect(bb.Min, bb.Max, IM_COL32(0, 255, 0, 255)); }
566+
567+
// Modify ClipRect for the ItemAdd(), faster than doing a PushColumnsBackground/PushTableBackground for every Selectable..
568+
const float backup_clip_rect_min_x = window->ClipRect.Min.x;
569+
const float backup_clip_rect_max_x = window->ClipRect.Max.x;
570+
if (span_all_columns)
571+
{
572+
window->ClipRect.Min.x = window->ParentWorkRect.Min.x;
573+
window->ClipRect.Max.x = window->ParentWorkRect.Max.x;
574+
}
565575

566576
bool item_add;
567577
if (flags & ImGuiSelectableFlags_Disabled)
568578
{
569579
ImGuiItemFlags backup_item_flags = window->DC.ItemFlags;
570580
window->DC.ItemFlags |= ImGuiItemFlags_Disabled | ImGuiItemFlags_NoNavDefaultFocus;
571-
item_add = ItemAdd(bb_enlarged, id);
581+
item_add = ItemAdd(bb, id);
572582
window->DC.ItemFlags = backup_item_flags;
573583
}
574584
else
575585
{
576-
item_add = ItemAdd(bb_enlarged, id);
586+
item_add = ItemAdd(bb, id);
577587
}
578-
if (!item_add)
588+
589+
if (span_all_columns)
579590
{
580-
if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns)
581-
PopColumnsBackground();
582-
return false;
591+
window->ClipRect.Min.x = backup_clip_rect_min_x;
592+
window->ClipRect.Max.x = backup_clip_rect_max_x;
583593
}
584594

595+
if (!item_add)
596+
return false;
597+
598+
// FIXME: We can standardize the behavior of those two, we could also keep the fast path of override ClipRect + full push on render only,
599+
// which would be advantageous since most selectable are not selected.
600+
if (span_all_columns && window->DC.CurrentColumns)
601+
PushColumnsBackground();
602+
else if (span_all_columns && g.CurrentTable)
603+
TablePushBackgroundChannel();
604+
585605
// We use NoHoldingActiveID on menus so user can click and _hold_ on a menu then drag to browse child entries
586606
ImGuiButtonFlags button_flags = 0;
587607
if (flags & ImGuiSelectableFlags_NoHoldingActiveID) { button_flags |= ImGuiButtonFlags_NoHoldingActiveId; }
@@ -596,7 +616,7 @@ namespace IGFD
596616

597617
const bool was_selected = selected;
598618
bool hovered, held;
599-
bool pressed = ButtonBehavior(bb_enlarged, id, &hovered, &held, button_flags);
619+
bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
600620

601621
// Update NavId when clicking or when Hovering (this doesn't happen on most widgets), so navigation can be resumed with gamepad/keyboard
602622
if (pressed || (hovered && (flags & ImGuiSelectableFlags_SetNavIdOnHover)))
@@ -618,20 +638,22 @@ namespace IGFD
618638
window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_ToggledSelection;
619639

620640
// Render
621-
if ((held && (flags & ImGuiSelectableFlags_DrawHoveredWhenHeld)) || vFlashing)
641+
if (held && (flags & ImGuiSelectableFlags_DrawHoveredWhenHeld) || vFlashing)
622642
hovered = true;
623643
if (hovered || selected)
624644
{
625645
const ImU32 col = GetColorU32((held && hovered) ? ImGuiCol_HeaderActive : hovered ? ImGuiCol_HeaderHovered : ImGuiCol_Header);
626-
RenderFrame(bb_enlarged.Min, bb_enlarged.Max, col, false, 0.0f);
627-
RenderNavHighlight(bb_enlarged, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding);
646+
RenderFrame(bb.Min, bb.Max, col, false, 0.0f);
647+
RenderNavHighlight(bb, id, ImGuiNavHighlightFlags_TypeThin | ImGuiNavHighlightFlags_NoRounding);
628648
}
629649

630-
if ((flags & ImGuiSelectableFlags_SpanAllColumns) && window->DC.CurrentColumns)
650+
if (span_all_columns && window->DC.CurrentColumns)
631651
PopColumnsBackground();
652+
else if (span_all_columns && g.CurrentTable)
653+
TablePopBackgroundChannel();
632654

633655
if (flags & ImGuiSelectableFlags_Disabled) PushStyleColor(ImGuiCol_Text, style.Colors[ImGuiCol_TextDisabled]);
634-
RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb_enlarged);
656+
RenderTextClipped(text_min, text_max, label, NULL, &label_size, style.SelectableTextAlign, &bb);
635657
if (flags & ImGuiSelectableFlags_Disabled) PopStyleColor();
636658

637659
// Automatically close popups
@@ -1294,12 +1316,13 @@ namespace IGFD
12941316
| ImGuiTableFlags_Sortable
12951317
#endif // USE_CUSTOM_SORTING_ICON
12961318
;
1297-
if (ImGui::BeginTable("##fileTable", 3, flags, vSize))
1319+
if (ImGui::BeginTable("##fileTable", 4, flags, vSize))
12981320
{
12991321
ImGui::TableSetupScrollFreeze(0, 1); // Make header always visible
13001322
ImGui::TableSetupColumn(m_HeaderFileName.c_str(), ImGuiTableColumnFlags_WidthStretch, -1, 0);
1301-
ImGui::TableSetupColumn(m_HeaderFileSize.c_str(), ImGuiTableColumnFlags_WidthFixed, -1, 1);
1302-
ImGui::TableSetupColumn(m_HeaderFileDate.c_str(), ImGuiTableColumnFlags_WidthFixed, -1, 2);
1323+
ImGui::TableSetupColumn(m_HeaderFileType.c_str(), ImGuiTableColumnFlags_WidthFixed, -1, 1);
1324+
ImGui::TableSetupColumn(m_HeaderFileSize.c_str(), ImGuiTableColumnFlags_WidthFixed, -1, 2);
1325+
ImGui::TableSetupColumn(m_HeaderFileDate.c_str(), ImGuiTableColumnFlags_WidthFixed, -1, 3);
13031326

13041327
#ifndef USE_CUSTOM_SORTING_ICON
13051328
// Sort our data if sort specs have been changed!
@@ -1310,8 +1333,10 @@ namespace IGFD
13101333
if (sorts_specs->Specs->ColumnUserID == 0)
13111334
SortFields(SortingFieldEnum::FIELD_FILENAME, true);
13121335
else if (sorts_specs->Specs->ColumnUserID == 1)
1313-
SortFields(SortingFieldEnum::FIELD_SIZE, true);
1336+
SortFields(SortingFieldEnum::FIELD_TYPE, true);
13141337
else if (sorts_specs->Specs->ColumnUserID == 2)
1338+
SortFields(SortingFieldEnum::FIELD_SIZE, true);
1339+
else //if (sorts_specs->Specs->ColumnUserID == 3) => alwayd true for the moment, to uncomment if we add a fourth column
13151340
SortFields(SortingFieldEnum::FIELD_DATE, true);
13161341

13171342
sorts_specs->SpecsDirty = false;
@@ -1321,7 +1346,7 @@ namespace IGFD
13211346
ImGui::TableHeadersRow();
13221347
#else // USE_CUSTOM_SORTING_ICON
13231348
ImGui::TableNextRow(ImGuiTableRowFlags_Headers);
1324-
for (int column = 0; column < 3; column++)
1349+
for (int column = 0; column < 4; column++)
13251350
{
13261351
ImGui::TableSetColumnIndex(column);
13271352
const char* column_name = ImGui::TableGetColumnName(column); // Retrieve name passed to TableSetupColumn()
@@ -1333,8 +1358,10 @@ namespace IGFD
13331358
if (column == 0)
13341359
SortFields(SortingFieldEnum::FIELD_FILENAME, true);
13351360
else if (column == 1)
1361+
SortFields(SortingFieldEnum::FIELD_TYPE, true);
1362+
else if (column == 2)
13361363
SortFields(SortingFieldEnum::FIELD_SIZE, true);
1337-
else //if (column == 2) => alwasy true for the moment, to uncomment if we add a fourth column
1364+
else //if (column == 3) => alwayd true for the moment, to uncomment if we add a fourth column
13381365
SortFields(SortingFieldEnum::FIELD_DATE, true);
13391366
}
13401367
}
@@ -1367,28 +1394,33 @@ namespace IGFD
13671394
str = fileEntryString + str;
13681395
}
13691396
bool selected = (m_SelectedFileNames.find(infos.fileName) != m_SelectedFileNames.end()); // found
1397+
13701398
ImGui::TableNextRow();
13711399

13721400
bool needToBreakTheloop = false;
13731401

1374-
if (ImGui::TableSetColumnIndex(0)) // first column
1402+
if (ImGui::TableNextColumn()) // file name
13751403
{
13761404
needToBreakTheloop = SelectableItem(i, infos, selected, str.c_str());
13771405
}
1378-
if (ImGui::TableSetColumnIndex(1)) // second column
1406+
if (ImGui::TableNextColumn()) // file type
1407+
{
1408+
ImGui::Text("%s", infos.ext.c_str());
1409+
}
1410+
if (ImGui::TableNextColumn()) // file size
13791411
{
13801412
if (infos.type != 'd')
13811413
{
1382-
needToBreakTheloop = SelectableItem(i, infos, selected, "%s ", infos.formatedFileSize.c_str());
1414+
ImGui::Text("%s ", infos.formatedFileSize.c_str());
13831415
}
13841416
else
13851417
{
1386-
needToBreakTheloop = SelectableItem(i, infos, selected, "");
1418+
ImGui::Text("");
13871419
}
13881420
}
1389-
if (ImGui::TableSetColumnIndex(2)) // third column
1421+
if (ImGui::TableNextColumn()) // file date + time
13901422
{
1391-
needToBreakTheloop = SelectableItem(i, infos, selected, "%s", infos.fileModifDate.c_str());
1423+
ImGui::Text("%s", infos.fileModifDate.c_str());
13921424
}
13931425

13941426
if (showColor)
@@ -1954,6 +1986,7 @@ namespace IGFD
19541986
if (vSortingField != SortingFieldEnum::FIELD_NONE)
19551987
{
19561988
m_HeaderFileName = tableHeaderFileNameString;
1989+
m_HeaderFileType = tableHeaderFileTypeString;
19571990
m_HeaderFileSize = tableHeaderFileSizeString;
19581991
m_HeaderFileDate = tableHeaderFileDateString;
19591992
}
@@ -1988,13 +2021,43 @@ namespace IGFD
19882021
});
19892022
}
19902023
}
1991-
else if (vSortingField == SortingFieldEnum::FIELD_SIZE)
2024+
else if (vSortingField == SortingFieldEnum::FIELD_TYPE)
19922025
{
19932026
if (vCanChangeOrder && m_SortingField == vSortingField)
19942027
m_SortingDirection[1] = !m_SortingDirection[1];
19952028

19962029
if (m_SortingDirection[1])
19972030
{
2031+
#ifdef USE_CUSTOM_SORTING_ICON
2032+
m_HeaderFileType = tableHeaderDescendingIcon + m_HeaderFileType;
2033+
#endif // USE_CUSTOM_SORTING_ICON
2034+
std::sort(m_FileList.begin(), m_FileList.end(),
2035+
[](const FileInfoStruct& a, const FileInfoStruct& b) -> bool
2036+
{
2037+
if (a.type != b.type) return (a.type == 'd'); // directory in first
2038+
return (a.ext < b.ext); // else
2039+
});
2040+
}
2041+
else
2042+
{
2043+
#ifdef USE_CUSTOM_SORTING_ICON
2044+
m_HeaderFileType = tableHeaderAscendingIcon + m_HeaderFileType;
2045+
#endif // USE_CUSTOM_SORTING_ICON
2046+
std::sort(m_FileList.begin(), m_FileList.end(),
2047+
[](const FileInfoStruct& a, const FileInfoStruct& b) -> bool
2048+
{
2049+
if (a.type != b.type) return (a.type != 'd'); // directory in last
2050+
return (a.ext > b.ext); // else
2051+
});
2052+
}
2053+
}
2054+
else if (vSortingField == SortingFieldEnum::FIELD_SIZE)
2055+
{
2056+
if (vCanChangeOrder && m_SortingField == vSortingField)
2057+
m_SortingDirection[2] = !m_SortingDirection[2];
2058+
2059+
if (m_SortingDirection[2])
2060+
{
19982061
#ifdef USE_CUSTOM_SORTING_ICON
19992062
m_HeaderFileSize = tableHeaderDescendingIcon + m_HeaderFileSize;
20002063
#endif // USE_CUSTOM_SORTING_ICON
@@ -2021,9 +2084,9 @@ namespace IGFD
20212084
else if (vSortingField == SortingFieldEnum::FIELD_DATE)
20222085
{
20232086
if (vCanChangeOrder && m_SortingField == vSortingField)
2024-
m_SortingDirection[2] = !m_SortingDirection[2];
2087+
m_SortingDirection[3] = !m_SortingDirection[3];
20252088

2026-
if (m_SortingDirection[2])
2089+
if (m_SortingDirection[3])
20272090
{
20282091
#ifdef USE_CUSTOM_SORTING_ICON
20292092
m_HeaderFileDate = tableHeaderDescendingIcon + m_HeaderFileDate;

ImGuiFileDialog.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,7 @@ namespace IGFD
545545
{
546546
FIELD_NONE = 0,
547547
FIELD_FILENAME,
548+
FIELD_TYPE,
548549
FIELD_SIZE,
549550
FIELD_DATE
550551
};
@@ -599,9 +600,10 @@ namespace IGFD
599600
bool m_IsOk = false;
600601
bool m_CreateDirectoryMode = false; // for create directory mode
601602
std::string m_HeaderFileName; // detail view column file
603+
std::string m_HeaderFileType; // detail view column type
602604
std::string m_HeaderFileSize; // detail view column size
603605
std::string m_HeaderFileDate; // detail view column date + time
604-
bool m_SortingDirection[3] = { true,true,true }; // detail view // true => Descending, false => Ascending
606+
bool m_SortingDirection[4] = { true, true, true, true }; // detail view // true => Descending, false => Ascending
605607
SortingFieldEnum m_SortingField = SortingFieldEnum::FIELD_FILENAME; // detail view sorting column
606608

607609
std::string dlg_key;

ImGuiFileDialogConfig.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,11 @@
5757
//#define tableHeaderAscendingIcon "A|"
5858
//#define tableHeaderDescendingIcon "D|"
5959
//#define tableHeaderFileNameString " File name"
60+
//#define tableHeaderFileTypeString " Type"
6061
//#define tableHeaderFileSizeString " Size"
6162
//#define tableHeaderFileDateTimeString " Date"
6263

63-
#define USE_BOOKMARK
64+
//#define USE_BOOKMARK
6465
//#define bookmarkPaneWith 150.0f
6566
//#define IMGUI_TOGGLE_BUTTON ToggleButton
6667
//#define bookmarksButtonString "Bookmark"

0 commit comments

Comments
 (0)