mirror of
https://github.com/gwm17/implot.git
synced 2024-11-26 20:28:50 -05:00
convert to ImPlotTime usage
This commit is contained in:
parent
f92625a462
commit
d3ea373cc7
146
implot.cpp
146
implot.cpp
|
@ -617,9 +617,9 @@ inline int LowerBoundStep(int max_divs, const int* divs, const int* step, int si
|
|||
|
||||
inline int GetTimeStep(int max_divs, ImPlotTimeUnit unit) {
|
||||
if (unit == ImPlotTimeUnit_Ms || unit == ImPlotTimeUnit_Us) {
|
||||
static const int step[] = {500,250,200,100,50,25,20,10,5};
|
||||
static const int divs[] = {2,4,5,10,20,40,50,100,200};
|
||||
return LowerBoundStep(max_divs, divs, step, 9);
|
||||
static const int step[] = {500,250,200,100,50,25,20,10,5,2,1};
|
||||
static const int divs[] = {2,4,5,10,20,40,50,100,200,500,1000};
|
||||
return LowerBoundStep(max_divs, divs, step, 11);
|
||||
}
|
||||
if (unit == ImPlotTimeUnit_S || unit == ImPlotTimeUnit_Min) {
|
||||
static const int step[] = {30,15,10,5,1};
|
||||
|
@ -670,63 +670,63 @@ inline tm* GetGmTime(const time_t* time, tm* tm)
|
|||
#endif
|
||||
}
|
||||
|
||||
double AddTime(double t, ImPlotTimeUnit unit, int count) {
|
||||
ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count) {
|
||||
ImPlotTime t_out = t;
|
||||
switch(unit) {
|
||||
case ImPlotTimeUnit_Us: return t + count * 0.000001;
|
||||
case ImPlotTimeUnit_Ms: return t + count * 0.001;
|
||||
case ImPlotTimeUnit_S: return t + count;
|
||||
case ImPlotTimeUnit_Min: return t + count * 60;
|
||||
case ImPlotTimeUnit_Hr: return t + count * 3600;
|
||||
case ImPlotTimeUnit_Day: return t + count * 86400;
|
||||
case ImPlotTimeUnit_Us: return ImPlotTime(t.S, t.Us + count);
|
||||
case ImPlotTimeUnit_Ms: return ImPlotTime(t.S, t.Us + count * 1000);
|
||||
case ImPlotTimeUnit_S: t_out.S += count; break;
|
||||
case ImPlotTimeUnit_Min: t_out.S += count * 60; break;
|
||||
case ImPlotTimeUnit_Hr: t_out.S += count * 3600; break;
|
||||
case ImPlotTimeUnit_Day: t_out.S += count * 86400; break;
|
||||
case ImPlotTimeUnit_Yr: count *= 12; // fall-through
|
||||
case ImPlotTimeUnit_Mo: for (int i = 0; i < count; ++i) {
|
||||
time_t s = (time_t)t;
|
||||
GetGmTime(&s, &GImPlot->Tm);
|
||||
GetGmTime(&t.S, &GImPlot->Tm);
|
||||
int days = GetDaysInMonth(GImPlot->Tm.tm_year, GImPlot->Tm.tm_mon);
|
||||
t = AddTime(t, ImPlotTimeUnit_Day, days);
|
||||
t_out = AddTime(t_out, ImPlotTimeUnit_Day, days);
|
||||
}
|
||||
return t;
|
||||
default: return t;
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return t_out;
|
||||
}
|
||||
|
||||
double FloorTime(double t, ImPlotTimeUnit unit) {
|
||||
time_t s = (time_t)t;
|
||||
GetGmTime(&s, &GImPlot->Tm);
|
||||
ImPlotTime FloorTime(const ImPlotTime& t, ImPlotTimeUnit unit) {
|
||||
GetGmTime(&t.S, &GImPlot->Tm);
|
||||
GImPlot->Tm.tm_isdst = -1;
|
||||
switch (unit) {
|
||||
case ImPlotTimeUnit_S: return (double)s;
|
||||
case ImPlotTimeUnit_Ms: return floor(t * 1000) / 1000;
|
||||
case ImPlotTimeUnit_Us: return floor(t * 1000000) / 1000000;
|
||||
case ImPlotTimeUnit_S: return ImPlotTime(t.S, 0);
|
||||
case ImPlotTimeUnit_Ms: return ImPlotTime(t.S, (t.Us / 1000) * 1000);
|
||||
case ImPlotTimeUnit_Us: return t;
|
||||
case ImPlotTimeUnit_Yr: GImPlot->Tm.tm_mon = 0; // fall-through
|
||||
case ImPlotTimeUnit_Mo: GImPlot->Tm.tm_mday = 1; // fall-through
|
||||
case ImPlotTimeUnit_Day: GImPlot->Tm.tm_hour = 0; // fall-through
|
||||
case ImPlotTimeUnit_Hr: GImPlot->Tm.tm_min = 0; // fall-through
|
||||
case ImPlotTimeUnit_Min: GImPlot->Tm.tm_sec = 0; break;
|
||||
default: return t;
|
||||
default: return t;
|
||||
}
|
||||
s = MakeGmTime(&GImPlot->Tm);
|
||||
return (double)s;
|
||||
return ImPlotTime(MakeGmTime(&GImPlot->Tm),0);
|
||||
}
|
||||
|
||||
double CeilTime(double t, ImPlotTimeUnit unit) {
|
||||
ImPlotTime CeilTime(const ImPlotTime& t, ImPlotTimeUnit unit) {
|
||||
return AddTime(FloorTime(t, unit), unit, 1);
|
||||
}
|
||||
|
||||
double RoundTime(double t, ImPlotTimeUnit unit) {
|
||||
double t1 = FloorTime(t, unit);
|
||||
double t2 = AddTime(t1,unit,1);
|
||||
return t - t1 < t2 - t ? t1 : t2;
|
||||
ImPlotTime RoundTime(const ImPlotTime& t, ImPlotTimeUnit unit) {
|
||||
ImPlotTime t1 = FloorTime(t, unit);
|
||||
ImPlotTime t2 = AddTime(t1,unit,1);
|
||||
if (t1.S == t2.S)
|
||||
return t.Us - t1.Us < t2.Us - t.Us ? t1 : t2;
|
||||
return t.S - t1.S < t2.S - t.S ? t1 : t2;
|
||||
}
|
||||
|
||||
int GetYear(double t) {
|
||||
time_t s = (time_t)t;
|
||||
int GetYear(const ImPlotTime& t) {
|
||||
tm& Tm = GImPlot->Tm;
|
||||
GetGmTime(&s, &Tm);
|
||||
GetGmTime(&t.S, &Tm);
|
||||
return Tm.tm_year + 1900;
|
||||
}
|
||||
|
||||
double MakeYear(int year) {
|
||||
ImPlotTime MakeYear(int year) {
|
||||
int yr = year - 1900;
|
||||
if (yr < 0)
|
||||
yr = 0;
|
||||
|
@ -739,17 +739,13 @@ double MakeYear(int year) {
|
|||
return (double)s;
|
||||
}
|
||||
|
||||
int FormatTime(double t, char* buffer, int size, ImPlotTimeFmt fmt) {
|
||||
printf("%.6f\n",t);
|
||||
time_t s = (time_t)t;
|
||||
int ms = (int)(t * 1000 - floor(t) * 1000);
|
||||
ms = ms % 10 == 9 ? ms + 1 : ms; // don't like this
|
||||
int us = (int)(t * 1000000 - floor(t) * 1000000);
|
||||
us = us % 10 == 9 ? us + 1 : us; // don't like this
|
||||
int FormatTime(const ImPlotTime& t, char* buffer, int size, ImPlotTimeFmt fmt) {
|
||||
tm& Tm = GImPlot->Tm;
|
||||
GetGmTime(&s, &Tm);
|
||||
GetGmTime(&t.S, &Tm);
|
||||
|
||||
const char* ap = Tm.tm_hour < 12 ? "am" : "pm";
|
||||
const int us = t.Us % 1000;
|
||||
const int ms = t.Us / 1000;
|
||||
const int sec = Tm.tm_sec;
|
||||
const int min = Tm.tm_min;
|
||||
const int hr = (Tm.tm_hour == 0 || Tm.tm_hour == 12) ? 12 : Tm.tm_hour % 12;
|
||||
|
@ -761,8 +757,8 @@ int FormatTime(double t, char* buffer, int size, ImPlotTimeFmt fmt) {
|
|||
static const char mnames[12][4] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
|
||||
|
||||
switch(fmt) {
|
||||
case ImPlotTimeFmt_Us: return snprintf(buffer, size, ".%06d", us);
|
||||
case ImPlotTimeFmt_SUs: return snprintf(buffer, size, ":%02d.%06d", sec, us);
|
||||
case ImPlotTimeFmt_Us: return snprintf(buffer, size, ".%03d %03d", ms, us);
|
||||
case ImPlotTimeFmt_SUs: return snprintf(buffer, size, ":%02d.%03d %03d", sec, ms, us);
|
||||
case ImPlotTimeFmt_SMs: return snprintf(buffer, size, ":%02d.%03d", sec, ms);
|
||||
case ImPlotTimeFmt_S: return snprintf(buffer, size, ":%02d", sec);
|
||||
case ImPlotTimeFmt_HrMinS: return snprintf(buffer, size, "%d:%02d:%02d%s", hr, min, sec, ap);
|
||||
|
@ -773,6 +769,7 @@ int FormatTime(double t, char* buffer, int size, ImPlotTimeFmt fmt) {
|
|||
case ImPlotTimeFmt_DayMoYr: return snprintf(buffer, size, "%d/%d/%d", mon, day, yr);
|
||||
case ImPlotTimeFmt_DayMoYrHrMin: return snprintf(buffer, size, "%d/%d/%d %u:%02d%s", mon, day, yr, hr, min, ap);
|
||||
case ImPlotTimeFmt_DayMoYrHrMinS: return snprintf(buffer, size, "%d/%d/%d %u:%02d:%02d%s", mon, day, yr, hr, min, sec, ap);
|
||||
case ImPlotTimeFmt_MoYr: return snprintf(buffer, size, "%s %d", mnames[Tm.tm_mon], year);
|
||||
case ImPlotTimeFmt_Mo: return snprintf(buffer, size, "%s", mnames[Tm.tm_mon]);
|
||||
case ImPlotTimeFmt_Yr: return snprintf(buffer, size, "%d", year);
|
||||
default: return 0;
|
||||
|
@ -788,8 +785,8 @@ void PrintTime(double t, ImPlotTimeFmt fmt) {
|
|||
// Returns the nominally largest possible width for a time format
|
||||
inline float GetTimeLabelWidth(ImPlotTimeFmt fmt) {
|
||||
switch (fmt) {
|
||||
case ImPlotTimeFmt_Us: return ImGui::CalcTextSize(".888888").x; // .428552
|
||||
case ImPlotTimeFmt_SUs: return ImGui::CalcTextSize(":88.888888").x; // :29.428552
|
||||
case ImPlotTimeFmt_Us: return ImGui::CalcTextSize(".888 888").x; // .428 552
|
||||
case ImPlotTimeFmt_SUs: return ImGui::CalcTextSize(":88.888 888").x; // :29.428 552
|
||||
case ImPlotTimeFmt_SMs: return ImGui::CalcTextSize(":88.888").x; // :29.428
|
||||
case ImPlotTimeFmt_S: return ImGui::CalcTextSize(":88").x; // :29
|
||||
case ImPlotTimeFmt_HrMinS: return ImGui::CalcTextSize("88:88:88pm").x; // 7:21:29pm
|
||||
|
@ -800,6 +797,7 @@ inline float GetTimeLabelWidth(ImPlotTimeFmt fmt) {
|
|||
case ImPlotTimeFmt_DayMoYr: return ImGui::CalcTextSize("88/88/88").x; // 10/3/1991
|
||||
case ImPlotTimeFmt_DayMoYrHrMin: return ImGui::CalcTextSize("88/88/88 88:88pm").x; // 10/3/91 7:21pm
|
||||
case ImPlotTimeFmt_DayMoYrHrMinS: return ImGui::CalcTextSize("88/88/88 88:88:88pm").x; // 10/3/91 7:21:29pm
|
||||
case ImPlotTimeFmt_MoYr: return ImGui::CalcTextSize("MMM 8888").x; // Oct 1991
|
||||
case ImPlotTimeFmt_Mo: return ImGui::CalcTextSize("MMM").x; // Oct
|
||||
case ImPlotTimeFmt_Yr: return ImGui::CalcTextSize("8888").x; // 1991
|
||||
default: return 0;
|
||||
|
@ -834,7 +832,7 @@ static const ImPlotTimeFmt TimeFormatLevel1[ImPlotTimeUnit_COUNT] = {
|
|||
ImPlotTimeFmt_HrMin,
|
||||
ImPlotTimeFmt_DayMo,
|
||||
ImPlotTimeFmt_DayMo,
|
||||
ImPlotTimeFmt_Yr,
|
||||
ImPlotTimeFmt_MoYr,
|
||||
ImPlotTimeFmt_Yr
|
||||
};
|
||||
|
||||
|
@ -845,7 +843,7 @@ static const ImPlotTimeFmt TimeFormatLevel1First[ImPlotTimeUnit_COUNT] = {
|
|||
ImPlotTimeFmt_DayMoYrHrMin,
|
||||
ImPlotTimeFmt_DayMoYr,
|
||||
ImPlotTimeFmt_DayMoYr,
|
||||
ImPlotTimeFmt_Yr,
|
||||
ImPlotTimeFmt_MoYr,
|
||||
ImPlotTimeFmt_Yr
|
||||
};
|
||||
|
||||
|
@ -859,10 +857,16 @@ void AddTicksTime(const ImPlotRange& range, float plot_width, ImPlotTickCollecti
|
|||
const ImPlotTimeFmt fmt1 = TimeFormatLevel1[unit1];
|
||||
const ImPlotTimeFmt fmtf = TimeFormatLevel1First[unit1];
|
||||
|
||||
const ImPlotTime t_min(range.Min);
|
||||
const ImPlotTime t_max(range.Max);
|
||||
|
||||
// maximum allowable density of labels
|
||||
const float max_density = 0.5f;
|
||||
|
||||
// book keeping
|
||||
bool first = true;
|
||||
const char* last_major = NULL;
|
||||
|
||||
if (unit0 != ImPlotTimeUnit_Yr) {
|
||||
// pixels per major (level 1) division
|
||||
const float pix_per_major_div = plot_width / (float)(range.Size() / TimeUnitSpans[unit1]);
|
||||
|
@ -873,16 +877,17 @@ void AddTicksTime(const ImPlotRange& range, float plot_width, ImPlotTickCollecti
|
|||
// the minor step size (level 0)
|
||||
const int step = GetTimeStep(minor_per_major, unit0);
|
||||
// generate ticks
|
||||
double t1 = FloorTime(range.Min, unit1);
|
||||
while (t1 < range.Max) {
|
||||
if (range.Contains(t1)) {
|
||||
ImPlotTime t1 = FloorTime(ImPlotTime(range.Min), unit1);
|
||||
t1 = t1;
|
||||
while (t1 < t_max) {
|
||||
if (t1 >= t_min && t1 <= t_max) {
|
||||
// minor level 0 tick
|
||||
ImPlotTick tick_min(t1,true,true);
|
||||
ImPlotTick tick_min(t1.ToDouble(),true,true);
|
||||
tick_min.Level = 0;
|
||||
LabelTickTime(tick_min,ticks.Labels,fmt0);
|
||||
ticks.AddTick(tick_min);
|
||||
// major level 1 tick
|
||||
ImPlotTick tick_maj(t1,true,true);
|
||||
ImPlotTick tick_maj(t1.ToDouble(),true,true);
|
||||
tick_maj.Level = 1;
|
||||
LabelTickTime(tick_maj,ticks.Labels,first ? fmtf : fmt1);
|
||||
const char* this_major = ticks.Labels.Buf.Data + tick_maj.BufferOffset;
|
||||
|
@ -897,14 +902,13 @@ void AddTicksTime(const ImPlotRange& range, float plot_width, ImPlotTickCollecti
|
|||
if (first) first = false;
|
||||
}
|
||||
// add minor ticks up until next major
|
||||
const double t2 = AddTime(t1, unit1, 1);
|
||||
const ImPlotRange r12(t1,t2);
|
||||
if (minor_per_major > 1 && RangesOverlap(range,r12)) {
|
||||
double t12 = AddTime(t1, unit0, step);
|
||||
const ImPlotTime t2 = AddTime(t1, unit1, 1);
|
||||
if (minor_per_major > 1 && (t_min <= t2 && t1 <= t_max)) {
|
||||
ImPlotTime t12 = AddTime(t1, unit0, step);
|
||||
while (t12 < t2) {
|
||||
float px_to_t2 = (float)((t2 - t12)/range.Size()) * plot_width;
|
||||
if (range.Contains(t12)) {
|
||||
ImPlotTick tick(t12,false,px_to_t2 >= minor_label_width);
|
||||
float px_to_t2 = (float)((t2 - t12).ToDouble()/range.Size()) * plot_width;
|
||||
if (t12 >= t_min && t12 <= t_max) {
|
||||
ImPlotTick tick(t12.ToDouble(),false,px_to_t2 >= minor_label_width);
|
||||
tick.Level = 0;
|
||||
LabelTickTime(tick,ticks.Labels,fmt0);
|
||||
ticks.AddTick(tick);
|
||||
|
@ -931,10 +935,10 @@ void AddTicksTime(const ImPlotRange& range, float plot_width, ImPlotTickCollecti
|
|||
const double interval = NiceNum(nice_range / (max_labels - 1), true);
|
||||
const int graphmin = (int)(floor(year_min / interval) * interval);
|
||||
const int step = (int)interval <= 0 ? 1 : (int)interval;
|
||||
double t1 = MakeYear(graphmin);
|
||||
ImPlotTime t1 = MakeYear(graphmin);
|
||||
while (t1 < range.Max) {
|
||||
if (range.Contains(t1)) {
|
||||
ImPlotTick tick(t1, true, true);
|
||||
if (t1 >= t_min && t1 <= t_max) {
|
||||
ImPlotTick tick(t1.ToDouble(), true, true);
|
||||
tick.Level = 0;
|
||||
LabelTickTime(tick, ticks.Labels, TimeFormatLevel0[ImPlotTimeUnit_Yr]);
|
||||
ticks.AddTick(tick);
|
||||
|
@ -1028,18 +1032,14 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
// NextPlotData -----------------------------------------------------------
|
||||
|
||||
if (gp.NextPlotData.HasXRange) {
|
||||
if (just_created || gp.NextPlotData.XRangeCond == ImGuiCond_Always) {
|
||||
plot.XAxis.Range = gp.NextPlotData.X;
|
||||
plot.XAxis.Constrain();
|
||||
}
|
||||
if (just_created || gp.NextPlotData.XRangeCond == ImGuiCond_Always)
|
||||
plot.XAxis.SetRange(gp.NextPlotData.X);
|
||||
}
|
||||
|
||||
for (int i = 0; i < IMPLOT_Y_AXES; i++) {
|
||||
if (gp.NextPlotData.HasYRange[i]) {
|
||||
if (just_created || gp.NextPlotData.YRangeCond[i] == ImGuiCond_Always) {
|
||||
plot.YAxis[i].Range = gp.NextPlotData.Y[i];
|
||||
plot.YAxis[i].Constrain();
|
||||
}
|
||||
if (just_created || gp.NextPlotData.YRangeCond[i] == ImGuiCond_Always)
|
||||
plot.YAxis[i].SetRange(gp.NextPlotData.Y[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1236,7 +1236,6 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
plot.XAxis.SetMin(gp.X.Invert ? plot_br.x : plot_tl.x);
|
||||
if (!gp.X.LockMax)
|
||||
plot.XAxis.SetMax(gp.X.Invert ? plot_tl.x : plot_br.x);
|
||||
// ConstrainAxis(plot.XAxis);
|
||||
}
|
||||
for (int i = 0; i < IMPLOT_Y_AXES; i++) {
|
||||
if (!gp.Y[i].Lock && plot.YAxis[i].Dragging) {
|
||||
|
@ -1246,7 +1245,6 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
plot.YAxis[i].SetMin(gp.Y[i].Invert ? plot_tl.y : plot_br.y);
|
||||
if (!gp.Y[i].LockMax)
|
||||
plot.YAxis[i].SetMax(gp.Y[i].Invert ? plot_br.y : plot_tl.y);
|
||||
// ConstrainAxis(plot.YAxis[i]);
|
||||
}
|
||||
}
|
||||
// Set the mouse cursor based on which axes are moving.
|
||||
|
@ -1301,7 +1299,6 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
plot.XAxis.SetMin(gp.X.Invert ? plot_br.x : plot_tl.x);
|
||||
if (!gp.X.LockMax)
|
||||
plot.XAxis.SetMax(gp.X.Invert ? plot_tl.x : plot_br.x);
|
||||
// ConstrainAxis(plot.XAxis);
|
||||
}
|
||||
for (int i = 0; i < IMPLOT_Y_AXES; i++) {
|
||||
if (plot.YAxis[i].HoveredTot && !gp.Y[i].Lock) {
|
||||
|
@ -1312,7 +1309,6 @@ bool BeginPlot(const char* title, const char* x_label, const char* y_label, cons
|
|||
plot.YAxis[i].SetMin(gp.Y[i].Invert ? plot_tl.y : plot_br.y);
|
||||
if (!gp.Y[i].LockMax)
|
||||
plot.YAxis[i].SetMax(gp.Y[i].Invert ? plot_br.y : plot_tl.y);
|
||||
// ConstrainAxis(plot.YAxis[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1977,7 +1973,6 @@ void EndPlot() {
|
|||
plot.XAxis.Range.Min -= FLT_EPSILON;
|
||||
}
|
||||
plot.XAxis.Constrain();
|
||||
// ConstrainAxis(plot.XAxis);
|
||||
for (int i = 0; i < IMPLOT_Y_AXES; i++) {
|
||||
if (gp.FitY[i] && !ImHasFlag(plot.YAxis[i].Flags, ImPlotAxisFlags_LockMin) && !ImNanOrInf(gp.ExtentsY[i].Min)) {
|
||||
plot.YAxis[i].Range.Min = (gp.ExtentsY[i].Min);
|
||||
|
@ -1990,7 +1985,6 @@ void EndPlot() {
|
|||
plot.YAxis[i].Range.Min -= FLT_EPSILON;
|
||||
}
|
||||
plot.YAxis[i].Constrain();
|
||||
// ConstrainAxis(plot.YAxis[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1271,7 +1271,8 @@ void StyleSeaborn() {
|
|||
|
||||
namespace MyImPlot {
|
||||
|
||||
int BinarySearch(const double* arr, int l, int r, double x) {
|
||||
template <typename T>
|
||||
int BinarySearch(const T* arr, int l, int r, T x) {
|
||||
if (r >= l) {
|
||||
int mid = l + (r - l) / 2;
|
||||
if (arr[mid] == x)
|
||||
|
@ -1284,6 +1285,39 @@ int BinarySearch(const double* arr, int l, int r, double x) {
|
|||
}
|
||||
|
||||
void PlotCandlestick(const char* label_id, const double* xs, const double* opens, const double* closes, const double* lows, const double* highs, int count, bool tooltip, float width_percent, ImVec4 bullCol, ImVec4 bearCol) {
|
||||
|
||||
// get ImGui window DrawList
|
||||
ImDrawList* draw_list = ImPlot::GetPlotDrawList();
|
||||
// calc real value width
|
||||
double half_width = count > 1 ? (xs[1] - xs[0]) * width_percent : width_percent;
|
||||
|
||||
// custom tool
|
||||
if (ImPlot::IsPlotHovered() && tooltip) {
|
||||
ImPlotPoint mouse = ImPlot::GetPlotMousePos();
|
||||
mouse.x = ImPlot::RoundTime(ImPlotTime(mouse.x), ImPlotTimeUnit_Day).ToDouble();
|
||||
float tool_l = ImPlot::PlotToPixels(mouse.x - half_width * 1.5, mouse.y).x;
|
||||
float tool_r = ImPlot::PlotToPixels(mouse.x + half_width * 1.5, mouse.y).x;
|
||||
float tool_t = ImPlot::GetPlotPos().y;
|
||||
float tool_b = tool_t + ImPlot::GetPlotSize().y;
|
||||
ImPlot::PushPlotClipRect();
|
||||
draw_list->AddRectFilled(ImVec2(tool_l, tool_t), ImVec2(tool_r, tool_b), IM_COL32(128,128,128,64));
|
||||
ImPlot::PopPlotClipRect();
|
||||
// find mouse location index
|
||||
int idx = BinarySearch(xs, 0, count - 1, mouse.x);
|
||||
// render tool tip (won't be affected by plot clip rect)
|
||||
if (idx != -1) {
|
||||
ImGui::BeginTooltip();
|
||||
char buff[32];
|
||||
ImPlot::FormatTime(xs[idx],buff,32,ImPlotTimeFmt_DayMoYr);
|
||||
ImGui::Text("Day: %s", buff);
|
||||
ImGui::Text("Open: $%.2f", opens[idx]);
|
||||
ImGui::Text("Close: $%.2f", closes[idx]);
|
||||
ImGui::Text("Low: $%.2f", lows[idx]);
|
||||
ImGui::Text("High: $%.2f", highs[idx]);
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
// begin plot item
|
||||
if (ImPlot::BeginItem(label_id)) {
|
||||
// override legend icon color
|
||||
|
@ -1295,10 +1329,6 @@ void PlotCandlestick(const char* label_id, const double* xs, const double* opens
|
|||
ImPlot::FitPoint(ImPlotPoint(xs[i], highs[i]));
|
||||
}
|
||||
}
|
||||
// get ImGui window DrawList
|
||||
ImDrawList* draw_list = ImPlot::GetPlotDrawList();
|
||||
// calc real value width
|
||||
double half_width = count > 1 ? (xs[1] - xs[0]) * width_percent : width_percent;
|
||||
// render data
|
||||
for (int i = 0; i < count; ++i) {
|
||||
ImVec2 open_pos = ImPlot::PlotToPixels(xs[i] - half_width, opens[i]);
|
||||
|
@ -1309,30 +1339,7 @@ void PlotCandlestick(const char* label_id, const double* xs, const double* opens
|
|||
draw_list->AddLine(low_pos, high_pos, color);
|
||||
draw_list->AddRectFilled(open_pos, close_pos, color);
|
||||
}
|
||||
// custom tool
|
||||
if (ImPlot::IsPlotHovered() && tooltip) {
|
||||
ImPlotPoint mouse = ImPlot::GetPlotMousePos();
|
||||
mouse.x = ImPlot::RoundTime(mouse.x, ImPlotTimeUnit_Day);
|
||||
float tool_l = ImPlot::PlotToPixels(mouse.x - half_width * 1.5, mouse.y).x;
|
||||
float tool_r = ImPlot::PlotToPixels(mouse.x + half_width * 1.5, mouse.y).x;
|
||||
float tool_t = ImPlot::GetPlotPos().y;
|
||||
float tool_b = tool_t + ImPlot::GetPlotSize().y;
|
||||
draw_list->AddRectFilled(ImVec2(tool_l, tool_t), ImVec2(tool_r, tool_b), IM_COL32(0,255,255,64));
|
||||
// find mouse location index
|
||||
int idx = BinarySearch(xs, 0, count - 1, mouse.x);
|
||||
// render tool tip (won't be affected by plot clip rect)
|
||||
if (idx != -1) {
|
||||
ImGui::BeginTooltip();
|
||||
char buff[32];
|
||||
ImPlot::FormatTime(xs[idx],buff,32,ImPlotTimeFmt_DayMoYr);
|
||||
ImGui::Text("Day: %s", buff);
|
||||
ImGui::Text("Open: $%.2f", opens[idx]);
|
||||
ImGui::Text("Close: $%.2f", closes[idx]);
|
||||
ImGui::Text("Low: $%.2f", lows[idx]);
|
||||
ImGui::Text("High: $%.2f", highs[idx]);
|
||||
ImGui::EndTooltip();
|
||||
}
|
||||
}
|
||||
|
||||
// end plot item
|
||||
ImPlot::EndItem();
|
||||
}
|
||||
|
|
|
@ -195,6 +195,7 @@ enum ImPlotTimeFmt_ {
|
|||
ImPlotTimeFmt_DayMoYr, // 10/3/91
|
||||
ImPlotTimeFmt_DayMoYrHrMin, // 10/3/91 7:21pm
|
||||
ImPlotTimeFmt_DayMoYrHrMinS, // 10/3/91 7:21:29pm
|
||||
ImPlotTimeFmt_MoYr, // Oct 1991
|
||||
ImPlotTimeFmt_Mo, // Oct
|
||||
ImPlotTimeFmt_Yr // 1991
|
||||
};
|
||||
|
@ -307,11 +308,8 @@ struct ImPlotAxis
|
|||
_min = ImConstrainNan(ImConstrainInf(_min));
|
||||
if (ImHasFlag(Flags, ImPlotAxisFlags_LogScale))
|
||||
_min = ImConstrainLog(_min);
|
||||
if (ImHasFlag(Flags, ImPlotAxisFlags_Time)) {
|
||||
_min = ImConstrainTime(_min);
|
||||
if ((Range.Max - _min) < 0.0001)
|
||||
return false;
|
||||
}
|
||||
if (ImHasFlag(Flags, ImPlotAxisFlags_Time))
|
||||
_min = ImConstrainTime(_min);
|
||||
if (_min >= Range.Max)
|
||||
return false;
|
||||
Range.Min = _min;
|
||||
|
@ -322,17 +320,24 @@ struct ImPlotAxis
|
|||
_max = ImConstrainNan(ImConstrainInf(_max));
|
||||
if (ImHasFlag(Flags, ImPlotAxisFlags_LogScale))
|
||||
_max = ImConstrainLog(_max);
|
||||
if (ImHasFlag(Flags, ImPlotAxisFlags_Time)) {
|
||||
_max = ImConstrainTime(_max);
|
||||
if ((_max - Range.Min) < 0.0001)
|
||||
return false;
|
||||
}
|
||||
if (ImHasFlag(Flags, ImPlotAxisFlags_Time))
|
||||
_max = ImConstrainTime(_max);
|
||||
if (_max <= Range.Min)
|
||||
return false;
|
||||
Range.Max = _max;
|
||||
return true;
|
||||
};
|
||||
|
||||
void SetRange(double _min, double _max) {
|
||||
Range.Min = _min;
|
||||
Range.Max = _max;
|
||||
Constrain();
|
||||
}
|
||||
|
||||
void SetRange(const ImPlotRange& range) {
|
||||
SetRange(range.Min, range.Max);
|
||||
}
|
||||
|
||||
void Constrain() {
|
||||
Range.Min = ImConstrainNan(ImConstrainInf(Range.Min));
|
||||
Range.Max = ImConstrainNan(ImConstrainInf(Range.Max));
|
||||
|
@ -343,8 +348,6 @@ struct ImPlotAxis
|
|||
if (ImHasFlag(Flags, ImPlotAxisFlags_Time)) {
|
||||
Range.Min = ImConstrainTime(Range.Min);
|
||||
Range.Max = ImConstrainTime(Range.Max);
|
||||
if (Range.Size() < 0.0001)
|
||||
Range.Max = Range.Min + 0.0001; // TBD
|
||||
}
|
||||
if (Range.Max <= Range.Min)
|
||||
Range.Max = Range.Min + DBL_EPSILON;
|
||||
|
@ -576,14 +579,33 @@ struct ImPlotAxisScale
|
|||
/// Two part time struct.
|
||||
struct ImPlotTime {
|
||||
time_t S;
|
||||
time_t Us;
|
||||
ImPlotTime(time_t s, time_t us) { S = s; Us = us;}
|
||||
int Us;
|
||||
ImPlotTime(time_t s, int us) {
|
||||
S = s + us / 1000000;
|
||||
Us = us % 1000000;
|
||||
}
|
||||
ImPlotTime(double t) {
|
||||
S = (time_t)t;
|
||||
Us = (int)(t * 1000000 - floor(t) * 1000000);
|
||||
}
|
||||
double ToDouble() const { return (double)S + (double)Us / 1000000.0; }
|
||||
};
|
||||
|
||||
static inline ImPlotTime operator+(const ImPlotTime& lhs, const ImPlotTime& rhs)
|
||||
{ return ImPlotTime(lhs.S + rhs.S, lhs.Us + rhs.Us); }
|
||||
static inline ImPlotTime operator-(const ImPlotTime& lhs, const ImPlotTime& rhs)
|
||||
{ return ImPlotTime(lhs.S - rhs.S, lhs.Us - rhs.Us); }
|
||||
static inline bool operator==(const ImPlotTime& lhs, const ImPlotTime& rhs)
|
||||
{ return lhs.S == rhs.S && lhs.Us == rhs.Us; }
|
||||
static inline bool operator<(const ImPlotTime& lhs, const ImPlotTime& rhs)
|
||||
{ return lhs.S == rhs.S ? lhs.Us < rhs.Us : lhs.S < rhs.S; }
|
||||
static inline bool operator>(const ImPlotTime& lhs, const ImPlotTime& rhs)
|
||||
{ return rhs < lhs; }
|
||||
static inline bool operator<=(const ImPlotTime& lhs, const ImPlotTime& rhs)
|
||||
{ return lhs < rhs || lhs == rhs; }
|
||||
static inline bool operator>=(const ImPlotTime& lhs, const ImPlotTime& rhs)
|
||||
{ return lhs > rhs || lhs == rhs; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Internal API
|
||||
// No guarantee of forward compatibility here!
|
||||
|
@ -653,7 +675,8 @@ inline bool FitThisFrame() { return GImPlot->FitThisFrame; }
|
|||
void FitPoint(const ImPlotPoint& p);
|
||||
|
||||
// Returns true if two ranges overlap
|
||||
inline bool RangesOverlap(const ImPlotRange& r1, const ImPlotRange& r2) { return r1.Min <= r2.Max && r2.Min <= r1.Max; }
|
||||
inline bool RangesOverlap(const ImPlotRange& r1, const ImPlotRange& r2)
|
||||
{ return r1.Min <= r2.Max && r2.Min <= r1.Max; }
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Legend Utils
|
||||
|
@ -771,23 +794,23 @@ inline int GetDaysInMonth(int year, int month) {
|
|||
}
|
||||
|
||||
// Adds time to a timestamp. #count must be positive!
|
||||
double AddTime(double t, ImPlotTimeUnit unit, int count);
|
||||
ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count);
|
||||
// Rounds a timestamp down to nearest.
|
||||
double FloorTime(double t, ImPlotTimeUnit unit);
|
||||
ImPlotTime FloorTime(const ImPlotTime& t, ImPlotTimeUnit unit);
|
||||
// Rounds a timestamp up to the nearest unit.
|
||||
double CeilTime(double t, ImPlotTimeUnit unit);
|
||||
ImPlotTime CeilTime(const ImPlotTime& t, ImPlotTimeUnit unit);
|
||||
// Rounds a timestamp up or down to the nearest unit.
|
||||
double RoundTime(double t, ImPlotTimeUnit unit);
|
||||
ImPlotTime RoundTime(const ImPlotTime& t, ImPlotTimeUnit unit);
|
||||
|
||||
// Get year from timestamp
|
||||
int GetYear(double t);
|
||||
int GetYear(const ImPlotTime& t);
|
||||
// Make a timestamp starting at the first day of a year
|
||||
double MakeYear(int year);
|
||||
ImPlotTime MakeYear(int year);
|
||||
|
||||
// Formates a timestamp t into a buffer according to fmt.
|
||||
int FormatTime(double t, char* buffer, int size, ImPlotTimeFmt fmt);
|
||||
int FormatTime(const ImPlotTime& t, char* buffer, int size, ImPlotTimeFmt fmt);
|
||||
// Prints a timestamp to console
|
||||
void PrintTime(double t, ImPlotTimeFmt fmt);
|
||||
void PrintTime(const ImPlotTime& t, ImPlotTimeFmt fmt);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Internal / Experimental Plotters
|
||||
|
|
Loading…
Reference in New Issue
Block a user