mirror of
https://github.com/gwm17/implot.git
synced 2024-11-13 14:38:51 -05:00
Improved Drag and Drop Support (#172)
* prototyping enhanced dnd features * improve dnd demo using new utils * dnd stuff * finish up dnd improvements * remove unused code, fix timestamps
This commit is contained in:
parent
7234801868
commit
67e0876f89
249
implot.cpp
249
implot.cpp
|
@ -31,6 +31,7 @@ Below is a change-log of API breaking changes only. If you are using one of the
|
|||
When you are not sure about a old symbol or function name, try using the Search/Find function of your IDE to look for comments or references in all implot files.
|
||||
You can read releases logs https://github.com/epezent/implot/releases for more details.
|
||||
|
||||
- 2021/01/XX (0.9) - BeginLegendDragDropSource was changed to BeginDragDropSourceItem with a number of other drag and drop improvements.
|
||||
- 2021/01/18 (0.9) - The default behavior for opening context menus was change from double right-click to single right-click. ImPlotInputMap and related functions were moved
|
||||
to implot_internal.h due to its immaturity.
|
||||
- 2020/10/16 (0.8) - ImPlotStyleVar_InfoPadding was changed to ImPlotStyleVar_MousePosPadding
|
||||
|
@ -2265,31 +2266,7 @@ void EndPlot() {
|
|||
DrawList.AddRectFilled(rect.Min, rect.Max, an.ColorBg);
|
||||
DrawList.AddText(pos + gp.Style.AnnotationPadding, an.ColorFg, txt);
|
||||
}
|
||||
PopPlotClipRect();
|
||||
|
||||
// render y-axis drag/drop hover
|
||||
if ((plot.YAxis[1].Present || plot.YAxis[2].Present) && ImGui::IsDragDropPayloadBeingAccepted()) {
|
||||
for (int i = 0; i < IMPLOT_Y_AXES; ++i) {
|
||||
if (plot.YAxis[i].ExtHovered) {
|
||||
float x_loc = gp.YAxisReference[i];
|
||||
ImVec2 p1(x_loc - 5, plot.PlotRect.Min.y - 5);
|
||||
ImVec2 p2(x_loc + 5, plot.PlotRect.Max.y + 5);
|
||||
DrawList.AddRect(p1, p2, ImGui::GetColorU32(ImGuiCol_DragDropTarget), 0.0f, ImDrawCornerFlags_All, 2.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// render x-axis drag/drop hover
|
||||
if (plot.XAxis.Present && ImGui::IsDragDropPayloadBeingAccepted()) {
|
||||
if (plot.XAxis.ExtHovered) {
|
||||
float y_loc = plot.XAxis.HoverRect.Min.y;
|
||||
ImVec2 p1(plot.XAxis.HoverRect.Min.x - 5, y_loc - 5);
|
||||
ImVec2 p2(plot.XAxis.HoverRect.Max.x + 5, y_loc + 5);
|
||||
DrawList.AddRect(p1, p2, ImGui::GetColorU32(ImGuiCol_DragDropTarget), 0.0f, ImDrawCornerFlags_All, 2.0f);
|
||||
}
|
||||
}
|
||||
|
||||
PushPlotClipRect();
|
||||
// render selection/query
|
||||
if (plot.Selecting) {
|
||||
const ImRect select_bb(ImMin(IO.MousePos, plot.SelectStart), ImMax(IO.MousePos, plot.SelectStart));
|
||||
|
@ -2423,9 +2400,9 @@ void EndPlot() {
|
|||
legend_size,
|
||||
plot.LegendLocation,
|
||||
plot.LegendOutside ? gp.Style.PlotPadding : gp.Style.LegendPadding);
|
||||
const ImRect legend_bb(legend_pos, legend_pos + legend_size);
|
||||
plot.LegendRect = ImRect(legend_pos, legend_pos + legend_size);
|
||||
// test hover
|
||||
plot.LegendHovered = plot.FrameHovered && legend_bb.Contains(IO.MousePos);
|
||||
plot.LegendHovered = plot.FrameHovered && plot.LegendRect.Contains(IO.MousePos);
|
||||
|
||||
if (plot.LegendOutside)
|
||||
ImGui::PushClipRect(plot.FrameRect.Min, plot.FrameRect.Max, true);
|
||||
|
@ -2433,11 +2410,14 @@ void EndPlot() {
|
|||
PushPlotClipRect();
|
||||
ImU32 col_bg = GetStyleColorU32(ImPlotCol_LegendBg);
|
||||
ImU32 col_bd = GetStyleColorU32(ImPlotCol_LegendBorder);
|
||||
DrawList.AddRectFilled(legend_bb.Min, legend_bb.Max, col_bg);
|
||||
DrawList.AddRect(legend_bb.Min, legend_bb.Max, col_bd);
|
||||
ShowLegendEntries(plot, legend_bb, plot.LegendHovered, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, plot.LegendOrientation, DrawList);
|
||||
DrawList.AddRectFilled(plot.LegendRect.Min, plot.LegendRect.Max, col_bg);
|
||||
DrawList.AddRect(plot.LegendRect.Min, plot.LegendRect.Max, col_bd);
|
||||
ShowLegendEntries(plot, plot.LegendRect, plot.LegendHovered, gp.Style.LegendInnerPadding, gp.Style.LegendSpacing, plot.LegendOrientation, DrawList);
|
||||
ImGui::PopClipRect();
|
||||
}
|
||||
else {
|
||||
plot.LegendRect = ImRect();
|
||||
}
|
||||
if (plot.LegendFlipSideNextFrame) {
|
||||
plot.LegendOutside = !plot.LegendOutside;
|
||||
plot.LegendFlipSideNextFrame = false;
|
||||
|
@ -2924,6 +2904,150 @@ bool DragPoint(const char* id, double* x, double* y, bool show_label, const ImVe
|
|||
return dragging;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define IMPLOT_ID_PLT 10030910
|
||||
#define IMPLOT_ID_LEG 10030911
|
||||
#define IMPLOT_ID_XAX 10030912
|
||||
#define IMPLOT_ID_YAX 10030913
|
||||
|
||||
bool BeginDragDropTargetEx(int id, const ImRect& rect) {
|
||||
ImGuiContext& G = *GImGui;
|
||||
const ImGuiID ID = G.CurrentWindow->GetID(id);
|
||||
if (ImGui::ItemAdd(rect, ID, &rect) &&
|
||||
ImGui::BeginDragDropTarget())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BeginDragDropTarget() {
|
||||
return BeginDragDropTargetEx(IMPLOT_ID_PLT, GImPlot->CurrentPlot->PlotRect);
|
||||
}
|
||||
|
||||
bool BeginDragDropTargetX() {
|
||||
return BeginDragDropTargetEx(IMPLOT_ID_XAX, GImPlot->CurrentPlot->XAxis.HoverRect);
|
||||
}
|
||||
|
||||
bool BeginDragDropTargetY(ImPlotYAxis axis) {
|
||||
return BeginDragDropTargetEx(IMPLOT_ID_YAX + axis, GImPlot->CurrentPlot->YAxis[axis].HoverRect);
|
||||
}
|
||||
|
||||
bool BeginDragDropTargetLegend() {
|
||||
return !ImHasFlag(GImPlot->CurrentPlot->Flags,ImPlotFlags_NoLegend) &&
|
||||
BeginDragDropTargetEx(IMPLOT_ID_LEG, GImPlot->CurrentPlot->LegendRect);
|
||||
}
|
||||
|
||||
void EndDragDropTarget() {
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
|
||||
bool BeginDragDropSourceEx(ImGuiID source_id, bool is_hovered, ImGuiDragDropFlags flags, ImGuiKeyModFlags key_mods) {
|
||||
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] && g.IO.KeyMods == key_mods) {
|
||||
ImGui::SetActiveID(source_id, window);
|
||||
ImGui::FocusWindow(window);
|
||||
}
|
||||
|
||||
if (g.ActiveId != source_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
g.ActiveIdAllowOverlap = is_hovered;
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
|
||||
bool BeginDragDropSource(ImGuiKeyModFlags key_mods, ImGuiDragDropFlags flags) {
|
||||
if (ImGui::GetIO().KeyMods == key_mods) {
|
||||
GImPlot->CurrentPlot->XAxis.Dragging = false;
|
||||
for (int i = 0; i < IMPLOT_Y_AXES; ++i)
|
||||
GImPlot->CurrentPlot->YAxis[i].Dragging = false;
|
||||
}
|
||||
const ImGuiID ID = GImGui->CurrentWindow->GetID(IMPLOT_ID_PLT);
|
||||
ImRect rect = GImPlot->CurrentPlot->PlotRect;
|
||||
return ImGui::ItemAdd(rect, ID, &rect) && BeginDragDropSourceEx(ID, GImPlot->CurrentPlot->PlotHovered, flags, key_mods);
|
||||
}
|
||||
|
||||
bool BeginDragDropSourceX(ImGuiKeyModFlags key_mods, ImGuiDragDropFlags flags) {
|
||||
if (ImGui::GetIO().KeyMods == key_mods)
|
||||
GImPlot->CurrentPlot->XAxis.Dragging = false;
|
||||
const ImGuiID ID = GImGui->CurrentWindow->GetID(IMPLOT_ID_XAX);
|
||||
ImRect rect = GImPlot->CurrentPlot->XAxis.HoverRect;
|
||||
return ImGui::ItemAdd(rect, ID, &rect) && BeginDragDropSourceEx(ID, GImPlot->CurrentPlot->XAxis.ExtHovered, flags, key_mods);
|
||||
}
|
||||
|
||||
bool BeginDragDropSourceY(ImPlotYAxis axis, ImGuiKeyModFlags key_mods, ImGuiDragDropFlags flags) {
|
||||
if (ImGui::GetIO().KeyMods == key_mods)
|
||||
GImPlot->CurrentPlot->YAxis[axis].Dragging = false;
|
||||
const ImGuiID ID = GImGui->CurrentWindow->GetID(IMPLOT_ID_YAX + axis);
|
||||
ImRect rect = GImPlot->CurrentPlot->YAxis[axis].HoverRect;
|
||||
return ImGui::ItemAdd(rect, ID, &rect) && BeginDragDropSourceEx(ID, GImPlot->CurrentPlot->YAxis[axis].ExtHovered, flags, key_mods);
|
||||
}
|
||||
|
||||
bool BeginDragDropSourceItem(const char* label_id, ImGuiDragDropFlags flags) {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "BeginDragDropSourceItem() 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->LegendHovered;
|
||||
return BeginDragDropSourceEx(source_id, is_hovered, flags, ImGuiKeyModFlags_None);
|
||||
}
|
||||
|
||||
void EndDragDropSource() {
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
void ItemIcon(const ImVec4& col) {
|
||||
ItemIcon(ImGui::ColorConvertFloat4ToU32(col));
|
||||
}
|
||||
|
||||
void ItemIcon(ImU32 col) {
|
||||
const float txt_size = ImGui::GetTextLineHeight();
|
||||
ImVec2 size(txt_size-4,txt_size);
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
ImVec2 pos = window->DC.CursorPos;
|
||||
ImGui::GetWindowDrawList()->AddRectFilled(pos + ImVec2(0,2), pos + size - ImVec2(0,2), col);
|
||||
ImGui::Dummy(size);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SetLegendLocation(ImPlotLocation location, ImPlotOrientation orientation, bool outside) {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "SetLegendLocation() needs to be called between BeginPlot() and EndPlot()!");
|
||||
|
@ -2947,74 +3071,9 @@ bool IsLegendEntryHovered(const char* label_id) {
|
|||
return item && item->LegendHovered;
|
||||
}
|
||||
|
||||
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->LegendHovered;
|
||||
|
||||
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 EndLegendDragDropSource() {
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
|
||||
bool BeginLegendPopup(const char* label_id, ImGuiMouseButton mouse_button) {
|
||||
ImPlotContext& gp = *GImPlot;
|
||||
|
@ -3885,7 +3944,7 @@ bool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const ImPlotTime*
|
|||
ImVec4 col_btn = style.Colors[ImGuiCol_Button];
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0,0,0,0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
|
||||
|
||||
|
||||
const float ht = ImGui::GetFrameHeight();
|
||||
ImVec2 cell_size(ht*1.25f,ht);
|
||||
char buff[32];
|
||||
|
|
42
implot.h
42
implot.h
|
@ -527,7 +527,7 @@ IMPLOT_API bool DragPoint(const char* id, double* x, double* y, bool show_label
|
|||
// Legend Utils and Tools
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// The following functions MUST be called between Begin/EndPlot!
|
||||
// The following functions MUST be called BETWEEN Begin/EndPlot!
|
||||
|
||||
// Set the location of the current plot's legend.
|
||||
IMPLOT_API void SetLegendLocation(ImPlotLocation location, ImPlotOrientation orientation = ImPlotOrientation_Vertical, bool outside = false);
|
||||
|
@ -535,15 +535,43 @@ IMPLOT_API void SetLegendLocation(ImPlotLocation location, ImPlotOrientation ori
|
|||
IMPLOT_API void SetMousePosLocation(ImPlotLocation location);
|
||||
// Returns true if a plot item legend entry is hovered.
|
||||
IMPLOT_API bool IsLegendEntryHovered(const char* label_id);
|
||||
// Begin a drag and drop source from a legend entry. The only supported flag is SourceNoPreviewTooltip
|
||||
IMPLOT_API bool BeginLegendDragDropSource(const char* label_id, ImGuiDragDropFlags flags = 0);
|
||||
// End legend drag and drop source.
|
||||
IMPLOT_API void EndLegendDragDropSource();
|
||||
|
||||
// Begin a popup for a legend entry.
|
||||
IMPLOT_API bool BeginLegendPopup(const char* label_id, ImGuiMouseButton mouse_button = 1);
|
||||
// End a popup for a legend entry.
|
||||
IMPLOT_API void EndLegendPopup();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Drag and Drop Utils
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// The following functions MUST be called BETWEEN Begin/EndPlot!
|
||||
|
||||
// Turns the current plot's plotting area into a drag and drop target. Don't forget to call EndDragDropTarget!
|
||||
IMPLOT_API bool BeginDragDropTarget();
|
||||
// Turns the current plot's X-axis into a drag and drop target. Don't forget to call EndDragDropTarget!
|
||||
IMPLOT_API bool BeginDragDropTargetX();
|
||||
// Turns the current plot's Y-Axis into a drag and drop target. Don't forget to call EndDragDropTarget!
|
||||
IMPLOT_API bool BeginDragDropTargetY(ImPlotYAxis axis = ImPlotYAxis_1);
|
||||
// Turns the current plot's legend into a drag and drop target. Don't forget to call EndDragDropTarget!
|
||||
IMPLOT_API bool BeginDragDropTargetLegend();
|
||||
// Ends a drag and drop target (currently just an alias for ImGui::EndDragDropTarget).
|
||||
IMPLOT_API void EndDragDropTarget();
|
||||
|
||||
// NB: By default, plot and axes drag and drop sources require holding the Ctrl modifier to initiate the drag.
|
||||
// You can change the modifier if desired. If ImGuiKeyModFlags_None is provided, the axes will be locked from panning.
|
||||
|
||||
// Turns the current plot's plotting area into a drag and drop source. Don't forget to call EndDragDropSource!
|
||||
IMPLOT_API bool BeginDragDropSource(ImGuiKeyModFlags key_mods = ImGuiKeyModFlags_Ctrl, ImGuiDragDropFlags flags = 0);
|
||||
// Turns the current plot's X-axis into a drag and drop source. Don't forget to call EndDragDropSource!
|
||||
IMPLOT_API bool BeginDragDropSourceX(ImGuiKeyModFlags key_mods = ImGuiKeyModFlags_Ctrl, ImGuiDragDropFlags flags = 0);
|
||||
// Turns the current plot's Y-axis into a drag and drop source. Don't forget to call EndDragDropSource!
|
||||
IMPLOT_API bool BeginDragDropSourceY(ImPlotYAxis axis = ImPlotYAxis_1, ImGuiKeyModFlags key_mods = ImGuiKeyModFlags_Ctrl, ImGuiDragDropFlags flags = 0);
|
||||
// Turns an item in the current plot's legend into drag and drop source. Don't forget to call EndDragDropSource!
|
||||
IMPLOT_API bool BeginDragDropSourceItem(const char* label_id, ImGuiDragDropFlags flags = 0);
|
||||
// Ends a drag and drop source (currently just an alias for ImGui::EndDragDropSource).
|
||||
IMPLOT_API void EndDragDropSource();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Plot and Item Styling
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -645,6 +673,10 @@ IMPLOT_API const char* GetColormapName(ImPlotColormap colormap);
|
|||
// Miscellaneous
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Render a icon similar to those that appear in legends (nifty for data lists).
|
||||
IMPLOT_API void ItemIcon(const ImVec4& col);
|
||||
IMPLOT_API void ItemIcon(ImU32 col);
|
||||
|
||||
// Get the plot draw list for rendering to the current plot area.
|
||||
IMPLOT_API ImDrawList* GetPlotDrawList();
|
||||
// Push clip rect for rendering to current plot area.
|
||||
|
|
329
implot_demo.cpp
329
implot_demo.cpp
|
@ -81,8 +81,8 @@ struct ScrollingBuffer {
|
|||
int MaxSize;
|
||||
int Offset;
|
||||
ImVector<ImVec2> Data;
|
||||
ScrollingBuffer() {
|
||||
MaxSize = 2000;
|
||||
ScrollingBuffer(int max_size = 2000) {
|
||||
MaxSize = max_size;
|
||||
Offset = 0;
|
||||
Data.reserve(MaxSize);
|
||||
}
|
||||
|
@ -663,8 +663,8 @@ void ShowDemoWindow(bool* p_open) {
|
|||
}
|
||||
if (ImGui::CollapsingHeader("Time Formatted Axes")) {
|
||||
|
||||
static double t_min = 1577836800; // 01/01/2020 @ 12:00:00am (UTC)
|
||||
static double t_max = 1609459200; // 01/01/2021 @ 12:00:00am (UTC)
|
||||
static double t_min = 1609459200; // 01/01/2021 @ 12:00:00am (UTC)
|
||||
static double t_max = 1640995200; // 01/01/2022 @ 12:00:00am (UTC)
|
||||
|
||||
ImGui::BulletText("When ImPlotAxisFlags_Time is enabled on the X-Axis, values are interpreted as\n"
|
||||
"UNIX timestamps in seconds and axis labels are formated as date/time.");
|
||||
|
@ -969,175 +969,216 @@ void ShowDemoWindow(bool* p_open) {
|
|||
}
|
||||
//-------------------------------------------------------------------------
|
||||
if (ImGui::CollapsingHeader("Drag and Drop")) {
|
||||
const int K_CHANNELS = 9;
|
||||
srand((int)(10000000 * DEMO_TIME));
|
||||
static bool paused = false;
|
||||
static bool init = true;
|
||||
static ScrollingBuffer data[K_CHANNELS];
|
||||
static bool show[K_CHANNELS];
|
||||
static int yAxis[K_CHANNELS];
|
||||
if (init) {
|
||||
for (int i = 0; i < K_CHANNELS; ++i) {
|
||||
show[i] = false;
|
||||
yAxis[i] = 0;
|
||||
ImGui::BulletText("Drag/drop items from the left column.");
|
||||
ImGui::BulletText("Drag/drop items between plots.");
|
||||
ImGui::Indent();
|
||||
ImGui::BulletText("Plot 1 Targets: Plot, Y-Axes, Legend");
|
||||
ImGui::BulletText("Plot 1 Sources: Legend Items");
|
||||
ImGui::BulletText("Plot 2 Targets: Plot, X-Axis, Y-Axis");
|
||||
ImGui::BulletText("Plot 2 Sources: Plot, X-Axis, Y-Axis (hold Ctrl)");
|
||||
ImGui::Unindent();
|
||||
|
||||
// convenience struct to manage DND items; do this however you like
|
||||
struct MyDndItem {
|
||||
int Idx;
|
||||
int Plt;
|
||||
int Yax;
|
||||
char Label[16];
|
||||
ImVector<ImVec2> Data;
|
||||
ImVec4 Color;
|
||||
MyDndItem() {
|
||||
static int i = 0;
|
||||
Idx = i++;
|
||||
Plt = 0;
|
||||
Yax = ImPlotYAxis_1;
|
||||
sprintf(Label, "%02d Hz", Idx+1);
|
||||
Color = ImPlot::GetColormapColor(Idx);
|
||||
Data.reserve(1001);
|
||||
for (int k = 0; k < 1001; ++k) {
|
||||
float t = k * 1.0f / 999;
|
||||
Data.push_back(ImVec2(t, 0.5f + 0.5f * sinf(2*3.14f*t*(Idx+1))));
|
||||
}
|
||||
}
|
||||
init = false;
|
||||
void Reset() { Plt = 0; Yax = ImPlotYAxis_1; }
|
||||
};
|
||||
|
||||
const int k_dnd = 20;
|
||||
static MyDndItem dnd[k_dnd];
|
||||
static MyDndItem* dndx = NULL; // for plot 2
|
||||
static MyDndItem* dndy = NULL; // for plot 2
|
||||
|
||||
// child window to serve as initial source for our DND items
|
||||
ImGui::BeginChild("DND_LEFT",ImVec2(100,400));
|
||||
if (ImGui::Button("Reset Data", ImVec2(100, 0))) {
|
||||
for (int k = 0; k < k_dnd; ++k)
|
||||
dnd[k].Reset();
|
||||
dndx = dndy = NULL;
|
||||
}
|
||||
ImGui::BulletText("Drag data items from the left column onto the plot or onto a specific y-axis.");
|
||||
ImGui::BulletText("Redrag data items from the legend onto other y-axes.");
|
||||
ImGui::BeginGroup();
|
||||
if (ImGui::Button("Clear", ImVec2(100, 0))) {
|
||||
for (int i = 0; i < K_CHANNELS; ++i) {
|
||||
show[i] = false;
|
||||
data[i].Data.shrink(0);
|
||||
data[i].Offset = 0;
|
||||
}
|
||||
}
|
||||
if (ImGui::Button(paused ? "Resume" : "Pause", ImVec2(100,0)))
|
||||
paused = !paused;
|
||||
for (int i = 0; i < K_CHANNELS; ++i) {
|
||||
char label[16];
|
||||
sprintf(label, show[i] ? "data_%d (Y%d)" : "data_%d", i, yAxis[i]+1);
|
||||
ImGui::Selectable(label, false, 0, ImVec2(100, 0));
|
||||
for (int k = 0; k < k_dnd; ++k) {
|
||||
if (dnd[k].Plt > 0)
|
||||
continue;
|
||||
ImPlot::ItemIcon(dnd[k].Color); ImGui::SameLine();
|
||||
ImGui::Selectable(dnd[k].Label, false, 0, ImVec2(100, 0));
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) {
|
||||
ImGui::SetDragDropPayload("DND_PLOT", &i, sizeof(int));
|
||||
ImGui::TextUnformatted(label);
|
||||
ImGui::SetDragDropPayload("MY_DND", &k, sizeof(int));
|
||||
ImPlot::ItemIcon(dnd[k].Color); ImGui::SameLine();
|
||||
ImGui::TextUnformatted(dnd[k].Label);
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
ImGui::SameLine();
|
||||
srand((unsigned int)DEMO_TIME*10000000);
|
||||
static float t = 0;
|
||||
if (!paused) {
|
||||
t += ImGui::GetIO().DeltaTime;
|
||||
for (int i = 0; i < K_CHANNELS; ++i) {
|
||||
if (show[i])
|
||||
data[i].AddPoint(t, (i+1)*0.1f + RandomRange(-0.01f,0.01f));
|
||||
ImGui::EndChild();
|
||||
if (ImGui::BeginDragDropTarget()) {
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("MY_DND")) {
|
||||
int i = *(int*)payload->Data; dnd[i].Reset();
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
ImPlot::SetNextPlotLimitsX((double)t - 10, t, paused ? ImGuiCond_Once : ImGuiCond_Always);
|
||||
if (ImPlot::BeginPlot("##DND", NULL, NULL, ImVec2(-1,0), ImPlotFlags_YAxis2 | ImPlotFlags_YAxis3, ImPlotAxisFlags_NoTickLabels)) {
|
||||
for (int i = 0; i < K_CHANNELS; ++i) {
|
||||
if (show[i] && data[i].Data.size() > 0) {
|
||||
char label[K_CHANNELS];
|
||||
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(float));
|
||||
// allow legend labels to be dragged and dropped
|
||||
if (ImPlot::BeginLegendDragDropSource(label)) {
|
||||
ImGui::SetDragDropPayload("DND_PLOT", &i, sizeof(int));
|
||||
ImGui::TextUnformatted(label);
|
||||
ImPlot::EndLegendDragDropSource();
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginChild("DND_RIGHT",ImVec2(-1,400));
|
||||
// plot 1 (time series)
|
||||
ImPlotAxisFlags flags = ImPlotAxisFlags_NoTickLabels | ImPlotAxisFlags_NoGridLines;
|
||||
if (ImPlot::BeginPlot("##DND1", NULL, "[drop here]", ImVec2(-1,195), ImPlotFlags_YAxis2 | ImPlotFlags_YAxis3, flags | ImPlotAxisFlags_Lock, flags, flags, flags, "[drop here]", "[drop here]")) {
|
||||
for (int k = 0; k < k_dnd; ++k) {
|
||||
if (dnd[k].Plt == 1 && dnd[k].Data.size() > 0) {
|
||||
ImPlot::SetPlotYAxis(dnd[k].Yax);
|
||||
ImPlot::SetNextLineStyle(dnd[k].Color);
|
||||
static char label[16];
|
||||
sprintf(label,"%s (Y%d)", dnd[k].Label, dnd[k].Yax+1);
|
||||
ImPlot::PlotLine(label, &dnd[k].Data[0].x, &dnd[k].Data[0].y, dnd[k].Data.size(), 0, 2 * sizeof(float));
|
||||
// allow legend item labels to be DND sources
|
||||
if (ImPlot::BeginDragDropSourceItem(label)) {
|
||||
ImGui::SetDragDropPayload("MY_DND", &k, sizeof(int));
|
||||
ImPlot::ItemIcon(dnd[k].Color); ImGui::SameLine();
|
||||
ImGui::TextUnformatted(dnd[k].Label);
|
||||
ImPlot::EndDragDropSource();
|
||||
}
|
||||
}
|
||||
}
|
||||
// make our plot a drag and drop target
|
||||
if (ImGui::BeginDragDropTarget()) {
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_PLOT")) {
|
||||
int i = *(int*)payload->Data;
|
||||
show[i] = true;
|
||||
yAxis[i] = 0;
|
||||
// set specific y-axis if hovered
|
||||
for (int y = 0; y < 3; y++) {
|
||||
if (ImPlot::IsPlotYAxisHovered(y))
|
||||
yAxis[i] = y;
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
// allow the main plot area to be a DND target
|
||||
if (ImPlot::BeginDragDropTarget()) {
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("MY_DND")) {
|
||||
int i = *(int*)payload->Data; dnd[i].Plt = 1; dnd[i].Yax = 0;
|
||||
}
|
||||
ImPlot::EndDragDropTarget();
|
||||
}
|
||||
// allow each y-axis to be a DND target
|
||||
for (int y = 0; y < 3; ++y) {
|
||||
if (ImPlot::BeginDragDropTargetY(y)) {
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("MY_DND")) {
|
||||
int i = *(int*)payload->Data; dnd[i].Plt = 1; dnd[i].Yax = y;
|
||||
}
|
||||
ImPlot::EndDragDropTarget();
|
||||
}
|
||||
}
|
||||
// allow the legend to be a DND target
|
||||
if (ImPlot::BeginDragDropTargetLegend()) {
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("MY_DND")) {
|
||||
int i = *(int*)payload->Data; dnd[i].Plt = 1; dnd[i].Yax = 0;
|
||||
}
|
||||
ImPlot::EndDragDropTarget();
|
||||
}
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
// plot 2 (Lissajous)
|
||||
ImPlot::PushStyleColor(ImPlotCol_XAxis, dndx == NULL ? ImPlot::GetStyle().Colors[ImPlotCol_XAxis] : dndx->Color);
|
||||
ImPlot::PushStyleColor(ImPlotCol_YAxis, dndy == NULL ? ImPlot::GetStyle().Colors[ImPlotCol_YAxis] : dndy->Color);
|
||||
if (ImPlot::BeginPlot("##DND2", dndx == NULL ? "[drop here]" : dndx->Label, dndy == NULL ? "[drop here]" : dndy->Label, ImVec2(-1,195), 0, flags, flags )) {
|
||||
if (dndx != NULL && dndy != NULL) {
|
||||
ImVec4 mixed((dndx->Color.x + dndy->Color.x)/2,(dndx->Color.y + dndy->Color.y)/2,(dndx->Color.z + dndy->Color.z)/2,(dndx->Color.w + dndy->Color.w)/2);
|
||||
ImPlot::SetNextLineStyle(mixed);
|
||||
ImPlot::PlotLine("##dndxy", &dndx->Data[0].y, &dndy->Data[0].y, dndx->Data.size(), 0, 2 * sizeof(float));
|
||||
}
|
||||
// allow the x-axis to be a DND target
|
||||
if (ImPlot::BeginDragDropTargetX()) {
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("MY_DND")) {
|
||||
int i = *(int*)payload->Data; dndx = &dnd[i];
|
||||
}
|
||||
ImPlot::EndDragDropTarget();
|
||||
}
|
||||
// allow the x-axis to be a DND source
|
||||
if (dndx != NULL && ImPlot::BeginDragDropSourceX()) {
|
||||
ImGui::SetDragDropPayload("MY_DND", &dndx->Idx, sizeof(int));
|
||||
ImPlot::ItemIcon(dndx->Color); ImGui::SameLine();
|
||||
ImGui::TextUnformatted(dndx->Label);
|
||||
ImPlot::EndDragDropSource();
|
||||
}
|
||||
// allow the y-axis to be a DND target
|
||||
if (ImPlot::BeginDragDropTargetY()) {
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("MY_DND")) {
|
||||
int i = *(int*)payload->Data; dndy = &dnd[i];
|
||||
}
|
||||
ImPlot::EndDragDropTarget();
|
||||
}
|
||||
// allow the y-axis to be a DND source
|
||||
if (dndy != NULL && ImPlot::BeginDragDropSourceY()) {
|
||||
ImGui::SetDragDropPayload("MY_DND", &dndy->Idx, sizeof(int));
|
||||
ImPlot::ItemIcon(dndy->Color); ImGui::SameLine();
|
||||
ImGui::TextUnformatted(dndy->Label);
|
||||
ImPlot::EndDragDropSource();
|
||||
}
|
||||
// allow the plot area to be a DND target
|
||||
if (ImPlot::BeginDragDropTarget()) {
|
||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("MY_DND")) {
|
||||
int i = *(int*)payload->Data; dndx = dndy = &dnd[i];
|
||||
}
|
||||
}
|
||||
// allow the plot area to be a DND source
|
||||
if (ImPlot::BeginDragDropSource()) {
|
||||
ImGui::TextUnformatted("Yes, you can\ndrag this!");
|
||||
ImPlot::EndDragDropSource();
|
||||
}
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
ImPlot::PopStyleColor(2);
|
||||
ImGui::EndChild();
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
if (ImGui::CollapsingHeader("Digital and Analog Signals")) {
|
||||
static bool paused = false;
|
||||
#define K_PLOT_DIGITAL_CH_COUNT 4
|
||||
#define K_PLOT_ANALOG_CH_COUNT 4
|
||||
static ScrollingBuffer dataDigital[K_PLOT_DIGITAL_CH_COUNT];
|
||||
static ScrollingBuffer dataAnalog[K_PLOT_ANALOG_CH_COUNT];
|
||||
static bool showDigital[K_PLOT_DIGITAL_CH_COUNT];
|
||||
static bool showAnalog[K_PLOT_ANALOG_CH_COUNT];
|
||||
|
||||
ImGui::BulletText("You can plot digital and analog signals on the same plot.");
|
||||
ImGui::BulletText("Digital signals do not respond to Y drag and zoom, so that");
|
||||
ImGui::Indent();
|
||||
ImGui::Text("you can drag analog signals over the rising/falling digital edge.");
|
||||
ImGui::Unindent();
|
||||
ImGui::BeginGroup();
|
||||
if (ImGui::Button("Clear", ImVec2(100, 0))) {
|
||||
for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i)
|
||||
showDigital[i] = false;
|
||||
for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i)
|
||||
showAnalog[i] = false;
|
||||
}
|
||||
if (ImGui::Button(paused ? "Resume" : "Pause", ImVec2(100,0)))
|
||||
paused = !paused;
|
||||
for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) {
|
||||
char label[32];
|
||||
sprintf(label, "digital_%d", i);
|
||||
ImGui::Checkbox(label, &showDigital[i]);
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) {
|
||||
ImGui::SetDragDropPayload("DND_DIGITAL_PLOT", &i, sizeof(int));
|
||||
ImGui::TextUnformatted(label);
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) {
|
||||
char label[32];
|
||||
sprintf(label, "analog_%d", i);
|
||||
ImGui::Checkbox(label, &showAnalog[i]);
|
||||
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None)) {
|
||||
ImGui::SetDragDropPayload("DND_ANALOG_PLOT", &i, sizeof(int));
|
||||
ImGui::TextUnformatted(label);
|
||||
ImGui::EndDragDropSource();
|
||||
}
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
ImGui::SameLine();
|
||||
|
||||
static bool paused = false;
|
||||
static ScrollingBuffer dataDigital[2];
|
||||
static ScrollingBuffer dataAnalog[2];
|
||||
static bool showDigital[2] = {true, false};
|
||||
static bool showAnalog[2] = {true, false};
|
||||
|
||||
char label[32];
|
||||
ImGui::Checkbox("digital_0", &showDigital[0]); ImGui::SameLine();
|
||||
ImGui::Checkbox("digital_1", &showDigital[1]); ImGui::SameLine();
|
||||
ImGui::Checkbox("analog_0", &showAnalog[0]); ImGui::SameLine();
|
||||
ImGui::Checkbox("analog_1", &showAnalog[1]);
|
||||
|
||||
static float t = 0;
|
||||
if (!paused) {
|
||||
t += ImGui::GetIO().DeltaTime;
|
||||
//digital signal values
|
||||
int i = 0;
|
||||
if (showDigital[i])
|
||||
dataDigital[i].AddPoint(t, sinf(2*t) > 0.45);
|
||||
i++;
|
||||
if (showDigital[i])
|
||||
dataDigital[i].AddPoint(t, sinf(2*t) < 0.45);
|
||||
i++;
|
||||
if (showDigital[i])
|
||||
dataDigital[i].AddPoint(t, fmodf(t,5.0f));
|
||||
i++;
|
||||
if (showDigital[i])
|
||||
dataDigital[i].AddPoint(t, sinf(2*t) < 0.17);
|
||||
if (showDigital[0])
|
||||
dataDigital[0].AddPoint(t, sinf(2*t) > 0.45);
|
||||
if (showDigital[1])
|
||||
dataDigital[1].AddPoint(t, sinf(2*t) < 0.45);
|
||||
//Analog signal values
|
||||
i = 0;
|
||||
if (showAnalog[i])
|
||||
dataAnalog[i].AddPoint(t, sinf(2*t));
|
||||
i++;
|
||||
if (showAnalog[i])
|
||||
dataAnalog[i].AddPoint(t, cosf(2*t));
|
||||
i++;
|
||||
if (showAnalog[i])
|
||||
dataAnalog[i].AddPoint(t, sinf(2*t) * cosf(2*t));
|
||||
i++;
|
||||
if (showAnalog[i])
|
||||
dataAnalog[i].AddPoint(t, sinf(2*t) - cosf(2*t));
|
||||
if (showAnalog[0])
|
||||
dataAnalog[0].AddPoint(t, sinf(2*t));
|
||||
if (showAnalog[1])
|
||||
dataAnalog[1].AddPoint(t, cosf(2*t));
|
||||
}
|
||||
ImPlot::SetNextPlotLimitsY(-1, 1);
|
||||
ImPlot::SetNextPlotLimitsX(t - 10.0, t, paused ? ImGuiCond_Once : ImGuiCond_Always);
|
||||
if (ImPlot::BeginPlot("##Digital")) {
|
||||
for (int i = 0; i < K_PLOT_DIGITAL_CH_COUNT; ++i) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (showDigital[i] && dataDigital[i].Data.size() > 0) {
|
||||
char label[32];
|
||||
sprintf(label, "digital_%d", i);
|
||||
ImPlot::PlotDigital(label, &dataDigital[i].Data[0].x, &dataDigital[i].Data[0].y, dataDigital[i].Data.size(), dataDigital[i].Offset, 2 * sizeof(float));
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < K_PLOT_ANALOG_CH_COUNT; ++i) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
if (showAnalog[i]) {
|
||||
char label[32];
|
||||
sprintf(label, "analog_%d", i);
|
||||
if (dataAnalog[i].Data.size() > 0)
|
||||
ImPlot::PlotLine(label, &dataAnalog[i].Data[0].x, &dataAnalog[i].Data[0].y, dataAnalog[i].Data.size(), dataAnalog[i].Offset, 2 * sizeof(float));
|
||||
|
@ -1145,22 +1186,6 @@ void ShowDemoWindow(bool* p_open) {
|
|||
}
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
if (ImGui::BeginDragDropTarget()) {
|
||||
const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("DND_DIGITAL_PLOT");
|
||||
if (payload) {
|
||||
int i = *(int*)payload->Data;
|
||||
showDigital[i] = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
payload = ImGui::AcceptDragDropPayload("DND_ANALOG_PLOT");
|
||||
if (payload) {
|
||||
int i = *(int*)payload->Data;
|
||||
showAnalog[i] = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndDragDropTarget();
|
||||
}
|
||||
}
|
||||
if (ImGui::CollapsingHeader("Tables")) {
|
||||
#ifdef IMGUI_HAS_TABLE
|
||||
|
|
|
@ -572,6 +572,7 @@ struct ImPlotPlot
|
|||
ImRect CanvasRect;
|
||||
ImRect PlotRect;
|
||||
ImRect AxesRect;
|
||||
ImRect LegendRect;
|
||||
|
||||
ImPlotPlot() {
|
||||
Flags = PreviousFlags = ImPlotFlags_None;
|
||||
|
|
Loading…
Reference in New Issue
Block a user