Skip to content

Commit

Permalink
[ADD] : add a possible dialog customization picture
Browse files Browse the repository at this point in the history
[FIX] : fix somes issue with combo in ImWidgets
  • Loading branch information
aiekick committed Feb 21, 2024
1 parent b2335c1 commit d1b389c
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 87 deletions.
129 changes: 44 additions & 85 deletions 3rdparty/imwidgets/ImWidgets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -514,111 +514,70 @@ inline float inCalcMaxPopupHeightFromItemCount(int items_count) {
}

bool BeginContrastedCombo(const char* label, const char* preview_value, ImGuiComboFlags flags) {
// Always consume the SetNextWindowSizeConstraint() call in our early return paths
ImGuiContext& g = *GImGui;
bool has_window_size_constraint = (g.NextWindowData.Flags & ImGuiNextWindowDataFlags_HasSizeConstraint) != 0;
g.NextWindowData.Flags &= ~ImGuiNextWindowDataFlags_HasSizeConstraint;

ImGuiContext& g = *GImGui;
ImGuiWindow* window = GetCurrentWindow();
if (window->SkipItems) return false;

IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together
ImGuiNextWindowDataFlags backup_next_window_data_flags = g.NextWindowData.Flags;
g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
if (window->SkipItems) return false;

const ImGuiStyle& style = g.Style;

PushID(++CustomStyle::pushId);
const ImGuiID id = window->GetID(label);
PopID();

const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
const ImVec2 label_size = CalcTextSize(label, NULL, true);
const float expected_w = CalcItemWidth();
const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : expected_w;
const ImRect frame_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
const ImRect total_bb(frame_bb.Min, frame_bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
const ImGuiID id = window->GetID(label);
IM_ASSERT((flags & (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)) != (ImGuiComboFlags_NoArrowButton | ImGuiComboFlags_NoPreview)); // Can't use both flags together
if (flags & ImGuiComboFlags_WidthFitPreview) IM_ASSERT((flags & (ImGuiComboFlags_NoPreview | (ImGuiComboFlags)ImGuiComboFlags_CustomPreview)) == 0);

const float arrow_size = (flags & ImGuiComboFlags_NoArrowButton) ? 0.0f : GetFrameHeight();
const ImVec2 label_size = CalcTextSize(label, NULL, true);
const float preview_width = ((flags & ImGuiComboFlags_WidthFitPreview) && (preview_value != NULL)) ? CalcTextSize(preview_value, NULL, true).x : 0.0f;
const float w = (flags & ImGuiComboFlags_NoPreview) ? arrow_size : ((flags & ImGuiComboFlags_WidthFitPreview) ? (arrow_size + preview_width + style.FramePadding.x * 2.0f) : CalcItemWidth());
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y * 2.0f));
const ImRect total_bb(bb.Min, bb.Max + ImVec2(label_size.x > 0.0f ? style.ItemInnerSpacing.x + label_size.x : 0.0f, 0.0f));
ItemSize(total_bb, style.FramePadding.y);
if (!ItemAdd(total_bb, id, &frame_bb)) return false;
if (!ItemAdd(total_bb, id, &bb)) return false;

// Open on click
bool hovered, held;
bool pressed = ButtonBehavior(frame_bb, id, &hovered, &held, ImGuiButtonFlags_PressedOnClick);
bool popup_open = IsPopupOpen(id, ImGuiPopupFlags_None);
bool pressed = ButtonBehavior(bb, id, &hovered, &held);
const ImGuiID popup_id = ImHashStr("##ComboPopup", 0, id);
bool popup_open = IsPopupOpen(popup_id, ImGuiPopupFlags_None);
if (pressed && !popup_open) {
OpenPopupEx(popup_id, ImGuiPopupFlags_None);
popup_open = true;
}

