1
0
Fork 0
mirror of https://github.com/gwm17/implot.git synced 2024-11-23 02:38:53 -05:00

handle time/log formatting for drag lines and points

This commit is contained in:
epezent 2020-09-21 07:09:14 -05:00
parent 93bab1930e
commit 28fedd01f9
3 changed files with 65 additions and 30 deletions

View File

@ -391,13 +391,13 @@ void Reset(ImPlotContext* ctx) {
// Plot Utils // Plot Utils
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
ImPlotState* GetPlot(const char* title) { ImPlotPlot* GetPlot(const char* title) {
ImGuiWindow* Window = GImGui->CurrentWindow; ImGuiWindow* Window = GImGui->CurrentWindow;
const ImGuiID ID = Window->GetID(title); const ImGuiID ID = Window->GetID(title);
return GImPlot->Plots.GetByKey(ID); return GImPlot->Plots.GetByKey(ID);
} }
ImPlotState* GetCurrentPlot() { ImPlotPlot* GetCurrentPlot() {
return GImPlot->CurrentPlot; return GImPlot->CurrentPlot;
} }
@ -1122,6 +1122,24 @@ void AddTicksTime(const ImPlotRange& range, float plot_width, bool hour24, ImPlo
// Axis Utils // Axis Utils
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int LabelAxisValue(const ImPlotAxis& axis, const ImPlotTickCollection& ticks, double value, char* buff, int size) {
ImPlotContext& gp = *GImPlot;
if (ImHasFlag(axis.Flags, ImPlotAxisFlags_LogScale)) {
return snprintf(buff, size, "%.3E", value);
}
else if (ImHasFlag(axis.Flags, ImPlotAxisFlags_Time)) {
ImPlotTimeUnit unit = (axis.Direction == ImPlotDirection_Horizontal)
? GetUnitForRange(axis.Range.Size() / (gp.BB_Plot.GetWidth() / 100))
: GetUnitForRange(axis.Range.Size() / (gp.BB_Plot.GetHeight() / 100));
return gp.Style.Use24HourClock ? FormatTime24(ImPlotTime::FromDouble(value), buff, size, TimeFormatMouseCursor[unit])
: FormatTime12(ImPlotTime::FromDouble(value), buff, size, TimeFormatMouseCursor[unit]);
}
else {
double range = ticks.Size > 1 ? (ticks.Ticks[1].PlotPos - ticks.Ticks[0].PlotPos) : axis.Range.Size();
return snprintf(buff, size, "%.*f", Precision(range), value);
}
}
void UpdateAxisColors(int axis_flag, ImPlotAxisColor* col) { void UpdateAxisColors(int axis_flag, ImPlotAxisColor* col) {
const ImVec4 col_label = GetStyleColorVec4(axis_flag); const ImVec4 col_label = GetStyleColorVec4(axis_flag);
const ImVec4 col_grid = GetStyleColorVec4(axis_flag + 1); const ImVec4 col_grid = GetStyleColorVec4(axis_flag + 1);
@ -1131,7 +1149,6 @@ void UpdateAxisColors(int axis_flag, ImPlotAxisColor* col) {
col->MinTxt = ImGui::GetColorU32(col_label); col->MinTxt = ImGui::GetColorU32(col_label);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// BeginPlot() // BeginPlot()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1160,7 +1177,7 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
bool just_created = gp.Plots.GetByKey(ID) == NULL; bool just_created = gp.Plots.GetByKey(ID) == NULL;
gp.CurrentPlot = gp.Plots.GetOrAddByKey(ID); gp.CurrentPlot = gp.Plots.GetOrAddByKey(ID);
ImPlotState &plot = *gp.CurrentPlot; ImPlotPlot &plot = *gp.CurrentPlot;
plot.CurrentYAxis = 0; plot.CurrentYAxis = 0;
@ -1878,7 +1895,7 @@ void ShowAxisContextMenu(ImPlotAxisState& state, bool time_allowed) {
} }
void ShowPlotContextMenu(ImPlotState& plot) { void ShowPlotContextMenu(ImPlotPlot& plot) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
if (ImGui::BeginMenu("X-Axis")) { if (ImGui::BeginMenu("X-Axis")) {
ImGui::PushID("X"); ImGui::PushID("X");
@ -1956,7 +1973,7 @@ void EndPlot() {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "Mismatched BeginPlot()/EndPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "Mismatched BeginPlot()/EndPlot()!");
ImGuiContext &G = *GImGui; ImGuiContext &G = *GImGui;
ImPlotState &plot = *gp.CurrentPlot; ImPlotPlot &plot = *gp.CurrentPlot;
ImGuiWindow * Window = G.CurrentWindow; ImGuiWindow * Window = G.CurrentWindow;
ImDrawList & DrawList = *Window->DrawList; ImDrawList & DrawList = *Window->DrawList;
const ImGuiIO & IO = ImGui::GetIO(); const ImGuiIO & IO = ImGui::GetIO();
@ -2202,7 +2219,7 @@ void EndPlot() {
DrawList.AddLine(v3, v4, col); DrawList.AddLine(v3, v4, col);
} }
// render mouse pos // render mouse pos (TODO: use LabelAxisValue)
if (!ImHasFlag(plot.Flags, ImPlotFlags_NoMousePos) && gp.Hov_Plot) { if (!ImHasFlag(plot.Flags, ImPlotFlags_NoMousePos) && gp.Hov_Plot) {
char buffer[128] = {}; char buffer[128] = {};
ImBufferWriter writer(buffer, sizeof(buffer)); ImBufferWriter writer(buffer, sizeof(buffer));
@ -2497,7 +2514,7 @@ ImPlotLimits GetPlotLimits(int y_axis_in) {
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotLimits() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotLimits() needs to be called between BeginPlot() and EndPlot()!");
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis; const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
ImPlotState& plot = *gp.CurrentPlot; ImPlotPlot& plot = *gp.CurrentPlot;
ImPlotLimits limits; ImPlotLimits limits;
limits.X = plot.XAxis.Range; limits.X = plot.XAxis.Range;
limits.Y = plot.YAxis[y_axis].Range; limits.Y = plot.YAxis[y_axis].Range;
@ -2514,7 +2531,7 @@ ImPlotLimits GetPlotQuery(int y_axis_in) {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
IM_ASSERT_USER_ERROR(y_axis_in >= -1 && y_axis_in < IMPLOT_Y_AXES, "y_axis needs to between -1 and IMPLOT_Y_AXES"); IM_ASSERT_USER_ERROR(y_axis_in >= -1 && y_axis_in < IMPLOT_Y_AXES, "y_axis needs to between -1 and IMPLOT_Y_AXES");
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotQuery() needs to be called between BeginPlot() and EndPlot()!"); IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "GetPlotQuery() needs to be called between BeginPlot() and EndPlot()!");
ImPlotState& plot = *gp.CurrentPlot; ImPlotPlot& plot = *gp.CurrentPlot;
const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis; const int y_axis = y_axis_in >= 0 ? y_axis_in : gp.CurrentPlot->CurrentYAxis;
UpdateTransformCache(); UpdateTransformCache();
@ -2596,8 +2613,9 @@ bool DragLineX(const char* id, double* value, bool show_label, const ImVec4& col
gp.Hov_Plot = false; gp.Hov_Plot = false;
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW);
if (show_label) { if (show_label) {
double range_x = gp.XTicks.Size > 1 ? (gp.XTicks.Ticks[1].PlotPos - gp.XTicks.Ticks[0].PlotPos) : gp.CurrentPlot->XAxis.Range.Size(); char buff[32];
gp.Annotations.Append(ImVec2(x,yb),ImVec2(0,0),col32,CalcTextColor(color),true,"%s = %.*f", id, Precision(range_x), *value); LabelAxisValue(gp.CurrentPlot->XAxis, gp.XTicks, *value, buff, 32);
gp.Annotations.Append(ImVec2(x,yb),ImVec2(0,0),col32,CalcTextColor(color),true,"%s = %s", id, buff);
} }
} }
bool dragging = false; bool dragging = false;
@ -2641,8 +2659,9 @@ bool DragLineY(const char* id, double* value, bool show_label, const ImVec4& col
gp.Hov_Plot = false; gp.Hov_Plot = false;
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS); ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeNS);
if (show_label) { if (show_label) {
double range_y = gp.YTicks[yax].Size > 1 ? (gp.YTicks[yax].Ticks[1].PlotPos - gp.YTicks[yax].Ticks[0].PlotPos) : gp.CurrentPlot->YAxis[yax].Range.Size(); char buff[32];
gp.Annotations.Append(ImVec2(yax == 0 ? xl : xr,y), ImVec2(0,0), col32, CalcTextColor(color), true, "%s = %.*f", id, Precision(range_y), *value); LabelAxisValue(gp.CurrentPlot->YAxis[yax], gp.YTicks[yax], *value, buff, 32);
gp.Annotations.Append(ImVec2(yax == 0 ? xl : xr,y), ImVec2(0,0), col32, CalcTextColor(color), true, "%s = %s", id, buff);
} }
} }
bool dragging = false; bool dragging = false;
@ -2678,10 +2697,12 @@ bool DragPoint(const char* id, double* x, double* y, bool show_label, const ImVe
gp.Hov_Plot = false; gp.Hov_Plot = false;
ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll); ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeAll);
if (show_label) { if (show_label) {
double range_x = gp.XTicks.Size > 1 ? (gp.XTicks.Ticks[1].PlotPos - gp.XTicks.Ticks[0].PlotPos) : gp.CurrentPlot->XAxis.Range.Size();
double range_y = gp.YTicks[yax].Size > 1 ? (gp.YTicks[yax].Ticks[1].PlotPos - gp.YTicks[yax].Ticks[0].PlotPos) : gp.CurrentPlot->YAxis[yax].Range.Size();
ImVec2 label_pos = pos + ImVec2(16 * GImGui->Style.MouseCursorScale, 8 * GImGui->Style.MouseCursorScale); ImVec2 label_pos = pos + ImVec2(16 * GImGui->Style.MouseCursorScale, 8 * GImGui->Style.MouseCursorScale);
gp.Annotations.Append(label_pos, ImVec2(0.0001f,0.00001f), col32, CalcTextColor(color), true, "%s = %.*f,%.*f", id, Precision(range_x), *x, Precision(range_y), *y); char buff1[32];
char buff2[32];
LabelAxisValue(gp.CurrentPlot->XAxis, gp.XTicks, *x, buff1, 32);
LabelAxisValue(gp.CurrentPlot->YAxis[yax], gp.YTicks[yax], *y, buff2, 32);
gp.Annotations.Append(label_pos, ImVec2(0.0001f,0.00001f), col32, CalcTextColor(color), true, "%s = %s,%s", id, buff1, buff2);
} }
} }
bool dragging = false; bool dragging = false;

View File

@ -51,7 +51,7 @@ struct ImPlotAxis;
struct ImPlotAxisState; struct ImPlotAxisState;
struct ImPlotAxisColor; struct ImPlotAxisColor;
struct ImPlotItem; struct ImPlotItem;
struct ImPlotState; struct ImPlotPlot;
struct ImPlotNextPlotData; struct ImPlotNextPlotData;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -158,10 +158,17 @@ struct ImPlotPointArray {
// [SECTION] ImPlot Enums // [SECTION] ImPlot Enums
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
typedef int ImPlotDirection; // -> enum ImPlotDirection_
typedef int ImPlotScale; // -> enum ImPlotScale_ typedef int ImPlotScale; // -> enum ImPlotScale_
typedef int ImPlotTimeUnit; // -> enum ImPlotTimeUnit_ typedef int ImPlotTimeUnit; // -> enum ImPlotTimeUnit_
typedef int ImPlotTimeFmt; // -> enum ImPlotTimeFmt_ typedef int ImPlotTimeFmt; // -> enum ImPlotTimeFmt_
// Axis direction
enum ImPlotDirection_ {
ImPlotDirection_Horizontal, // left/right
ImPlotDirection_Vertical // up/down
};
// XY axes scaling combinations // XY axes scaling combinations
enum ImPlotScale_ { enum ImPlotScale_ {
ImPlotScale_LinLin, // linear x, linear y ImPlotScale_LinLin, // linear x, linear y
@ -370,6 +377,7 @@ struct ImPlotAxis
ImPlotAxisFlags Flags; ImPlotAxisFlags Flags;
ImPlotAxisFlags PreviousFlags; ImPlotAxisFlags PreviousFlags;
ImPlotRange Range; ImPlotRange Range;
ImPlotDirection Direction;
bool Dragging; bool Dragging;
bool HoveredExt; bool HoveredExt;
bool HoveredTot; bool HoveredTot;
@ -502,7 +510,7 @@ struct ImPlotItem
}; };
// Holds Plot state information that must persist after EndPlot // Holds Plot state information that must persist after EndPlot
struct ImPlotState struct ImPlotPlot
{ {
ImPlotFlags Flags; ImPlotFlags Flags;
ImPlotFlags PreviousFlags; ImPlotFlags PreviousFlags;
@ -520,11 +528,14 @@ struct ImPlotState
int ColormapIdx; int ColormapIdx;
int CurrentYAxis; int CurrentYAxis;
ImPlotState() { ImPlotPlot() {
Flags = PreviousFlags = ImPlotFlags_None; Flags = PreviousFlags = ImPlotFlags_None;
SelectStart = QueryStart = ImVec2(0,0); XAxis.Direction = ImPlotDirection_Horizontal;
Selecting = Querying = Queried = DraggingQuery = false; for (int i = 0; i < IMPLOT_Y_AXES; ++i)
ColormapIdx = CurrentYAxis = 0; YAxis[i].Direction = ImPlotDirection_Vertical;
SelectStart = QueryStart = ImVec2(0,0);
Selecting = Querying = Queried = DraggingQuery = false;
ColormapIdx = CurrentYAxis = 0;
} }
}; };
@ -591,8 +602,8 @@ struct ImPlotNextItemData {
// Holds state information that must persist between calls to BeginPlot()/EndPlot() // Holds state information that must persist between calls to BeginPlot()/EndPlot()
struct ImPlotContext { struct ImPlotContext {
// Plot States // Plot States
ImPool<ImPlotState> Plots; ImPool<ImPlotPlot> Plots;
ImPlotState* CurrentPlot; ImPlotPlot* CurrentPlot;
ImPlotItem* CurrentItem; ImPlotItem* CurrentItem;
ImPlotItem* PreviousItem; ImPlotItem* PreviousItem;
@ -699,14 +710,14 @@ IMPLOT_API void Reset(ImPlotContext* ctx);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Gets a plot from the current ImPlotContext // Gets a plot from the current ImPlotContext
IMPLOT_API ImPlotState* GetPlot(const char* title); IMPLOT_API ImPlotPlot* GetPlot(const char* title);
// Gets the current plot from the current ImPlotContext // Gets the current plot from the current ImPlotContext
IMPLOT_API ImPlotState* GetCurrentPlot(); IMPLOT_API ImPlotPlot* GetCurrentPlot();
// Busts the cache for every plot in the current context // Busts the cache for every plot in the current context
IMPLOT_API void BustPlotCache(); IMPLOT_API void BustPlotCache();
// Shows a plot's context menu. // Shows a plot's context menu.
IMPLOT_API void ShowPlotContextMenu(ImPlotState& plot); IMPLOT_API void ShowPlotContextMenu(ImPlotPlot& plot);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Item Utils // [SECTION] Item Utils
@ -790,6 +801,9 @@ IMPLOT_API void AddTicksTime(const ImPlotRange& range, int nMajor, bool hour24,
// Populates a list of ImPlotTicks with custom spaced and labeled ticks // Populates a list of ImPlotTicks with custom spaced and labeled ticks
IMPLOT_API void AddTicksCustom(const double* values, const char* const labels[], int n, ImPlotTickCollection& ticks); IMPLOT_API void AddTicksCustom(const double* values, const char* const labels[], int n, ImPlotTickCollection& ticks);
// Create a a string label for a an axis value
IMPLOT_API int LabelAxisValue(const ImPlotAxis& axis, const ImPlotTickCollection& ticks, double value, char* buff, int size);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// [SECTION] Styling Utils // [SECTION] Styling Utils
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -84,7 +84,7 @@ ImPlotItem* GetItem(const char* label_id) {
} }
ImPlotItem* GetItem(const char* plot_title, const char* item_label_id) { ImPlotItem* GetItem(const char* plot_title, const char* item_label_id) {
ImPlotState* plot = GetPlot(plot_title); ImPlotPlot* plot = GetPlot(plot_title);
if (plot) { if (plot) {
ImGuiID id = ImGui::GetID(item_label_id); ImGuiID id = ImGui::GetID(item_label_id);
return plot->Items.GetByKey(id); return plot->Items.GetByKey(id);
@ -142,7 +142,7 @@ void HideNextItem(bool hidden, ImGuiCond cond) {
void BustItemCache() { void BustItemCache() {
ImPlotContext& gp = *GImPlot; ImPlotContext& gp = *GImPlot;
for (int p = 0; p < gp.Plots.GetSize(); ++p) { for (int p = 0; p < gp.Plots.GetSize(); ++p) {
ImPlotState& plot = *gp.Plots.GetByIndex(p); ImPlotPlot& plot = *gp.Plots.GetByIndex(p);
plot.ColormapIdx = 0; plot.ColormapIdx = 0;
plot.Items.Clear(); plot.Items.Clear();
} }