mirror of
https://github.com/gwm17/implot.git
synced 2024-11-23 02:38:53 -05:00
Adds SetNextPlotFormatX/Y for custom tick label formatting (#198)
* add SetNextPlotFormat * work on pruning * finish up fmt
This commit is contained in:
parent
4b0f9c9495
commit
ed1baf471a
166
implot.cpp
166
implot.cpp
|
@ -689,45 +689,55 @@ void ShowLegendEntries(ImPlotPlot& plot, const ImRect& legend_bb, bool interacta
|
||||||
// Tick Utils
|
// Tick Utils
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
void LabelTickDefault(ImPlotTick& tick, ImGuiTextBuffer& buffer) {
|
void AddTicksDefault(const ImPlotRange& range, float pix, ImPlotOrientation orn, ImPlotTickCollection& ticks, const char* fmt) {
|
||||||
char temp[32];
|
const int idx0 = ticks.Size;
|
||||||
if (tick.ShowLabel) {
|
const int nMinor = 10;
|
||||||
tick.TextOffset = buffer.size();
|
const int nMajor = ImMax(2, (int)IM_ROUND(pix / (orn == ImPlotOrientation_Horizontal ? 400.0f : 300.0f)));
|
||||||
snprintf(temp, 32, "%.10g", tick.PlotPos);
|
|
||||||
buffer.append(temp, temp + strlen(temp) + 1);
|
|
||||||
tick.LabelSize = ImGui::CalcTextSize(buffer.Buf.Data + tick.TextOffset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LabelTickScientific(ImPlotTick& tick, ImGuiTextBuffer& buffer) {
|
|
||||||
char temp[32];
|
|
||||||
if (tick.ShowLabel) {
|
|
||||||
tick.TextOffset = buffer.size();
|
|
||||||
snprintf(temp, 32, "%.0E", tick.PlotPos);
|
|
||||||
buffer.append(temp, temp + strlen(temp) + 1);
|
|
||||||
tick.LabelSize = ImGui::CalcTextSize(buffer.Buf.Data + tick.TextOffset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddTicksDefault(const ImPlotRange& range, int nMajor, int nMinor, ImPlotTickCollection& ticks) {
|
|
||||||
const double nice_range = NiceNum(range.Size() * 0.99, false);
|
const double nice_range = NiceNum(range.Size() * 0.99, false);
|
||||||
const double interval = NiceNum(nice_range / (nMajor - 1), true);
|
const double interval = NiceNum(nice_range / (nMajor - 1), true);
|
||||||
const double graphmin = floor(range.Min / interval) * interval;
|
const double graphmin = floor(range.Min / interval) * interval;
|
||||||
const double graphmax = ceil(range.Max / interval) * interval;
|
const double graphmax = ceil(range.Max / interval) * interval;
|
||||||
|
bool first_major_set = false;
|
||||||
|
int first_major_idx = 0;
|
||||||
|
|
||||||
|
char dummy[32];
|
||||||
|
sprintf(dummy,fmt,-ImAbs(interval / nMinor));
|
||||||
|
ImVec2 dummy_size = ImGui::CalcTextSize(dummy);
|
||||||
|
ImVec2 total_size(0,0);
|
||||||
|
|
||||||
for (double major = graphmin; major < graphmax + 0.5 * interval; major += interval) {
|
for (double major = graphmin; major < graphmax + 0.5 * interval; major += interval) {
|
||||||
if (range.Contains(major))
|
// is this zero? combat zero formatting issues
|
||||||
ticks.Append(major, true, true, LabelTickDefault);
|
if (major-interval < 0 && major+interval > 0)
|
||||||
|
major = 0;
|
||||||
|
if (range.Contains(major)) {
|
||||||
|
if (!first_major_set) {
|
||||||
|
first_major_idx = ticks.Size;
|
||||||
|
first_major_set = true;
|
||||||
|
}
|
||||||
|
ticks.Append(major, true, true, fmt);
|
||||||
|
total_size += dummy_size;
|
||||||
|
}
|
||||||
for (int i = 1; i < nMinor; ++i) {
|
for (int i = 1; i < nMinor; ++i) {
|
||||||
double minor = major + i * interval / nMinor;
|
double minor = major + i * interval / nMinor;
|
||||||
if (range.Contains(minor))
|
if (range.Contains(minor)) {
|
||||||
ticks.Append(minor, false, true, LabelTickDefault);
|
ticks.Append(minor, false, true, fmt);
|
||||||
|
total_size += dummy_size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// prune if necessary
|
||||||
|
if ((orn == ImPlotOrientation_Horizontal && total_size.x > pix) || (orn == ImPlotOrientation_Vertical && total_size.y > pix)) {
|
||||||
|
for (int i = first_major_idx-1; i >= idx0; i -= 2)
|
||||||
|
ticks.Ticks[i].ShowLabel = false;
|
||||||
|
for (int i = first_major_idx+1; i < ticks.Size; i += 2)
|
||||||
|
ticks.Ticks[i].ShowLabel = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddTicksLogarithmic(const ImPlotRange& range, int nMajor, ImPlotTickCollection& ticks) {
|
void AddTicksLogarithmic(const ImPlotRange& range, float pix, ImPlotOrientation orn, ImPlotTickCollection& ticks, const char* fmt) {
|
||||||
if (range.Min <= 0 || range.Max <= 0)
|
if (range.Min <= 0 || range.Max <= 0)
|
||||||
return;
|
return;
|
||||||
|
const int nMajor = orn == ImPlotOrientation_Horizontal ? ImMax(2, (int)IM_ROUND(pix * 0.01f)) : ImMax(2, (int)IM_ROUND(pix * 0.02f));
|
||||||
double log_min = ImLog10(range.Min);
|
double log_min = ImLog10(range.Min);
|
||||||
double log_max = ImLog10(range.Max);
|
double log_max = ImLog10(range.Max);
|
||||||
int exp_step = ImMax(1,(int)(log_max - log_min) / nMajor);
|
int exp_step = ImMax(1,(int)(log_max - log_min) / nMajor);
|
||||||
|
@ -742,7 +752,7 @@ void AddTicksLogarithmic(const ImPlotRange& range, int nMajor, ImPlotTickCollect
|
||||||
double major2 = ImPow(10, (double)(e + 1));
|
double major2 = ImPow(10, (double)(e + 1));
|
||||||
double interval = (major2 - major1) / 9;
|
double interval = (major2 - major1) / 9;
|
||||||
if (major1 >= (range.Min - DBL_EPSILON) && major1 <= (range.Max + DBL_EPSILON))
|
if (major1 >= (range.Min - DBL_EPSILON) && major1 <= (range.Max + DBL_EPSILON))
|
||||||
ticks.Append(major1, true, true, LabelTickScientific);
|
ticks.Append(major1, true, true, fmt);
|
||||||
for (int j = 0; j < exp_step; ++j) {
|
for (int j = 0; j < exp_step; ++j) {
|
||||||
major1 = ImPow(10, (double)(e+j));
|
major1 = ImPow(10, (double)(e+j));
|
||||||
major2 = ImPow(10, (double)(e+j+1));
|
major2 = ImPow(10, (double)(e+j+1));
|
||||||
|
@ -750,25 +760,25 @@ void AddTicksLogarithmic(const ImPlotRange& range, int nMajor, ImPlotTickCollect
|
||||||
for (int i = 1; i < (9 + (int)(j < (exp_step - 1))); ++i) {
|
for (int i = 1; i < (9 + (int)(j < (exp_step - 1))); ++i) {
|
||||||
double minor = major1 + i * interval;
|
double minor = major1 + i * interval;
|
||||||
if (minor >= (range.Min - DBL_EPSILON) && minor <= (range.Max + DBL_EPSILON))
|
if (minor >= (range.Min - DBL_EPSILON) && minor <= (range.Max + DBL_EPSILON))
|
||||||
ticks.Append(minor, false, false, LabelTickScientific);
|
ticks.Append(minor, false, false, fmt);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddTicksCustom(const double* values, const char* const labels[], int n, ImPlotTickCollection& ticks) {
|
void AddTicksCustom(const double* values, const char* const labels[], int n, ImPlotTickCollection& ticks, const char* fmt) {
|
||||||
for (int i = 0; i < n; ++i) {
|
for (int i = 0; i < n; ++i) {
|
||||||
ImPlotTick tick(values[i], false, true);
|
|
||||||
if (labels != NULL) {
|
if (labels != NULL) {
|
||||||
|
ImPlotTick tick(values[i], false, true);
|
||||||
tick.TextOffset = ticks.TextBuffer.size();
|
tick.TextOffset = ticks.TextBuffer.size();
|
||||||
ticks.TextBuffer.append(labels[i], labels[i] + strlen(labels[i]) + 1);
|
ticks.TextBuffer.append(labels[i], labels[i] + strlen(labels[i]) + 1);
|
||||||
tick.LabelSize = ImGui::CalcTextSize(labels[i]);
|
tick.LabelSize = ImGui::CalcTextSize(labels[i]);
|
||||||
|
ticks.Append(tick);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LabelTickDefault(tick, ticks.TextBuffer);
|
ticks.Append(values[i], false, true, fmt);
|
||||||
}
|
}
|
||||||
ticks.Append(tick);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1256,12 +1266,18 @@ void AddTicksTime(const ImPlotRange& range, float plot_width, ImPlotTickCollecti
|
||||||
// Axis Utils
|
// Axis Utils
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static inline int AxisPrecision(const ImPlotAxis& axis, const ImPlotTickCollection& ticks) {
|
||||||
|
const double range = ticks.Size > 1 ? (ticks.Ticks[1].PlotPos - ticks.Ticks[0].PlotPos) : axis.Range.Size();
|
||||||
|
return Precision(range);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline double RoundAxisValue(const ImPlotAxis& axis, const ImPlotTickCollection& ticks, double value) {
|
||||||
|
return RoundTo(value, AxisPrecision(axis,ticks));
|
||||||
|
}
|
||||||
|
|
||||||
int LabelAxisValue(const ImPlotAxis& axis, const ImPlotTickCollection& ticks, double value, char* buff, int size) {
|
int LabelAxisValue(const ImPlotAxis& axis, const ImPlotTickCollection& ticks, double value, char* buff, int size) {
|
||||||
ImPlotContext& gp = *GImPlot;
|
ImPlotContext& gp = *GImPlot;
|
||||||
if (ImHasFlag(axis.Flags, ImPlotAxisFlags_LogScale)) {
|
if (ImHasFlag(axis.Flags, ImPlotAxisFlags_Time)) {
|
||||||
return snprintf(buff, size, "%.3E", value);
|
|
||||||
}
|
|
||||||
else if (ImHasFlag(axis.Flags, ImPlotAxisFlags_Time)) {
|
|
||||||
ImPlotTimeUnit unit = (axis.Orientation == ImPlotOrientation_Horizontal)
|
ImPlotTimeUnit unit = (axis.Orientation == ImPlotOrientation_Horizontal)
|
||||||
? GetUnitForRange(axis.Range.Size() / (gp.CurrentPlot->PlotRect.GetWidth() / 100))
|
? GetUnitForRange(axis.Range.Size() / (gp.CurrentPlot->PlotRect.GetWidth() / 100))
|
||||||
: GetUnitForRange(axis.Range.Size() / (gp.CurrentPlot->PlotRect.GetHeight() / 100));
|
: GetUnitForRange(axis.Range.Size() / (gp.CurrentPlot->PlotRect.GetHeight() / 100));
|
||||||
|
@ -1521,9 +1537,9 @@ bool BeginPlot(const char* title, const char* x_label, const char* y1_label, con
|
||||||
for (int i = 0; i < IMPLOT_Y_AXES; i++) {
|
for (int i = 0; i < IMPLOT_Y_AXES; i++) {
|
||||||
if (gp.RenderY[i] && gp.NextPlotData.ShowDefaultTicksY[i]) {
|
if (gp.RenderY[i] && gp.NextPlotData.ShowDefaultTicksY[i]) {
|
||||||
if (ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LogScale))
|
if (ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LogScale))
|
||||||
AddTicksLogarithmic(plot.YAxis[i].Range, ImMax(2, (int)IM_ROUND(plot_height * 0.02f)) ,gp.YTicks[i]);
|
AddTicksLogarithmic(plot.YAxis[i].Range, plot_height, ImPlotOrientation_Vertical, gp.YTicks[i], GetFormatY(i));
|
||||||
else
|
else
|
||||||
AddTicksDefault(plot.YAxis[i].Range, ImMax(2, (int)IM_ROUND(0.0025 * plot_height)), IMPLOT_SUB_DIV, gp.YTicks[i]);
|
AddTicksDefault(plot.YAxis[i].Range, plot_height, ImPlotOrientation_Vertical, gp.YTicks[i], GetFormatY(i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1547,9 +1563,9 @@ bool BeginPlot(const char* title, const char* x_label, const char* y1_label, con
|
||||||
if (plot.XAxis.IsTime())
|
if (plot.XAxis.IsTime())
|
||||||
AddTicksTime(plot.XAxis.Range, plot_width, gp.XTicks);
|
AddTicksTime(plot.XAxis.Range, plot_width, gp.XTicks);
|
||||||
else if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale))
|
else if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale))
|
||||||
AddTicksLogarithmic(plot.XAxis.Range, (int)IM_ROUND(plot_width * 0.01f), gp.XTicks);
|
AddTicksLogarithmic(plot.XAxis.Range, plot_width, ImPlotOrientation_Horizontal, gp.XTicks, GetFormatX());
|
||||||
else
|
else
|
||||||
AddTicksDefault(plot.XAxis.Range, ImMax(2, (int)IM_ROUND(0.0025 * plot_width)), IMPLOT_SUB_DIV, gp.XTicks);
|
AddTicksDefault(plot.XAxis.Range, plot_width, ImPlotOrientation_Horizontal, gp.XTicks, GetFormatX());
|
||||||
}
|
}
|
||||||
|
|
||||||
// (5) calc plot bb
|
// (5) calc plot bb
|
||||||
|
@ -2242,10 +2258,8 @@ void EndPlot() {
|
||||||
|
|
||||||
// AXIS STATES ------------------------------------------------------------
|
// AXIS STATES ------------------------------------------------------------
|
||||||
|
|
||||||
const bool any_y_locked = plot.AnyYInputLocked();
|
|
||||||
const bool any_y_dragging = plot.YAxis[0].Dragging || plot.YAxis[1].Dragging || plot.YAxis[2].Dragging;
|
const bool any_y_dragging = plot.YAxis[0].Dragging || plot.YAxis[1].Dragging || plot.YAxis[2].Dragging;
|
||||||
|
|
||||||
|
|
||||||
// FINAL RENDER -----------------------------------------------------------
|
// FINAL RENDER -----------------------------------------------------------
|
||||||
|
|
||||||
// render ticks
|
// render ticks
|
||||||
|
@ -2284,10 +2298,7 @@ void EndPlot() {
|
||||||
|
|
||||||
if (axis_count >= 3) {
|
if (axis_count >= 3) {
|
||||||
// Draw a bar next to the ticks to act as a visual separator.
|
// Draw a bar next to the ticks to act as a visual separator.
|
||||||
DrawList.AddLine(
|
DrawList.AddLine(ImVec2(x_start, plot.PlotRect.Min.y), ImVec2(x_start, plot.PlotRect.Max.y), GetStyleColorU32(ImPlotCol_YAxisGrid3), 1);
|
||||||
ImVec2(x_start, plot.PlotRect.Min.y),
|
|
||||||
ImVec2(x_start, plot.PlotRect.Max.y),
|
|
||||||
GetStyleColorU32(ImPlotCol_YAxisGrid3), 1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::PopClipRect();
|
ImGui::PopClipRect();
|
||||||
|
@ -2358,52 +2369,34 @@ void EndPlot() {
|
||||||
DrawList.AddLine(v3, v4, col);
|
DrawList.AddLine(v3, v4, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
// render mouse pos (TODO: use LabelAxisValue)
|
// render mouse pos
|
||||||
if (!ImHasFlag(plot.Flags, ImPlotFlags_NoMousePos) && plot.PlotHovered) {
|
if (!ImHasFlag(plot.Flags, ImPlotFlags_NoMousePos) && plot.PlotHovered) {
|
||||||
char buffer[128] = {};
|
char buffer[128] = {};
|
||||||
ImBufferWriter writer(buffer, sizeof(buffer));
|
ImBufferWriter writer(buffer, sizeof(buffer));
|
||||||
|
|
||||||
// x
|
// x
|
||||||
if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_LogScale)) {
|
if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_Time)) {
|
||||||
writer.Write("%.3E", gp.MousePos[0].x);
|
|
||||||
}
|
|
||||||
else if (ImHasFlag(plot.XAxis.Flags, ImPlotAxisFlags_Time)) {
|
|
||||||
ImPlotTimeUnit unit = GetUnitForRange(plot.XAxis.Range.Size() / (plot.PlotRect.GetWidth() / 100));
|
ImPlotTimeUnit unit = GetUnitForRange(plot.XAxis.Range.Size() / (plot.PlotRect.GetWidth() / 100));
|
||||||
const int written = FormatDateTime(ImPlotTime::FromDouble(gp.MousePos[0].x), &writer.Buffer[writer.Pos], writer.Size - writer.Pos - 1, GetDateTimeFmt(TimeFormatMouseCursor, unit));
|
const int written = FormatDateTime(ImPlotTime::FromDouble(gp.MousePos[0].x), &writer.Buffer[writer.Pos], writer.Size - writer.Pos - 1, GetDateTimeFmt(TimeFormatMouseCursor, unit));
|
||||||
if (written > 0)
|
if (written > 0)
|
||||||
writer.Pos += ImMin(written, writer.Size - writer.Pos - 1);
|
writer.Pos += ImMin(written, writer.Size - writer.Pos - 1);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
double range_x = gp.XTicks.Size > 1 ? (gp.XTicks.Ticks[1].PlotPos - gp.XTicks.Ticks[0].PlotPos) : plot.XAxis.Range.Size();
|
writer.Write(GetFormatX(), RoundAxisValue(plot.XAxis, gp.XTicks, gp.MousePos[0].x));
|
||||||
writer.Write("%.*f", Precision(range_x), gp.MousePos[0].x);
|
|
||||||
}
|
}
|
||||||
// y1
|
// y1
|
||||||
if (ImHasFlag(plot.YAxis[0].Flags, ImPlotAxisFlags_LogScale)) {
|
writer.Write(", ");
|
||||||
writer.Write(",%.3E", gp.MousePos[0].y);
|
writer.Write(GetFormatY(0), RoundAxisValue(plot.YAxis[0], gp.YTicks[0], gp.MousePos[0].y));
|
||||||
}
|
|
||||||
else {
|
|
||||||
double range_y = gp.YTicks[0].Size > 1 ? (gp.YTicks[0].Ticks[1].PlotPos - gp.YTicks[0].Ticks[0].PlotPos) : plot.YAxis[0].Range.Size();
|
|
||||||
writer.Write(",%.*f", Precision(range_y), gp.MousePos[0].y);
|
|
||||||
}
|
|
||||||
// y2
|
// y2
|
||||||
if (ImHasFlag(plot.Flags, ImPlotFlags_YAxis2)) {
|
if (ImHasFlag(plot.Flags, ImPlotFlags_YAxis2)) {
|
||||||
if (ImHasFlag(plot.YAxis[1].Flags, ImPlotAxisFlags_LogScale)) {
|
writer.Write(", (");
|
||||||
writer.Write(",(%.3E)", gp.MousePos[1].y);
|
writer.Write(GetFormatY(1), RoundAxisValue(plot.YAxis[1], gp.YTicks[1], gp.MousePos[1].y));
|
||||||
}
|
writer.Write(")");
|
||||||
else {
|
|
||||||
double range_y = gp.YTicks[1].Size > 1 ? (gp.YTicks[1].Ticks[1].PlotPos - gp.YTicks[1].Ticks[0].PlotPos) : plot.YAxis[1].Range.Size();
|
|
||||||
writer.Write(",(%.*f)", Precision(range_y), gp.MousePos[1].y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// y3
|
// y3
|
||||||
if (ImHasFlag(plot.Flags, ImPlotFlags_YAxis3)) {
|
if (ImHasFlag(plot.Flags, ImPlotFlags_YAxis3)) {
|
||||||
if (ImHasFlag(plot.YAxis[2].Flags, ImPlotAxisFlags_LogScale)) {
|
writer.Write(", (");
|
||||||
writer.Write(",(%.3E)", gp.MousePos[2].y);
|
writer.Write(GetFormatY(2), RoundAxisValue(plot.YAxis[2], gp.YTicks[2], gp.MousePos[2].y));
|
||||||
}
|
writer.Write(")");
|
||||||
else {
|
|
||||||
double range_y = gp.YTicks[2].Size > 1 ? (gp.YTicks[2].Ticks[1].PlotPos - gp.YTicks[2].Ticks[0].PlotPos) : plot.YAxis[2].Range.Size();
|
|
||||||
writer.Write(",(%.*f)", Precision(range_y), gp.MousePos[2].y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const ImVec2 size = ImGui::CalcTextSize(buffer);
|
const ImVec2 size = ImGui::CalcTextSize(buffer);
|
||||||
const ImVec2 pos = GetLocationPos(plot.PlotRect, size, plot.MousePosLocation, gp.Style.MousePosPadding);
|
const ImVec2 pos = GetLocationPos(plot.PlotRect, size, plot.MousePosLocation, gp.Style.MousePosPadding);
|
||||||
|
@ -2618,7 +2611,7 @@ void SetNextPlotTicksX(const double* values, int n_ticks, const char* const labe
|
||||||
ImPlotContext& gp = *GImPlot;
|
ImPlotContext& gp = *GImPlot;
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot == NULL, "SetNextPlotTicksX() needs to be called before BeginPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot == NULL, "SetNextPlotTicksX() needs to be called before BeginPlot()!");
|
||||||
gp.NextPlotData.ShowDefaultTicksX = show_default;
|
gp.NextPlotData.ShowDefaultTicksX = show_default;
|
||||||
AddTicksCustom(values, labels, n_ticks, gp.XTicks);
|
AddTicksCustom(values, labels, n_ticks, gp.XTicks, GetFormatX());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetNextPlotTicksX(double x_min, double x_max, int n_ticks, const char* const labels[], bool show_default) {
|
void SetNextPlotTicksX(double x_min, double x_max, int n_ticks, const char* const labels[], bool show_default) {
|
||||||
|
@ -2633,7 +2626,7 @@ void SetNextPlotTicksY(const double* values, int n_ticks, const char* const labe
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot == NULL, "SetNextPlotTicksY() needs to be called before BeginPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot == NULL, "SetNextPlotTicksY() needs to be called before BeginPlot()!");
|
||||||
IM_ASSERT_USER_ERROR(y_axis >= 0 && y_axis < IMPLOT_Y_AXES, "y_axis needs to be between 0 and IMPLOT_Y_AXES");
|
IM_ASSERT_USER_ERROR(y_axis >= 0 && y_axis < IMPLOT_Y_AXES, "y_axis needs to be between 0 and IMPLOT_Y_AXES");
|
||||||
gp.NextPlotData.ShowDefaultTicksY[y_axis] = show_default;
|
gp.NextPlotData.ShowDefaultTicksY[y_axis] = show_default;
|
||||||
AddTicksCustom(values, labels, n_ticks, gp.YTicks[y_axis]);
|
AddTicksCustom(values, labels, n_ticks, gp.YTicks[y_axis], GetFormatY(y_axis));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetNextPlotTicksY(double y_min, double y_max, int n_ticks, const char* const labels[], bool show_default, ImPlotYAxis y_axis) {
|
void SetNextPlotTicksY(double y_min, double y_max, int n_ticks, const char* const labels[], bool show_default, ImPlotYAxis y_axis) {
|
||||||
|
@ -2643,6 +2636,21 @@ void SetNextPlotTicksY(double y_min, double y_max, int n_ticks, const char* cons
|
||||||
SetNextPlotTicksY(&buffer[0], n_ticks, labels, show_default,y_axis);
|
SetNextPlotTicksY(&buffer[0], n_ticks, labels, show_default,y_axis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetNextPlotFormatX(const char* fmt){
|
||||||
|
ImPlotContext& gp = *GImPlot;
|
||||||
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot == NULL, "SetNextPlotFormatX() needs to be called before BeginPlot()!");
|
||||||
|
gp.NextPlotData.HasFmtX = true;
|
||||||
|
ImStrncpy(gp.NextPlotData.FmtX, fmt, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetNextPlotFormatY(const char* fmt, ImPlotYAxis y_axis) {
|
||||||
|
ImPlotContext& gp = *GImPlot;
|
||||||
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot == NULL, "SetNextPlotFormatY() needs to be called before BeginPlot()!");
|
||||||
|
IM_ASSERT_USER_ERROR(y_axis >= 0 && y_axis < IMPLOT_Y_AXES, "y_axis needs to be between 0 and IMPLOT_Y_AXES");
|
||||||
|
gp.NextPlotData.HasFmtY[y_axis] = true;
|
||||||
|
ImStrncpy(gp.NextPlotData.FmtY[y_axis], fmt, 16);
|
||||||
|
}
|
||||||
|
|
||||||
void SetPlotYAxis(ImPlotYAxis y_axis) {
|
void SetPlotYAxis(ImPlotYAxis y_axis) {
|
||||||
ImPlotContext& gp = *GImPlot;
|
ImPlotContext& gp = *GImPlot;
|
||||||
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "SetPlotYAxis() needs to be called between BeginPlot() and EndPlot()!");
|
IM_ASSERT_USER_ERROR(gp.CurrentPlot != NULL, "SetPlotYAxis() needs to be called between BeginPlot() and EndPlot()!");
|
||||||
|
@ -3453,7 +3461,7 @@ void RenderColorBar(const ImU32* colors, int size, ImDrawList& DrawList, const I
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColormapScale(const char* label, double scale_min, double scale_max, const ImVec2& size, ImPlotColormap cmap) {
|
void ColormapScale(const char* label, double scale_min, double scale_max, const ImVec2& size, ImPlotColormap cmap, const char* fmt) {
|
||||||
ImGuiContext &G = *GImGui;
|
ImGuiContext &G = *GImGui;
|
||||||
ImGuiWindow * Window = G.CurrentWindow;
|
ImGuiWindow * Window = G.CurrentWindow;
|
||||||
if (Window->SkipItems)
|
if (Window->SkipItems)
|
||||||
|
@ -3473,7 +3481,7 @@ void ColormapScale(const char* label, double scale_min, double scale_max, const
|
||||||
|
|
||||||
ImPlotRange range(scale_min,scale_max);
|
ImPlotRange range(scale_min,scale_max);
|
||||||
gp.CTicks.Reset();
|
gp.CTicks.Reset();
|
||||||
AddTicksDefault(range, ImMax(2, (int)IM_ROUND(0.0025 * frame_size.y)), IMPLOT_SUB_DIV, gp.CTicks);
|
AddTicksDefault(range, frame_size.y, ImPlotOrientation_Vertical, gp.CTicks, fmt);
|
||||||
|
|
||||||
const float txt_off = gp.Style.LabelPadding.x;
|
const float txt_off = gp.Style.LabelPadding.x;
|
||||||
const float pad_right = txt_off + gp.CTicks.MaxWidth + (label_size.x > 0 ? txt_off + label_size.y : 0);
|
const float pad_right = txt_off + gp.CTicks.MaxWidth + (label_size.x > 0 ? txt_off + label_size.y : 0);
|
||||||
|
|
20
implot.h
20
implot.h
|
@ -513,19 +513,23 @@ IMPLOT_API void SetNextPlotLimits(double xmin, double xmax, double ymin, double
|
||||||
// Set the X axis range limits of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the X axis limits will be locked.
|
// Set the X axis range limits of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the X axis limits will be locked.
|
||||||
IMPLOT_API void SetNextPlotLimitsX(double xmin, double xmax, ImGuiCond cond = ImGuiCond_Once);
|
IMPLOT_API void SetNextPlotLimitsX(double xmin, double xmax, ImGuiCond cond = ImGuiCond_Once);
|
||||||
// Set the Y axis range limits of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the Y axis limits will be locked.
|
// Set the Y axis range limits of the next plot. Call right before BeginPlot(). If ImGuiCond_Always is used, the Y axis limits will be locked.
|
||||||
IMPLOT_API void SetNextPlotLimitsY(double ymin, double ymax, ImGuiCond cond = ImGuiCond_Once, ImPlotYAxis y_axis = 0);
|
IMPLOT_API void SetNextPlotLimitsY(double ymin, double ymax, ImGuiCond cond = ImGuiCond_Once, ImPlotYAxis y_axis = ImPlotYAxis_1);
|
||||||
// Links the next plot limits to external values. Set to NULL for no linkage. The pointer data must remain valid until the matching call to EndPlot.
|
// Links the next plot limits to external values. Set to NULL for no linkage. The pointer data must remain valid until the matching call to EndPlot.
|
||||||
IMPLOT_API void LinkNextPlotLimits(double* xmin, double* xmax, double* ymin, double* ymax, double* ymin2 = NULL, double* ymax2 = NULL, double* ymin3 = NULL, double* ymax3 = NULL);
|
IMPLOT_API void LinkNextPlotLimits(double* xmin, double* xmax, double* ymin, double* ymax, double* ymin2 = NULL, double* ymax2 = NULL, double* ymin3 = NULL, double* ymax3 = NULL);
|
||||||
// Fits the next plot axes to all plotted data if they are unlocked (equivalent to double-clicks).
|
// Fits the next plot axes to all plotted data if they are unlocked (equivalent to double-clicks).
|
||||||
IMPLOT_API void FitNextPlotAxes(bool x = true, bool y = true, bool y2 = true, bool y3 = true);
|
IMPLOT_API void FitNextPlotAxes(bool x = true, bool y = true, bool y2 = true, bool y3 = true);
|
||||||
|
|
||||||
// Set the X axis ticks and optionally the labels for the next plot. To keep the default ticks, set #show_default=true.
|
// Set the X axis ticks and optionally the labels for the next plot. To keep the default ticks, set #keep_default=true.
|
||||||
IMPLOT_API void SetNextPlotTicksX(const double* values, int n_ticks, const char* const labels[] = NULL, bool show_default = false);
|
IMPLOT_API void SetNextPlotTicksX(const double* values, int n_ticks, const char* const labels[] = NULL, bool keep_default = false);
|
||||||
IMPLOT_API void SetNextPlotTicksX(double x_min, double x_max, int n_ticks, const char* const labels[] = NULL, bool show_default = false);
|
IMPLOT_API void SetNextPlotTicksX(double x_min, double x_max, int n_ticks, const char* const labels[] = NULL, bool keep_default = false);
|
||||||
|
// Set the Y axis ticks and optionally the labels for the next plot. To keep the default ticks, set #keep_default=true.
|
||||||
|
IMPLOT_API void SetNextPlotTicksY(const double* values, int n_ticks, const char* const labels[] = NULL, bool keep_default = false, ImPlotYAxis y_axis = ImPlotYAxis_1);
|
||||||
|
IMPLOT_API void SetNextPlotTicksY(double y_min, double y_max, int n_ticks, const char* const labels[] = NULL, bool keep_default = false, ImPlotYAxis y_axis = ImPlotYAxis_1);
|
||||||
|
|
||||||
// Set the Y axis ticks and optionally the labels for the next plot. To keep the default ticks, set #show_default=true.
|
// Set the format for numeric X axis labels (default="%g"). Formated values will be doubles (i.e. don't supply %d, %i, etc.). Not applicable if ImPlotAxisFlags_Time enabled.
|
||||||
IMPLOT_API void SetNextPlotTicksY(const double* values, int n_ticks, const char* const labels[] = NULL, bool show_default = false, ImPlotYAxis y_axis = 0);
|
IMPLOT_API void SetNextPlotFormatX(const char* fmt);
|
||||||
IMPLOT_API void SetNextPlotTicksY(double y_min, double y_max, int n_ticks, const char* const labels[] = NULL, bool show_default = false, ImPlotYAxis y_axis = 0);
|
// Set the format for numeric Y axis labels (default="%g"). Formated values will be doubles (i.e. don't supply %d, %i, etc.).
|
||||||
|
IMPLOT_API void SetNextPlotFormatY(const char* fmt, ImPlotYAxis y_axis=ImPlotYAxis_1);
|
||||||
|
|
||||||
// The following functions MUST be called BETWEEN Begin/EndPlot!
|
// The following functions MUST be called BETWEEN Begin/EndPlot!
|
||||||
|
|
||||||
|
@ -778,7 +782,7 @@ IMPLOT_API ImVec4 GetColormapColor(int idx, ImPlotColormap cmap = IMPLOT_AUTO);
|
||||||
IMPLOT_API ImVec4 SampleColormap(float t, ImPlotColormap cmap = IMPLOT_AUTO);
|
IMPLOT_API ImVec4 SampleColormap(float t, ImPlotColormap cmap = IMPLOT_AUTO);
|
||||||
|
|
||||||
// Shows a vertical color scale with linear spaced ticks using the specified color map. Use double hashes to hide label (e.g. "##NoLabel").
|
// Shows a vertical color scale with linear spaced ticks using the specified color map. Use double hashes to hide label (e.g. "##NoLabel").
|
||||||
IMPLOT_API void ColormapScale(const char* label, double scale_min, double scale_max, const ImVec2& size = ImVec2(0,0), ImPlotColormap cmap = IMPLOT_AUTO);
|
IMPLOT_API void ColormapScale(const char* label, double scale_min, double scale_max, const ImVec2& size = ImVec2(0,0), ImPlotColormap cmap = IMPLOT_AUTO, const char* fmt = "%g");
|
||||||
// Shows a horizontal slider with a colormap gradient background. Optionally returns the color sampled at t in [0 1].
|
// Shows a horizontal slider with a colormap gradient background. Optionally returns the color sampled at t in [0 1].
|
||||||
IMPLOT_API bool ColormapSlider(const char* label, float* t, ImVec4* out = NULL, const char* format = "", ImPlotColormap cmap = IMPLOT_AUTO);
|
IMPLOT_API bool ColormapSlider(const char* label, float* t, ImVec4* out = NULL, const char* format = "", ImPlotColormap cmap = IMPLOT_AUTO);
|
||||||
// Shows a button with a colormap gradient brackground.
|
// Shows a button with a colormap gradient brackground.
|
||||||
|
|
|
@ -1420,8 +1420,11 @@ void ShowDemoWindow(bool* p_open) {
|
||||||
}
|
}
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
if (ImGui::CollapsingHeader("Custom Ticks##")) {
|
if (ImGui::CollapsingHeader("Custom Ticks##")) {
|
||||||
static bool custom_ticks = true;
|
static bool custom_fmt = true;
|
||||||
|
static bool custom_ticks = false;
|
||||||
static bool custom_labels = true;
|
static bool custom_labels = true;
|
||||||
|
ImGui::Checkbox("Show Custom Format", &custom_fmt);
|
||||||
|
ImGui::SameLine();
|
||||||
ImGui::Checkbox("Show Custom Ticks", &custom_ticks);
|
ImGui::Checkbox("Show Custom Ticks", &custom_ticks);
|
||||||
if (custom_ticks) {
|
if (custom_ticks) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
|
@ -1433,11 +1436,17 @@ void ShowDemoWindow(bool* p_open) {
|
||||||
static const char* ylabels[] = {"One","Three","Seven","Nine"};
|
static const char* ylabels[] = {"One","Three","Seven","Nine"};
|
||||||
static double yticks_aux[] = {0.2,0.4,0.6};
|
static double yticks_aux[] = {0.2,0.4,0.6};
|
||||||
static const char* ylabels_aux[] = {"A","B","C","D","E","F"};
|
static const char* ylabels_aux[] = {"A","B","C","D","E","F"};
|
||||||
|
if (custom_fmt) {
|
||||||
|
ImPlot::SetNextPlotFormatX("%g ms");
|
||||||
|
ImPlot::SetNextPlotFormatY("%g Hz", ImPlotYAxis_1);
|
||||||
|
ImPlot::SetNextPlotFormatY("%g dB", ImPlotYAxis_2);
|
||||||
|
ImPlot::SetNextPlotFormatY("%g km", ImPlotYAxis_3);
|
||||||
|
}
|
||||||
if (custom_ticks) {
|
if (custom_ticks) {
|
||||||
ImPlot::SetNextPlotTicksX(&pi,1,custom_labels ? pi_str : NULL, true);
|
ImPlot::SetNextPlotTicksX(&pi,1,custom_labels ? pi_str : NULL, true);
|
||||||
ImPlot::SetNextPlotTicksY(yticks, 4, custom_labels ? ylabels : NULL);
|
ImPlot::SetNextPlotTicksY(yticks, 4, custom_labels ? ylabels : NULL, ImPlotYAxis_1);
|
||||||
ImPlot::SetNextPlotTicksY(yticks_aux, 3, custom_labels ? ylabels_aux : NULL, false, 1);
|
ImPlot::SetNextPlotTicksY(yticks_aux, 3, custom_labels ? ylabels_aux : NULL, false, ImPlotYAxis_2);
|
||||||
ImPlot::SetNextPlotTicksY(0, 1, 6, custom_labels ? ylabels_aux : NULL, false, 2);
|
ImPlot::SetNextPlotTicksY(0, 1, 6, custom_labels ? ylabels_aux : NULL, false, ImPlotYAxis_3);
|
||||||
}
|
}
|
||||||
ImPlot::SetNextPlotLimits(2.5,5,0,10);
|
ImPlot::SetNextPlotLimits(2.5,5,0,10);
|
||||||
if (ImPlot::BeginPlot("Custom Ticks", NULL, NULL, ImVec2(-1,0), ImPlotFlags_YAxis2 | ImPlotFlags_YAxis3)) {
|
if (ImPlot::BeginPlot("Custom Ticks", NULL, NULL, ImVec2(-1,0), ImPlotFlags_YAxis2 | ImPlotFlags_YAxis3)) {
|
||||||
|
@ -1545,8 +1554,9 @@ void ShowDemoWindow(bool* p_open) {
|
||||||
ImGui::SameLine(); ImGui::ColorEdit4("##Bull", &bullCol.x, ImGuiColorEditFlags_NoInputs);
|
ImGui::SameLine(); ImGui::ColorEdit4("##Bull", &bullCol.x, ImGuiColorEditFlags_NoInputs);
|
||||||
ImGui::SameLine(); ImGui::ColorEdit4("##Bear", &bearCol.x, ImGuiColorEditFlags_NoInputs);
|
ImGui::SameLine(); ImGui::ColorEdit4("##Bear", &bearCol.x, ImGuiColorEditFlags_NoInputs);
|
||||||
ImPlot::GetStyle().UseLocalTime = false;
|
ImPlot::GetStyle().UseLocalTime = false;
|
||||||
|
ImPlot::SetNextPlotFormatY("$%.0f");
|
||||||
ImPlot::SetNextPlotLimits(1546300800, 1571961600, 1250, 1600);
|
ImPlot::SetNextPlotLimits(1546300800, 1571961600, 1250, 1600);
|
||||||
if (ImPlot::BeginPlot("Candlestick Chart","Day","USD",ImVec2(-1,0),0,ImPlotAxisFlags_Time)) {
|
if (ImPlot::BeginPlot("Candlestick Chart",NULL,NULL,ImVec2(-1,0),0,ImPlotAxisFlags_Time)) {
|
||||||
MyImPlot::PlotCandlestick("GOOGL",dates, opens, closes, lows, highs, 218, tooltip, 0.25f, bullCol, bearCol);
|
MyImPlot::PlotCandlestick("GOOGL",dates, opens, closes, lows, highs, 218, tooltip, 0.25f, bullCol, bearCol);
|
||||||
ImPlot::EndPlot();
|
ImPlot::EndPlot();
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,14 +51,14 @@
|
||||||
|
|
||||||
// The maximum number of supported y-axes (DO NOT CHANGE THIS)
|
// The maximum number of supported y-axes (DO NOT CHANGE THIS)
|
||||||
#define IMPLOT_Y_AXES 3
|
#define IMPLOT_Y_AXES 3
|
||||||
// The number of times to subdivided grid divisions (best if a multiple of 1, 2, and 5)
|
|
||||||
#define IMPLOT_SUB_DIV 10
|
|
||||||
// Zoom rate for scroll (e.g. 0.1f = 10% plot range every scroll click)
|
// Zoom rate for scroll (e.g. 0.1f = 10% plot range every scroll click)
|
||||||
#define IMPLOT_ZOOM_RATE 0.1f
|
#define IMPLOT_ZOOM_RATE 0.1f
|
||||||
// Mimimum allowable timestamp value 01/01/1970 @ 12:00am (UTC) (DO NOT DECREASE THIS)
|
// Mimimum allowable timestamp value 01/01/1970 @ 12:00am (UTC) (DO NOT DECREASE THIS)
|
||||||
#define IMPLOT_MIN_TIME 0
|
#define IMPLOT_MIN_TIME 0
|
||||||
// Maximum allowable timestamp value 01/01/3000 @ 12:00am (UTC) (DO NOT INCREASE THIS)
|
// Maximum allowable timestamp value 01/01/3000 @ 12:00am (UTC) (DO NOT INCREASE THIS)
|
||||||
#define IMPLOT_MAX_TIME 32503680000
|
#define IMPLOT_MAX_TIME 32503680000
|
||||||
|
// Default label format for axis labels
|
||||||
|
#define IMPLOT_LABEL_FMT "%g"
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] Macros
|
// [SECTION] Macros
|
||||||
|
@ -528,6 +528,7 @@ struct ImPlotTick
|
||||||
struct ImPlotTickCollection {
|
struct ImPlotTickCollection {
|
||||||
ImVector<ImPlotTick> Ticks;
|
ImVector<ImPlotTick> Ticks;
|
||||||
ImGuiTextBuffer TextBuffer;
|
ImGuiTextBuffer TextBuffer;
|
||||||
|
float TotalWidthMax;
|
||||||
float TotalWidth;
|
float TotalWidth;
|
||||||
float TotalHeight;
|
float TotalHeight;
|
||||||
float MaxWidth;
|
float MaxWidth;
|
||||||
|
@ -536,22 +537,28 @@ struct ImPlotTickCollection {
|
||||||
|
|
||||||
ImPlotTickCollection() { Reset(); }
|
ImPlotTickCollection() { Reset(); }
|
||||||
|
|
||||||
void Append(const ImPlotTick& tick) {
|
const ImPlotTick& Append(const ImPlotTick& tick) {
|
||||||
if (tick.ShowLabel) {
|
if (tick.ShowLabel) {
|
||||||
TotalWidth += tick.ShowLabel ? tick.LabelSize.x : 0;
|
TotalWidth += tick.ShowLabel ? tick.LabelSize.x : 0;
|
||||||
TotalHeight += tick.ShowLabel ? tick.LabelSize.y : 0;
|
TotalHeight += tick.ShowLabel ? tick.LabelSize.y : 0;
|
||||||
MaxWidth = tick.LabelSize.x > MaxWidth ? tick.LabelSize.x : MaxWidth;
|
MaxWidth = tick.LabelSize.x > MaxWidth ? tick.LabelSize.x : MaxWidth;
|
||||||
MaxHeight = tick.LabelSize.y > MaxHeight ? tick.LabelSize.y : MaxHeight;
|
MaxHeight = tick.LabelSize.y > MaxHeight ? tick.LabelSize.y : MaxHeight;
|
||||||
}
|
}
|
||||||
Ticks.push_back(tick);
|
Ticks.push_back(tick);
|
||||||
Size++;
|
Size++;
|
||||||
|
return Ticks.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Append(double value, bool major, bool show_label, void (*labeler)(ImPlotTick& tick, ImGuiTextBuffer& buf)) {
|
const ImPlotTick& Append(double value, bool major, bool show_label, const char* fmt) {
|
||||||
ImPlotTick tick(value, major, show_label);
|
ImPlotTick tick(value, major, show_label);
|
||||||
if (labeler)
|
if (show_label && fmt != NULL) {
|
||||||
labeler(tick, TextBuffer);
|
char temp[32];
|
||||||
Append(tick);
|
tick.TextOffset = TextBuffer.size();
|
||||||
|
snprintf(temp, 32, fmt, tick.PlotPos);
|
||||||
|
TextBuffer.append(temp, temp + strlen(temp) + 1);
|
||||||
|
tick.LabelSize = ImGui::CalcTextSize(TextBuffer.Buf.Data + tick.TextOffset);
|
||||||
|
}
|
||||||
|
return Append(tick);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* GetText(int idx) const {
|
const char* GetText(int idx) const {
|
||||||
|
@ -788,6 +795,10 @@ struct ImPlotNextPlotData
|
||||||
bool HasYRange[IMPLOT_Y_AXES];
|
bool HasYRange[IMPLOT_Y_AXES];
|
||||||
bool ShowDefaultTicksX;
|
bool ShowDefaultTicksX;
|
||||||
bool ShowDefaultTicksY[IMPLOT_Y_AXES];
|
bool ShowDefaultTicksY[IMPLOT_Y_AXES];
|
||||||
|
char FmtX[16];
|
||||||
|
char FmtY[IMPLOT_Y_AXES][16];
|
||||||
|
bool HasFmtX;
|
||||||
|
bool HasFmtY[IMPLOT_Y_AXES];
|
||||||
bool FitX;
|
bool FitX;
|
||||||
bool FitY[IMPLOT_Y_AXES];
|
bool FitY[IMPLOT_Y_AXES];
|
||||||
double* LinkedXmin;
|
double* LinkedXmin;
|
||||||
|
@ -800,11 +811,13 @@ struct ImPlotNextPlotData
|
||||||
void Reset() {
|
void Reset() {
|
||||||
HasXRange = false;
|
HasXRange = false;
|
||||||
ShowDefaultTicksX = true;
|
ShowDefaultTicksX = true;
|
||||||
|
HasFmtX = false;
|
||||||
FitX = false;
|
FitX = false;
|
||||||
LinkedXmin = LinkedXmax = NULL;
|
LinkedXmin = LinkedXmax = NULL;
|
||||||
for (int i = 0; i < IMPLOT_Y_AXES; ++i) {
|
for (int i = 0; i < IMPLOT_Y_AXES; ++i) {
|
||||||
HasYRange[i] = false;
|
HasYRange[i] = false;
|
||||||
ShowDefaultTicksY[i] = true;
|
ShowDefaultTicksY[i] = true;
|
||||||
|
HasFmtY[i] = false;
|
||||||
FitY[i] = false;
|
FitY[i] = false;
|
||||||
LinkedYmin[i] = LinkedYmax[i] = NULL;
|
LinkedYmin[i] = LinkedYmax[i] = NULL;
|
||||||
}
|
}
|
||||||
|
@ -993,6 +1006,10 @@ IMPLOT_API void PullLinkedAxis(ImPlotAxis& axis);
|
||||||
// Shows an axis's context menu.
|
// Shows an axis's context menu.
|
||||||
IMPLOT_API void ShowAxisContextMenu(ImPlotAxis& axis, ImPlotAxis* equal_axis, bool time_allowed = false);
|
IMPLOT_API void ShowAxisContextMenu(ImPlotAxis& axis, ImPlotAxis* equal_axis, bool time_allowed = false);
|
||||||
|
|
||||||
|
// Get format spec for axis
|
||||||
|
static inline const char* GetFormatX() { return GImPlot->NextPlotData.HasFmtX ? GImPlot->NextPlotData.FmtX : IMPLOT_LABEL_FMT; }
|
||||||
|
static inline const char* GetFormatY(ImPlotYAxis y) { return GImPlot->NextPlotData.HasFmtY[y] ? GImPlot->NextPlotData.FmtY[y] : IMPLOT_LABEL_FMT; }
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// [SECTION] Legend Utils
|
// [SECTION] Legend Utils
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -1010,21 +1027,17 @@ IMPLOT_API void ShowAltLegend(const char* title_id, ImPlotOrientation orientatio
|
||||||
// [SECTION] Tick Utils
|
// [SECTION] Tick Utils
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Label a tick with default formatting.
|
|
||||||
IMPLOT_API void LabelTickDefault(ImPlotTick& tick, ImGuiTextBuffer& buffer);
|
|
||||||
// Label a tick with scientific formating.
|
|
||||||
IMPLOT_API void LabelTickScientific(ImPlotTick& tick, ImGuiTextBuffer& buffer);
|
|
||||||
// Label a tick with time formatting.
|
// Label a tick with time formatting.
|
||||||
IMPLOT_API void LabelTickTime(ImPlotTick& tick, ImGuiTextBuffer& buffer, const ImPlotTime& t, ImPlotDateTimeFmt fmt);
|
IMPLOT_API void LabelTickTime(ImPlotTick& tick, ImGuiTextBuffer& buffer, const ImPlotTime& t, ImPlotDateTimeFmt fmt);
|
||||||
|
|
||||||
// Populates a list of ImPlotTicks with normal spaced and formatted ticks
|
// Populates a list of ImPlotTicks with normal spaced and formatted ticks
|
||||||
IMPLOT_API void AddTicksDefault(const ImPlotRange& range, int nMajor, int nMinor, ImPlotTickCollection& ticks);
|
IMPLOT_API void AddTicksDefault(const ImPlotRange& range, float pix, ImPlotOrientation orn, ImPlotTickCollection& ticks, const char* fmt);
|
||||||
// Populates a list of ImPlotTicks with logarithmic space and formatted ticks
|
// Populates a list of ImPlotTicks with logarithmic space and formatted ticks
|
||||||
IMPLOT_API void AddTicksLogarithmic(const ImPlotRange& range, int nMajor, ImPlotTickCollection& ticks);
|
IMPLOT_API void AddTicksLogarithmic(const ImPlotRange& range, float pix, ImPlotOrientation orn, ImPlotTickCollection& ticks, const char* fmt);
|
||||||
// Populates a list of ImPlotTicks with time formatted ticks.
|
// Populates a list of ImPlotTicks with time formatted ticks.
|
||||||
IMPLOT_API void AddTicksTime(const ImPlotRange& range, float plot_width, ImPlotTickCollection& ticks);
|
IMPLOT_API void AddTicksTime(const ImPlotRange& range, float plot_width, ImPlotTickCollection& ticks);
|
||||||
// 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, const char* fmt);
|
||||||
|
|
||||||
// Create a a string label for a an axis value
|
// 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);
|
IMPLOT_API int LabelAxisValue(const ImPlotAxis& axis, const ImPlotTickCollection& ticks, double value, char* buff, int size);
|
||||||
|
@ -1057,7 +1070,7 @@ static inline ImVec2 CalcTextSizeVertical(const char *text) {
|
||||||
// Returns white or black text given background color
|
// Returns white or black text given background color
|
||||||
static inline ImU32 CalcTextColor(const ImVec4& bg) { return (bg.x * 0.299 + bg.y * 0.587 + bg.z * 0.114) > 0.5 ? IM_COL32_BLACK : IM_COL32_WHITE; }
|
static inline ImU32 CalcTextColor(const ImVec4& bg) { return (bg.x * 0.299 + bg.y * 0.587 + bg.z * 0.114) > 0.5 ? IM_COL32_BLACK : IM_COL32_WHITE; }
|
||||||
static inline ImU32 CalcTextColor(ImU32 bg) { return CalcTextColor(ImGui::ColorConvertU32ToFloat4(bg)); }
|
static inline ImU32 CalcTextColor(ImU32 bg) { return CalcTextColor(ImGui::ColorConvertU32ToFloat4(bg)); }
|
||||||
// Lights or darkens a color for hover
|
// Lightens or darkens a color for hover
|
||||||
static inline ImU32 CalcHoverColor(ImU32 col) { return ImMixU32(col, CalcTextColor(col), 32); }
|
static inline ImU32 CalcHoverColor(ImU32 col) { return ImMixU32(col, CalcTextColor(col), 32); }
|
||||||
|
|
||||||
// Clamps a label position so that it fits a rect defined by Min/Max
|
// Clamps a label position so that it fits a rect defined by Min/Max
|
||||||
|
@ -1091,6 +1104,8 @@ static inline int OrderOfMagnitude(double val) { return val == 0 ? 0 : (int)(flo
|
||||||
static inline int OrderToPrecision(int order) { return order > 0 ? 0 : 1 - order; }
|
static inline int OrderToPrecision(int order) { return order > 0 ? 0 : 1 - order; }
|
||||||
// Returns a floating point precision to use given a value
|
// Returns a floating point precision to use given a value
|
||||||
static inline int Precision(double val) { return OrderToPrecision(OrderOfMagnitude(val)); }
|
static inline int Precision(double val) { return OrderToPrecision(OrderOfMagnitude(val)); }
|
||||||
|
// Round a value to a given precision
|
||||||
|
static inline double RoundTo(double val, int prec) { double p = pow(10,(double)prec); return floor(val*p+0.5)/p; }
|
||||||
|
|
||||||
// Returns the intersection point of two lines A and B (assumes they are not parallel!)
|
// Returns the intersection point of two lines A and B (assumes they are not parallel!)
|
||||||
static inline ImVec2 Intersection(const ImVec2& a1, const ImVec2& a2, const ImVec2& b1, const ImVec2& b2) {
|
static inline ImVec2 Intersection(const ImVec2& a1, const ImVec2& a2, const ImVec2& b1, const ImVec2& b2) {
|
||||||
|
@ -1118,7 +1133,7 @@ static inline T OffsetAndStride(const T* data, int idx, int count, int offset, i
|
||||||
|
|
||||||
// Calculate histogram bin counts and widths
|
// Calculate histogram bin counts and widths
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void CalculateBins(const T* values, int count, ImPlotBin meth, const ImPlotRange& range, int& bins_out, double& width_out) {
|
static inline void CalculateBins(const T* values, int count, ImPlotBin meth, const ImPlotRange& range, int& bins_out, double& width_out) {
|
||||||
switch (meth) {
|
switch (meth) {
|
||||||
case ImPlotBin_Sqrt:
|
case ImPlotBin_Sqrt:
|
||||||
bins_out = (int)ceil(sqrt(count));
|
bins_out = (int)ceil(sqrt(count));
|
||||||
|
|
Loading…
Reference in New Issue
Block a user