// Render shape
const ImU32 frame_col = GetColorU32(hovered ? ImGuiCol_FrameBgHovered : ImGuiCol_FrameBg);
const float value_x2 = ImMax(frame_bb.Min.x, frame_bb.Max.x - arrow_size);
RenderNavHighlight(frame_bb, id);
if (!(flags & ImGuiComboFlags_NoPreview))
window->DrawList->AddRectFilled(frame_bb.Min, ImVec2(value_x2, frame_bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersLeft);
const float value_x2 = ImMax(bb.Min.x, bb.Max.x - arrow_size);
RenderNavHighlight(bb, id);
if (!(flags & ImGuiComboFlags_NoPreview)) window->DrawList->AddRectFilled(bb.Min, ImVec2(value_x2, bb.Max.y), frame_col, style.FrameRounding, (flags & ImGuiComboFlags_NoArrowButton) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersLeft);
if (!(flags & ImGuiComboFlags_NoArrowButton)) {
const bool pushed = PushStyleColorWithContrast(ImGuiCol_Button, ImGuiCol_Text, CustomStyle::puContrastedTextColor, CustomStyle::puContrastRatio);
ImU32 bg_col = GetColorU32((popup_open || hovered) ? ImGuiCol_ButtonHovered : ImGuiCol_Button);
ImU32 text_col = GetColorU32(ImGuiCol_Text);
window->DrawList->AddRectFilled(ImVec2(value_x2, frame_bb.Min.y), frame_bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersRight);
if (value_x2 + arrow_size - style.FramePadding.x <= frame_bb.Max.x) RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, frame_bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f);
ImU32 text_col = GetColorU32(ImGuiCol_Text);
window->DrawList->AddRectFilled(ImVec2(value_x2, bb.Min.y), bb.Max, bg_col, style.FrameRounding, (w <= arrow_size) ? ImDrawFlags_RoundCornersAll : ImDrawFlags_RoundCornersRight);
if (value_x2 + arrow_size - style.FramePadding.x <= bb.Max.x) RenderArrow(window->DrawList, ImVec2(value_x2 + style.FramePadding.y, bb.Min.y + style.FramePadding.y), text_col, ImGuiDir_Down, 1.0f);
if (pushed) PopStyleColor();
}
RenderFrameBorder(frame_bb.Min, frame_bb.Max, style.FrameRounding);
if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview)) {
ImVec2 preview_pos = frame_bb.Min + style.FramePadding;
if (g.LogEnabled) LogSetNextTextDecoration("{", "}");
RenderTextClipped(preview_pos, ImVec2(value_x2, frame_bb.Max.y), preview_value, NULL, NULL, ImVec2(0.0f, 0.0f));
}
if (label_size.x > 0) RenderText(ImVec2(frame_bb.Max.x + style.ItemInnerSpacing.x, frame_bb.Min.y + style.FramePadding.y), label);
RenderFrameBorder(bb.Min, bb.Max, style.FrameRounding);

if ((pressed || g.NavActivateId == id) && !popup_open) {
if (window->DC.NavLayerCurrent == 0) window->NavLastIds[0] = id;
OpenPopupEx(id, ImGuiPopupFlags_None);
popup_open = true;
// Custom preview
if (flags & ImGuiComboFlags_CustomPreview) {
g.ComboPreviewData.PreviewRect = ImRect(bb.Min.x, bb.Min.y, value_x2, bb.Max.y);
IM_ASSERT(preview_value == NULL || preview_value[0] == 0);
preview_value = NULL;
}

if (!popup_open) return false;

if (has_window_size_constraint) {
g.NextWindowData.Flags |= ImGuiNextWindowDataFlags_HasSizeConstraint;
g.NextWindowData.SizeConstraintRect.Min.x = ImMax(g.NextWindowData.SizeConstraintRect.Min.x, w);
} else {
if ((flags & ImGuiComboFlags_HeightMask_) == 0) flags |= ImGuiComboFlags_HeightRegular;
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiComboFlags_HeightMask_)); // Only one
int popup_max_height_in_items = -1;
if (flags & ImGuiComboFlags_HeightRegular)
popup_max_height_in_items = 8;
else if (flags & ImGuiComboFlags_HeightSmall)
popup_max_height_in_items = 4;
else if (flags & ImGuiComboFlags_HeightLarge)
popup_max_height_in_items = 20;
SetNextWindowSizeConstraints(ImVec2(w, 0.0f), ImVec2(FLT_MAX, inCalcMaxPopupHeightFromItemCount(popup_max_height_in_items)));
// Render preview and label
if (preview_value != NULL && !(flags & ImGuiComboFlags_NoPreview)) {
if (g.LogEnabled) LogSetNextTextDecoration("{", "}");
RenderTextClipped(bb.Min + style.FramePadding, ImVec2(value_x2, bb.Max.y), preview_value, NULL, NULL);
}
if (label_size.x > 0) RenderText(ImVec2(bb.Max.x + style.ItemInnerSpacing.x, bb.Min.y + style.FramePadding.y), label);

