diff --git a/implot.cpp b/implot.cpp index 9a5ce87..2aba360 100644 --- a/implot.cpp +++ b/implot.cpp @@ -1864,6 +1864,75 @@ bool IsLegendEntryHovered(const char* label_id) { return false; } +bool BeginLegendDragDropSource(const char* label_id, ImGuiDragDropFlags flags) { + ImPlotContext& gp = *GImPlot; + IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "BeginLegendDragDropSource() needs to be called between BeginPlot() and EndPlot()!"); + ImGuiID source_id = ImGui::GetID(label_id); + ImPlotItem* item = gp.CurrentPlot->Items.GetByKey(source_id); + bool is_hovered = item && item->Highlight; + + ImGuiContext& g = *GImGui; + ImGuiWindow* window = g.CurrentWindow; + + ImGuiMouseButton mouse_button = ImGuiMouseButton_Left; + + if (g.IO.MouseDown[mouse_button] == false) { + if (g.ActiveId == source_id) + ImGui::ClearActiveID(); + return false; + } + + if (is_hovered && g.IO.MouseClicked[mouse_button]) { + ImGui::SetActiveID(source_id, window); + ImGui::FocusWindow(window); + } + + if (g.ActiveId != source_id) + return false; + + // Allow the underlying widget to display/return hovered during the mouse + // release frame, else we would get a flicker. + g.ActiveIdAllowOverlap = is_hovered; + + // Disable navigation and key inputs while dragging + g.ActiveIdUsingNavDirMask = ~(ImU32)0; + g.ActiveIdUsingNavInputMask = ~(ImU32)0; + g.ActiveIdUsingKeyInputMask = ~(ImU64)0; + + if (ImGui::IsMouseDragging(mouse_button)) { + if (!g.DragDropActive) { + ImGui::ClearDragDrop(); + ImGuiPayload& payload = g.DragDropPayload; + payload.SourceId = source_id; + payload.SourceParentId = 0; + g.DragDropActive = true; + g.DragDropSourceFlags = 0; + g.DragDropMouseButton = mouse_button; + } + g.DragDropSourceFrameCount = g.FrameCount; + g.DragDropWithinSource = true; + + if (!(flags & ImGuiDragDropFlags_SourceNoPreviewTooltip)) { + // Target can request the Source to not display its tooltip (we use a + // dedicated flag to make this request explicit) We unfortunately can't + // just modify the source flags and skip the call to BeginTooltip, as + // caller may be emitting contents. + ImGui::BeginTooltip(); + if (g.DragDropAcceptIdPrev && (g.DragDropAcceptFlags & ImGuiDragDropFlags_AcceptNoPreviewTooltip)) { + ImGuiWindow* tooltip_window = g.CurrentWindow; + tooltip_window->SkipItems = true; + tooltip_window->HiddenFramesCanSkipItems = 1; + } + } + return true; + } + return false; +} + +void EndDragDropSource() { + ImGui::EndDragDropSource(); +} + //----------------------------------------------------------------------------- // STYLING //----------------------------------------------------------------------------- diff --git a/implot.h b/implot.h index 378b45c..aed03e8 100644 --- a/implot.h +++ b/implot.h @@ -494,6 +494,11 @@ void PushPlotClipRect(); // Pop plot clip rect. void PopPlotClipRect(); +// Begin a drag and drop source from a legend entry. The only supported flag is SourceNoPreviewTooltip +bool BeginLegendDragDropSource(const char* label_id, ImGuiDragDropFlags flags = 0); +// End drag and drop source. +void EndDragDropSource(); + //----------------------------------------------------------------------------- // Demo (add implot_demo.cpp to your sources!) //----------------------------------------------------------------------------- diff --git a/implot_demo.cpp b/implot_demo.cpp index a92a5f3..ed3eff9 100644 --- a/implot_demo.cpp +++ b/implot_demo.cpp @@ -733,6 +733,7 @@ void ShowDemoWindow(bool* p_open) { init = false; } ImGui::BulletText("Drag data items from the left column onto the plot or onto a specific y-axis."); + ImGui::BulletText("Drag data items from the legend onto a specific y-axis."); ImGui::BeginGroup(); if (ImGui::Button("Clear", ImVec2(100, 0))) { for (int i = 0; i < K_CHANNELS; ++i) { @@ -772,6 +773,11 @@ void ShowDemoWindow(bool* p_open) { sprintf(label, "data_%d", i); ImPlot::SetPlotYAxis(yAxis[i]); ImPlot::PlotLine(label, &data[i].Data[0].x, &data[i].Data[0].y, data[i].Data.size(), data[i].Offset, 2 * sizeof(t_float)); + if (ImPlot::BeginLegendDragDropSource(label)) { + ImGui::SetDragDropPayload("DND_PLOT", &i, sizeof(int)); + ImGui::TextUnformatted(label); + ImPlot::EndDragDropSource(); + } } } if (ImGui::BeginDragDropTarget()) { @@ -1354,4 +1360,4 @@ void ShowBenchmarkTool() { } } -} \ No newline at end of file +}