char name[16];
ImFormatString(name, IM_ARRAYSIZE(name), "##Combo_%02d", g.BeginPopupStack.Size); // Recycle windows based on depth

// Position the window given a custom constraint (peak into expected window size so we can position it)
// This might be easier to express with an hypothetical SetNextWindowPosConstraints() function.
if (ImGuiWindow* popup_window = FindWindowByName(name))
if (popup_window->WasActive) {
// Always override 'AutoPosLastDirection' to not leave a chance for a past value to affect us.
ImVec2 size_expected = CalcWindowNextAutoFitSize(popup_window);
if (flags & ImGuiComboFlags_PopupAlignLeft)
popup_window->AutoPosLastDirection = ImGuiDir_Left; // "Below, Toward Left"
else
popup_window->AutoPosLastDirection = ImGuiDir_Down; // "Below, Toward Right (default)"
ImRect r_outer = GetPopupAllowedExtentRect(popup_window);
ImVec2 pos = FindBestWindowPosForPopupEx(frame_bb.GetBL(), size_expected, &popup_window->AutoPosLastDirection, r_outer, frame_bb, ImGuiPopupPositionPolicy_ComboBox);
SetNextWindowPos(pos);
}
if (!popup_open) return false;

// We don't use BeginPopupEx() solely because we have a custom name string, which we could make an argument to BeginPopupEx()
ImGuiWindowFlags window_flags = ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_Popup | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoMove;

// Horizontally align ourselves with the framed text
PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(style.FramePadding.x, style.WindowPadding.y));
bool ret = Begin(name, NULL, window_flags);
PopStyleVar();
if (!ret) {
EndPopup();
IM_ASSERT(0); // This should never happen as we tested for IsPopupOpen() above
return false;
}
return true;
g.NextWindowData.Flags = backup_next_window_data_flags;
return BeginComboPopup(popup_id, bb, flags);
}

bool ContrastedCombo(float vWidth, const char* label, int* current_item, bool (*items_getter)(void*, int, const char**), void* data, int items_count, int popup_max_height_in_items) {
Expand Down
2 changes: 1 addition & 1 deletion ImGuiFileDialog
Submodule ImGuiFileDialog updated 1 files
+4 −0 README.md
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ ImGuiFileDialog is a file selection dialog built for (and using only) [Dear ImGu
My primary goal was to have a custom pane with widgets according to file extension. This was not possible using other
solutions.

## Possible Dialog Customization

![alt text](https://github.com/aiekick/ImGuiFileDialog/blob/demoApp/doc/demo_dialog.png)

## ImGui Supported Version

ImGuiFileDialog follow the master and docking branch of ImGui. Currently ImGui 1.90.4
Expand Down
Binary file added doc/demo_dialog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -702,7 +702,7 @@ int main(int, char**) {
}
if (ImGui::ContrastedButton(ICON_IGFD_FOLDER_OPEN " Open File Dialog with collections of filters")) {
const char* filters =
"All files{.*},Frames Format 1(.001,.NNN){(([.][0-9]{3}))},Frames Format 2(nnn.png){(([0-9]*.png))},Source files (*.cpp *.h *.hpp){.cpp,.h,.hpp},Image files (*.png *.gif *.jpg *.jpeg){.png,.gif,.jpg,.jpeg},.md";
"All files {.*},Frames Format 1 (.001,.NNN){(([.][0-9]{3}))},Frames Format 2 (nnn.png){(([0-9]*.png))},Source files (*.cpp *.h *.hpp){.cpp,.h,.hpp},Image files (*.png *.gif *.jpg *.jpeg){.png,.gif,.jpg,.jpeg},.md";
IGFD::FileDialogConfig config;
config.path = ".";
config.countSelectionMax = 1;
Expand Down

0 comments on commit d1b389c

Please sign in to comment.