mirror of
https://github.com/gwm17/implot.git
synced 2024-11-22 18:28:53 -05:00
Merge branch 'date-picker'
This commit is contained in:
commit
fbfd41047b
591
implot.cpp
591
implot.cpp
|
@ -659,17 +659,15 @@ inline int GetTimeStep(int max_divs, ImPlotTimeUnit unit) {
|
|||
}
|
||||
|
||||
ImPlotTime MkGmtTime(struct tm *ptm) {
|
||||
time_t secs = 0;
|
||||
int year = ptm->tm_year + 1900;
|
||||
for (int y = 1970; y < year; ++y)
|
||||
secs += (IsLeapYear(y)? 366: 365) * 86400;
|
||||
for (int m = 0; m < ptm->tm_mon; ++m)
|
||||
secs += GetDaysInMonth(year, m) * 86400;
|
||||
secs += (ptm->tm_mday - 1) * 86400;
|
||||
secs += ptm->tm_hour * 3600;
|
||||
secs += ptm->tm_min * 60;
|
||||
secs += ptm->tm_sec;
|
||||
return ImPlotTime(secs,0);
|
||||
ImPlotTime t;
|
||||
#ifdef _WIN32
|
||||
t.S = _mkgmtime(ptm);
|
||||
#else
|
||||
t.S = timegm(ptm);
|
||||
#endif
|
||||
if (t.S < 0)
|
||||
t.S = 0;
|
||||
return t;
|
||||
}
|
||||
|
||||
tm* GetGmtTime(const ImPlotTime& t, tm* ptm)
|
||||
|
@ -687,6 +685,8 @@ tm* GetGmtTime(const ImPlotTime& t, tm* ptm)
|
|||
ImPlotTime MkLocTime(struct tm *ptm) {
|
||||
ImPlotTime t;
|
||||
t.S = mktime(ptm);
|
||||
if (t.S < 0)
|
||||
t.S = 0;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -715,6 +715,35 @@ inline tm* GetTime(const ImPlotTime& t, tm* ptm) {
|
|||
return GetGmtTime(t,ptm);
|
||||
}
|
||||
|
||||
ImPlotTime MakeTime(int year, int month, int day, int hour, int min, int sec, int us) {
|
||||
tm& Tm = GImPlot->Tm;
|
||||
|
||||
int yr = year - 1900;
|
||||
if (yr < 0)
|
||||
yr = 0;
|
||||
|
||||
sec = sec + us / 1000000;
|
||||
us = us % 1000000;
|
||||
|
||||
Tm.tm_sec = sec;
|
||||
Tm.tm_min = min;
|
||||
Tm.tm_hour = hour;
|
||||
Tm.tm_mday = day;
|
||||
Tm.tm_mon = month;
|
||||
Tm.tm_year = yr;
|
||||
|
||||
ImPlotTime t = MkTime(&Tm);
|
||||
|
||||
t.Us = us;
|
||||
return t;
|
||||
}
|
||||
|
||||
int GetYear(const ImPlotTime& t) {
|
||||
tm& Tm = GImPlot->Tm;
|
||||
GetTime(t, &Tm);
|
||||
return Tm.tm_year + 1900;
|
||||
}
|
||||
|
||||
ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count) {
|
||||
tm& Tm = GImPlot->Tm;
|
||||
ImPlotTime t_out = t;
|
||||
|
@ -725,16 +754,20 @@ ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count) {
|
|||
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_Mo: for (int i = 0; i < count; ++i) { // this might have a bug
|
||||
case ImPlotTimeUnit_Mo: for (int i = 0; i < abs(count); ++i) {
|
||||
GetTime(t_out, &Tm);
|
||||
t_out.S += 86400 * GetDaysInMonth(Tm.tm_year + 1900, Tm.tm_mon);
|
||||
if (count > 0)
|
||||
t_out.S += 86400 * GetDaysInMonth(Tm.tm_year + 1900, Tm.tm_mon);
|
||||
else if (count < 0)
|
||||
t_out.S -= 86400 * GetDaysInMonth(Tm.tm_year + 1900 - (Tm.tm_mon == 0 ? 1 : 0), Tm.tm_mon == 0 ? 11 : Tm.tm_mon - 1); // NOT WORKING
|
||||
}
|
||||
break;
|
||||
case ImPlotTimeUnit_Yr: for (int i = 0; i < count; ++i) {
|
||||
if (IsLeapYear(GetYear(t_out)))
|
||||
t_out.S += 366 * 86400;
|
||||
else
|
||||
t_out.S += 365 * 86400;
|
||||
case ImPlotTimeUnit_Yr: for (int i = 0; i < abs(count); ++i) {
|
||||
if (count > 0)
|
||||
t_out.S += 86400 * (365 + (int)IsLeapYear(GetYear(t_out)));
|
||||
else if (count < 0)
|
||||
t_out.S -= 86400 * (365 + (int)IsLeapYear(GetYear(t_out) - 1));
|
||||
// this is incorrect if leap year and we are past Feb 28
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
|
@ -771,25 +804,19 @@ ImPlotTime RoundTime(const ImPlotTime& t, ImPlotTimeUnit unit) {
|
|||
return t.S - t1.S < t2.S - t.S ? t1 : t2;
|
||||
}
|
||||
|
||||
int GetYear(const ImPlotTime& t) {
|
||||
ImPlotTime CombineDateTime(const ImPlotTime& date_part, const ImPlotTime& tod_part) {
|
||||
tm& Tm = GImPlot->Tm;
|
||||
GetTime(t, &Tm);
|
||||
return Tm.tm_year + 1900;
|
||||
}
|
||||
|
||||
ImPlotTime MakeYear(int year) {
|
||||
int yr = year - 1900;
|
||||
if (yr < 0)
|
||||
yr = 0;
|
||||
tm& Tm = GImPlot->Tm;
|
||||
Tm.tm_sec = 0;
|
||||
Tm.tm_min = 0;
|
||||
Tm.tm_hour = 0;
|
||||
Tm.tm_mday = 1;
|
||||
Tm.tm_mon = 0;
|
||||
Tm.tm_year = yr;
|
||||
Tm.tm_sec = 0;
|
||||
return MkTime(&Tm);
|
||||
GetTime(date_part, &GImPlot->Tm);
|
||||
int y = Tm.tm_year;
|
||||
int m = Tm.tm_mon;
|
||||
int d = Tm.tm_mday;
|
||||
GetTime(tod_part, &GImPlot->Tm);
|
||||
Tm.tm_year = y;
|
||||
Tm.tm_mon = m;
|
||||
Tm.tm_mday = d;
|
||||
ImPlotTime t = MkTime(&Tm);
|
||||
t.Us = tod_part.Us;
|
||||
return t;
|
||||
}
|
||||
|
||||
int FormatTime(const ImPlotTime& t, char* buffer, int size, ImPlotTimeFmt fmt) {
|
||||
|
@ -810,23 +837,24 @@ int FormatTime(const ImPlotTime& 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, ".%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);
|
||||
case ImPlotTimeFmt_HrMin: return snprintf(buffer, size, "%d:%02d%s", hr, min, ap);
|
||||
case ImPlotTimeFmt_Hr: return snprintf(buffer, size, "%d%s", hr, ap);
|
||||
case ImPlotTimeFmt_DayMo: return snprintf(buffer, size, "%d/%d", mon, day);
|
||||
case ImPlotTimeFmt_DayMoHr: return snprintf(buffer, size, "%d/%d %d%s", mon, day, hr, ap);
|
||||
case ImPlotTimeFmt_DayMoHrMin: return snprintf(buffer, size, "%d/%d %d:%02d%s", mon, day, hr, min, ap);
|
||||
case ImPlotTimeFmt_DayMoYr: return snprintf(buffer, size, "%d/%d/%02d", mon, day, yr);
|
||||
case ImPlotTimeFmt_DayMoYrHrMin: return snprintf(buffer, size, "%d/%d/%02d %d:%02d%s", mon, day, yr, hr, min, ap);
|
||||
case ImPlotTimeFmt_DayMoYrHrMinS: return snprintf(buffer, size, "%d/%d/%02d %d:%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;
|
||||
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);
|
||||
case ImPlotTimeFmt_HrMin: return snprintf(buffer, size, "%d:%02d%s", hr, min, ap);
|
||||
case ImPlotTimeFmt_Hr: return snprintf(buffer, size, "%d%s", hr, ap);
|
||||
case ImPlotTimeFmt_DayMo: return snprintf(buffer, size, "%d/%d", mon, day);
|
||||
case ImPlotTimeFmt_DayMoHr: return snprintf(buffer, size, "%d/%d %d%s", mon, day, hr, ap);
|
||||
case ImPlotTimeFmt_DayMoHrMin: return snprintf(buffer, size, "%d/%d %d:%02d%s", mon, day, hr, min, ap);
|
||||
case ImPlotTimeFmt_DayMoYr: return snprintf(buffer, size, "%d/%d/%02d", mon, day, yr);
|
||||
case ImPlotTimeFmt_DayMoYrHrMin: return snprintf(buffer, size, "%d/%d/%02d %d:%02d%s", mon, day, yr, hr, min, ap);
|
||||
case ImPlotTimeFmt_DayMoYrHrMinS: return snprintf(buffer, size, "%d/%d/%02d %d:%02d:%02d%s", mon, day, yr, hr, min, sec, ap);
|
||||
case ImPlotTimeFmt_DayMoYrHrMinSUs: return snprintf(buffer, size, "%d/%d/%d %d:%02d:%02d.%03d%03d%s", mon, day, year, hr, min, sec, ms, us, 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -839,23 +867,24 @@ void PrintTime(const ImPlotTime& 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(".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
|
||||
case ImPlotTimeFmt_HrMin: return ImGui::CalcTextSize("88:88pm").x; // 7:21pm
|
||||
case ImPlotTimeFmt_Hr: return ImGui::CalcTextSize("88pm").x; // 7pm
|
||||
case ImPlotTimeFmt_DayMo: return ImGui::CalcTextSize("88/88").x; // 10/3
|
||||
case ImPlotTimeFmt_DayMoHr: return ImGui::CalcTextSize("88/88 88pm").x; // 10/3 7:21pm
|
||||
case ImPlotTimeFmt_DayMoHrMin: return ImGui::CalcTextSize("88/88 88:88pm").x; // 10/3 7:21pm
|
||||
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;
|
||||
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
|
||||
case ImPlotTimeFmt_HrMin: return ImGui::CalcTextSize("88:88pm").x; // 7:21pm
|
||||
case ImPlotTimeFmt_Hr: return ImGui::CalcTextSize("88pm").x; // 7pm
|
||||
case ImPlotTimeFmt_DayMo: return ImGui::CalcTextSize("88/88").x; // 10/3
|
||||
case ImPlotTimeFmt_DayMoHr: return ImGui::CalcTextSize("88/88 88pm").x; // 10/3 7:21pm
|
||||
case ImPlotTimeFmt_DayMoHrMin: return ImGui::CalcTextSize("88/88 88:88pm").x; // 10/3 7:21pm
|
||||
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_DayMoYrHrMinSUs: return ImGui::CalcTextSize("88/88/8888 88:88:88.888888pm").x; // 10/3/1991 7:21:29.123456pm
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1004,7 +1033,7 @@ void AddTicksTime(const ImPlotRange& range, float plot_width, ImPlotTickCollecti
|
|||
const int step = (int)interval <= 0 ? 1 : (int)interval;
|
||||
|
||||
for (int y = graphmin; y < graphmax; y += step) {
|
||||
ImPlotTime t = MakeYear(y);
|
||||
ImPlotTime t = MakeTime(y);
|
||||
if (t >= t_min && t <= t_max) {
|
||||
ImPlotTick tick(t.ToDouble(), true, true);
|
||||
tick.Level = 0;
|
||||
|
@ -1661,63 +1690,115 @@ inline void EndDisabledControls(bool cond) {
|
|||
}
|
||||
}
|
||||
|
||||
inline void ShowAxisContextMenu(ImPlotAxisState& state, bool time_allowed) {
|
||||
void ShowAxisContextMenu(ImPlotAxisState& state, bool time_allowed) {
|
||||
|
||||
ImGui::PushItemWidth(75);
|
||||
bool total_lock = state.HasRange && state.RangeCond == ImGuiCond_Always;
|
||||
bool logscale = ImHasFlag(state.Axis->Flags, ImPlotAxisFlags_LogScale);
|
||||
bool timescale = ImHasFlag(state.Axis->Flags, ImPlotAxisFlags_Time);
|
||||
bool grid = !ImHasFlag(state.Axis->Flags, ImPlotAxisFlags_NoGridLines);
|
||||
bool ticks = !ImHasFlag(state.Axis->Flags, ImPlotAxisFlags_NoTickMarks);
|
||||
bool labels = !ImHasFlag(state.Axis->Flags, ImPlotAxisFlags_NoTickLabels);
|
||||
double drag_speed = (state.Axis->Range.Size() <= DBL_EPSILON) ? DBL_EPSILON * 1.0e+13 : 0.01 * state.Axis->Range.Size(); // recover from almost equal axis limits.
|
||||
ImPlotAxis& axis = *state.Axis;
|
||||
bool total_lock = state.HasRange && state.RangeCond == ImGuiCond_Always;
|
||||
bool logscale = ImHasFlag(axis.Flags, ImPlotAxisFlags_LogScale);
|
||||
bool timescale = ImHasFlag(axis.Flags, ImPlotAxisFlags_Time);
|
||||
bool grid = !ImHasFlag(axis.Flags, ImPlotAxisFlags_NoGridLines);
|
||||
bool ticks = !ImHasFlag(axis.Flags, ImPlotAxisFlags_NoTickMarks);
|
||||
bool labels = !ImHasFlag(axis.Flags, ImPlotAxisFlags_NoTickLabels);
|
||||
double drag_speed = (axis.Range.Size() <= DBL_EPSILON) ? DBL_EPSILON * 1.0e+13 : 0.01 * axis.Range.Size(); // recover from almost equal axis limits.
|
||||
|
||||
BeginDisabledControls(total_lock);
|
||||
if (ImGui::Checkbox("##LockMin", &state.LockMin))
|
||||
ImFlipFlag(state.Axis->Flags, ImPlotAxisFlags_LockMin);
|
||||
EndDisabledControls(total_lock);
|
||||
if (timescale) {
|
||||
ImPlotTime tmin = ImPlotTime::FromDouble(axis.Range.Min);
|
||||
ImPlotTime tmax = ImPlotTime::FromDouble(axis.Range.Max);
|
||||
|
||||
ImGui::SameLine();
|
||||
BeginDisabledControls(state.LockMin);
|
||||
double temp_min = state.Axis->Range.Min;
|
||||
if (DragFloat("Min", &temp_min, (float)drag_speed, -HUGE_VAL, state.Axis->Range.Max - DBL_EPSILON))
|
||||
state.Axis->SetMin(temp_min);
|
||||
EndDisabledControls(state.LockMin);
|
||||
BeginDisabledControls(total_lock);
|
||||
if (ImGui::Checkbox("##LockMin", &state.LockMin))
|
||||
ImFlipFlag(axis.Flags, ImPlotAxisFlags_LockMin);
|
||||
EndDisabledControls(total_lock);
|
||||
ImGui::SameLine();
|
||||
BeginDisabledControls(state.LockMin);
|
||||
if (ImGui::BeginMenu("Min Time")) {
|
||||
if (ShowTimePicker("mintime", &tmin)) {
|
||||
if (tmin >= tmax)
|
||||
tmax = AddTime(tmin, ImPlotTimeUnit_S, 1);
|
||||
axis.SetRange(tmin.ToDouble(),tmax.ToDouble());
|
||||
}
|
||||
ImGui::Separator();
|
||||
if (ShowDatePicker("mindate",&axis.PickerLevel,&axis.PickerTimeMin,&tmin,&tmax)) {
|
||||
tmin = CombineDateTime(axis.PickerTimeMin, tmin);
|
||||
if (tmin >= tmax)
|
||||
tmax = AddTime(tmin, ImPlotTimeUnit_S, 1);
|
||||
axis.SetRange(tmin.ToDouble(), tmax.ToDouble());
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
EndDisabledControls(state.LockMin);
|
||||
|
||||
BeginDisabledControls(total_lock);
|
||||
if (ImGui::Checkbox("##LockMax", &state.LockMax))
|
||||
ImFlipFlag(state.Axis->Flags, ImPlotAxisFlags_LockMax);
|
||||
EndDisabledControls(total_lock);
|
||||
BeginDisabledControls(total_lock);
|
||||
if (ImGui::Checkbox("##LockMax", &state.LockMax))
|
||||
ImFlipFlag(axis.Flags, ImPlotAxisFlags_LockMax);
|
||||
EndDisabledControls(total_lock);
|
||||
ImGui::SameLine();
|
||||
BeginDisabledControls(state.LockMax);
|
||||
if (ImGui::BeginMenu("Max Time")) {
|
||||
if (ShowTimePicker("maxtime", &tmax)) {
|
||||
if (tmax <= tmin)
|
||||
tmin = AddTime(tmax, ImPlotTimeUnit_S, -1);
|
||||
axis.SetRange(tmin.ToDouble(),tmax.ToDouble());
|
||||
}
|
||||
ImGui::Separator();
|
||||
if (ShowDatePicker("maxdate",&axis.PickerLevel,&axis.PickerTimeMax,&tmin,&tmax)) {
|
||||
tmax = CombineDateTime(axis.PickerTimeMax, tmax);
|
||||
if (tmax <= tmin)
|
||||
tmin = AddTime(tmax, ImPlotTimeUnit_S, -1);
|
||||
axis.SetRange(tmin.ToDouble(), tmax.ToDouble());
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
EndDisabledControls(state.LockMax);
|
||||
}
|
||||
else {
|
||||
BeginDisabledControls(total_lock);
|
||||
if (ImGui::Checkbox("##LockMin", &state.LockMin))
|
||||
ImFlipFlag(axis.Flags, ImPlotAxisFlags_LockMin);
|
||||
EndDisabledControls(total_lock);
|
||||
ImGui::SameLine();
|
||||
BeginDisabledControls(state.LockMin);
|
||||
double temp_min = axis.Range.Min;
|
||||
if (DragFloat("Min", &temp_min, (float)drag_speed, -HUGE_VAL, axis.Range.Max - DBL_EPSILON))
|
||||
axis.SetMin(temp_min);
|
||||
EndDisabledControls(state.LockMin);
|
||||
|
||||
ImGui::SameLine();
|
||||
BeginDisabledControls(state.LockMax);
|
||||
double temp_max = state.Axis->Range.Max;
|
||||
if (DragFloat("Max", &temp_max, (float)drag_speed, state.Axis->Range.Min + DBL_EPSILON, HUGE_VAL))
|
||||
state.Axis->SetMax(temp_max);
|
||||
EndDisabledControls(state.LockMax);
|
||||
BeginDisabledControls(total_lock);
|
||||
if (ImGui::Checkbox("##LockMax", &state.LockMax))
|
||||
ImFlipFlag(axis.Flags, ImPlotAxisFlags_LockMax);
|
||||
EndDisabledControls(total_lock);
|
||||
ImGui::SameLine();
|
||||
BeginDisabledControls(state.LockMax);
|
||||
double temp_max = axis.Range.Max;
|
||||
if (DragFloat("Max", &temp_max, (float)drag_speed, axis.Range.Min + DBL_EPSILON, HUGE_VAL))
|
||||
axis.SetMax(temp_max);
|
||||
EndDisabledControls(state.LockMax);
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::Checkbox("Invert", &state.Invert))
|
||||
ImFlipFlag(state.Axis->Flags, ImPlotAxisFlags_Invert);
|
||||
ImFlipFlag(axis.Flags, ImPlotAxisFlags_Invert);
|
||||
BeginDisabledControls(timescale && time_allowed);
|
||||
if (ImGui::Checkbox("Log Scale", &logscale))
|
||||
ImFlipFlag(state.Axis->Flags, ImPlotAxisFlags_LogScale);
|
||||
ImFlipFlag(axis.Flags, ImPlotAxisFlags_LogScale);
|
||||
EndDisabledControls(timescale && time_allowed);
|
||||
|
||||
if (time_allowed) {
|
||||
BeginDisabledControls(logscale);
|
||||
if (ImGui::Checkbox("Time", ×cale))
|
||||
ImFlipFlag(state.Axis->Flags, ImPlotAxisFlags_Time);
|
||||
ImFlipFlag(axis.Flags, ImPlotAxisFlags_Time);
|
||||
EndDisabledControls(logscale);
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
if (ImGui::Checkbox("Grid Lines", &grid))
|
||||
ImFlipFlag(state.Axis->Flags, ImPlotAxisFlags_NoGridLines);
|
||||
ImFlipFlag(axis.Flags, ImPlotAxisFlags_NoGridLines);
|
||||
if (ImGui::Checkbox("Tick Marks", &ticks))
|
||||
ImFlipFlag(state.Axis->Flags, ImPlotAxisFlags_NoTickMarks);
|
||||
ImFlipFlag(axis.Flags, ImPlotAxisFlags_NoTickMarks);
|
||||
if (ImGui::Checkbox("Labels", &labels))
|
||||
ImFlipFlag(state.Axis->Flags, ImPlotAxisFlags_NoTickLabels);
|
||||
ImFlipFlag(axis.Flags, ImPlotAxisFlags_NoTickLabels);
|
||||
|
||||
}
|
||||
|
||||
|
@ -3109,6 +3190,306 @@ void ShowUserGuide() {
|
|||
ImGui::BulletText("Click legend label icons to show/hide plot items.");
|
||||
}
|
||||
|
||||
bool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const ImPlotTime* t1, const ImPlotTime* t2) {
|
||||
|
||||
ImGui::PushID(id);
|
||||
ImGui::BeginGroup();
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0,0,0,0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0,0));
|
||||
|
||||
static const char* names_mo[] = {"January","February","March","April","May","June","July","August","September","October","November","December"};
|
||||
static const char* abrvs_mo[] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
|
||||
static const char* abrvs_wd[] = {"Su","Mo","Tu","We","Th","Fr","Sa"};
|
||||
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
ImVec4 col_txt = style.Colors[ImGuiCol_Text];
|
||||
ImVec4 col_dis = style.Colors[ImGuiCol_TextDisabled];
|
||||
const float ht = ImGui::GetFrameHeight();
|
||||
ImVec2 cell_size(ht*1.25f,ht);
|
||||
char buff[32];
|
||||
bool clk = false;
|
||||
tm& Tm = GImPlot->Tm;
|
||||
|
||||
const int min_yr = 1970;
|
||||
const int max_yr = 2999;
|
||||
|
||||
// t1 parts
|
||||
int t1_mo = 0; int t1_md = 0; int t1_yr = 0;
|
||||
if (t1 != NULL) {
|
||||
GetTime(*t1,&Tm);
|
||||
t1_mo = Tm.tm_mon;
|
||||
t1_md = Tm.tm_mday;
|
||||
t1_yr = Tm.tm_year + 1900;
|
||||
}
|
||||
|
||||
// t2 parts
|
||||
int t2_mo = 0; int t2_md = 0; int t2_yr = 0;
|
||||
if (t2 != NULL) {
|
||||
GetTime(*t2,&Tm);
|
||||
t2_mo = Tm.tm_mon;
|
||||
t2_md = Tm.tm_mday;
|
||||
t2_yr = Tm.tm_year + 1900;
|
||||
}
|
||||
|
||||
// day widget
|
||||
if (*level == 0) {
|
||||
*t = FloorTime(*t, ImPlotTimeUnit_Day);
|
||||
GetTime(*t, &Tm);
|
||||
const int this_year = Tm.tm_year + 1900;
|
||||
const int last_year = this_year - 1;
|
||||
const int next_year = this_year + 1;
|
||||
const int this_mon = Tm.tm_mon;
|
||||
const int last_mon = this_mon == 0 ? 11 : this_mon - 1;
|
||||
const int next_mon = this_mon == 11 ? 0 : this_mon + 1;
|
||||
const int days_this_mo = GetDaysInMonth(this_year, this_mon);
|
||||
const int days_last_mo = GetDaysInMonth(this_mon == 0 ? last_year : this_year, last_mon);
|
||||
ImPlotTime t_first_mo = FloorTime(*t,ImPlotTimeUnit_Mo);
|
||||
GetTime(t_first_mo,&Tm);
|
||||
const int first_wd = Tm.tm_wday;
|
||||
// month year
|
||||
snprintf(buff, 32, "%s %d", names_mo[this_mon], this_year);
|
||||
if (ImGui::Button(buff))
|
||||
*level = 1;
|
||||
ImGui::SameLine(5*cell_size.x);
|
||||
BeginDisabledControls(this_year <= min_yr && this_mon == 0);
|
||||
if (ImGui::ArrowButtonEx("##Up",ImGuiDir_Up,cell_size))
|
||||
*t = AddTime(*t, ImPlotTimeUnit_Mo, -1);
|
||||
EndDisabledControls(this_year <= min_yr && this_mon == 0);
|
||||
ImGui::SameLine();
|
||||
BeginDisabledControls(this_year >= max_yr && this_mon == 11);
|
||||
if (ImGui::ArrowButtonEx("##Down",ImGuiDir_Down,cell_size))
|
||||
*t = AddTime(*t, ImPlotTimeUnit_Mo, 1);
|
||||
EndDisabledControls(this_year >= max_yr && this_mon == 11);
|
||||
// render weekday abbreviations
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
|
||||
for (int i = 0; i < 7; ++i) {
|
||||
ImGui::Button(abrvs_wd[i],cell_size);
|
||||
if (i != 6) { ImGui::SameLine(); }
|
||||
}
|
||||
ImGui::PopItemFlag();
|
||||
// 0 = last mo, 1 = this mo, 2 = next mo
|
||||
int mo = first_wd > 0 ? 0 : 1;
|
||||
int day = mo == 1 ? 1 : days_last_mo - first_wd + 1;
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
for (int j = 0; j < 7; ++j) {
|
||||
if (mo == 0 && day > days_last_mo) {
|
||||
mo = 1; day = 1;
|
||||
}
|
||||
else if (mo == 1 && day > days_this_mo) {
|
||||
mo = 2; day = 1;
|
||||
}
|
||||
const int now_yr = (mo == 0 && this_mon == 0) ? last_year : ((mo == 2 && this_mon == 11) ? next_year : this_year);
|
||||
const int now_mo = mo == 0 ? last_mon : (mo == 1 ? this_mon : next_mon);
|
||||
const int now_md = day;
|
||||
|
||||
const bool off_mo = mo == 0 || mo == 2;
|
||||
const bool t1_or_t2 = (t1 != NULL && t1_mo == now_mo && t1_yr == now_yr && t1_md == now_md) ||
|
||||
(t2 != NULL && t2_mo == now_mo && t2_yr == now_yr && t2_md == now_md);
|
||||
|
||||
if (off_mo)
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, col_dis);
|
||||
if (t1_or_t2) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, col_dis);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, col_txt);
|
||||
}
|
||||
ImGui::PushID(i*7+j);
|
||||
snprintf(buff,32,"%d",day);
|
||||
if (now_yr == min_yr-1 || now_yr == max_yr+1) {
|
||||
ImGui::Dummy(cell_size);
|
||||
}
|
||||
else if (ImGui::Button(buff,cell_size) && !clk) {
|
||||
*t = MakeTime(now_yr, now_mo, now_md);
|
||||
clk = true;
|
||||
}
|
||||
ImGui::PopID();
|
||||
if (t1_or_t2)
|
||||
ImGui::PopStyleColor(2);
|
||||
if (off_mo)
|
||||
ImGui::PopStyleColor();
|
||||
if (j != 6)
|
||||
ImGui::SameLine();
|
||||
day++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// month widget
|
||||
else if (*level == 1) {
|
||||
*t = FloorTime(*t, ImPlotTimeUnit_Mo);
|
||||
GetTime(*t, &Tm);
|
||||
int this_yr = Tm.tm_year + 1900;
|
||||
snprintf(buff, 32, "%d", this_yr);
|
||||
if (ImGui::Button(buff))
|
||||
*level = 2;
|
||||
BeginDisabledControls(this_yr <= min_yr);
|
||||
ImGui::SameLine(5*cell_size.x);
|
||||
if (ImGui::ArrowButtonEx("##Up",ImGuiDir_Up,cell_size))
|
||||
*t = AddTime(*t, ImPlotTimeUnit_Yr, -1);
|
||||
EndDisabledControls(this_yr <= min_yr);
|
||||
ImGui::SameLine();
|
||||
BeginDisabledControls(this_yr >= max_yr);
|
||||
if (ImGui::ArrowButtonEx("##Down",ImGuiDir_Down,cell_size))
|
||||
*t = AddTime(*t, ImPlotTimeUnit_Yr, 1);
|
||||
EndDisabledControls(this_yr >= max_yr);
|
||||
// ImGui::Dummy(cell_size);
|
||||
cell_size.x *= 7.0f/4.0f;
|
||||
cell_size.y *= 7.0f/3.0f;
|
||||
int mo = 0;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
const bool t1_or_t2 = (t1 != NULL && t1_yr == this_yr && t1_mo == mo) ||
|
||||
(t2 != NULL && t2_yr == this_yr && t2_mo == mo);
|
||||
if (t1_or_t2)
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, col_dis);
|
||||
if (ImGui::Button(abrvs_mo[mo],cell_size) && !clk) {
|
||||
*t = MakeTime(this_yr, mo);
|
||||
*level = 0;
|
||||
}
|
||||
if (t1_or_t2)
|
||||
ImGui::PopStyleColor();
|
||||
if (j != 3)
|
||||
ImGui::SameLine();
|
||||
mo++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (*level == 2) {
|
||||
*t = FloorTime(*t, ImPlotTimeUnit_Yr);
|
||||
int this_yr = GetYear(*t);
|
||||
int yr = this_yr - this_yr % 20;
|
||||
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
|
||||
snprintf(buff,32,"%d-%d",yr,yr+19);
|
||||
ImGui::Button(buff);
|
||||
ImGui::PopItemFlag();
|
||||
ImGui::SameLine(5*cell_size.x);
|
||||
BeginDisabledControls(yr <= min_yr);
|
||||
if (ImGui::ArrowButtonEx("##Up",ImGuiDir_Up,cell_size))
|
||||
*t = MakeTime(yr-20);
|
||||
EndDisabledControls(yr <= min_yr);
|
||||
ImGui::SameLine();
|
||||
BeginDisabledControls(yr + 20 >= max_yr);
|
||||
if (ImGui::ArrowButtonEx("##Down",ImGuiDir_Down,cell_size))
|
||||
*t = MakeTime(yr+20);
|
||||
EndDisabledControls(yr+ 20 >= max_yr);
|
||||
// ImGui::Dummy(cell_size);
|
||||
cell_size.x *= 7.0f/4.0f;
|
||||
cell_size.y *= 7.0f/5.0f;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
const bool t1_or_t2 = (t1 != NULL && t1_yr == yr) || (t2 != NULL && t2_yr == yr);
|
||||
if (t1_or_t2)
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, col_dis);
|
||||
snprintf(buff,32,"%d",yr);
|
||||
if (yr<1970||yr>3000) {
|
||||
ImGui::Dummy(cell_size);
|
||||
}
|
||||
else if (ImGui::Button(buff,cell_size)) {
|
||||
*t = MakeTime(yr);
|
||||
*level = 1;
|
||||
}
|
||||
if (t1_or_t2)
|
||||
ImGui::PopStyleColor();
|
||||
if (j != 3)
|
||||
ImGui::SameLine();
|
||||
yr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::EndGroup();
|
||||
ImGui::PopID();
|
||||
return clk;
|
||||
}
|
||||
|
||||
bool ShowTimePicker(const char* id, ImPlotTime* t) {
|
||||
ImGui::PushID(id);
|
||||
tm& Tm = GImPlot->Tm;
|
||||
GetTime(*t,&Tm);
|
||||
|
||||
static const char* nums[] = { "00","01","02","03","04","05","06","07","08","09",
|
||||
"10","11","12","13","14","15","16","17","18","19",
|
||||
"20","21","22","23","24","25","26","27","28","29",
|
||||
"30","31","32","33","34","35","36","37","38","39",
|
||||
"40","41","42","43","44","45","46","47","48","49",
|
||||
"50","51","52","53","54","55","56","57","58","59"};
|
||||
|
||||
static const char* am_pm[] = {"am","pm"};
|
||||
|
||||
int hr = (Tm.tm_hour == 0 || Tm.tm_hour == 12) ? 12 : Tm.tm_hour % 12;
|
||||
int min = Tm.tm_min;
|
||||
int sec = Tm.tm_sec;
|
||||
int ap = Tm.tm_hour < 12 ? 0 : 1;
|
||||
|
||||
bool changed = false;
|
||||
|
||||
ImVec2 spacing = ImGui::GetStyle().ItemSpacing;
|
||||
spacing.x = 0;
|
||||
float width = ImGui::CalcTextSize("888").x;
|
||||
float height = ImGui::GetFrameHeight();
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, spacing);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ScrollbarSize,2.0f);
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBg, ImVec4(0,0,0,0));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0,0,0,0));
|
||||
ImGui::PushStyleColor(ImGuiCol_FrameBgHovered, ImGui::GetStyleColorVec4(ImGuiCol_ButtonHovered));
|
||||
|
||||
ImGui::SetNextItemWidth(width);
|
||||
if (ImGui::BeginCombo("##hr",nums[hr],ImGuiComboFlags_NoArrowButton)) {
|
||||
for (int i = 1; i < 13; ++i) {
|
||||
if (ImGui::Selectable(nums[i],i==hr)) {
|
||||
hr = i;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(":");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(width);
|
||||
if (ImGui::BeginCombo("##min",nums[min],ImGuiComboFlags_NoArrowButton)) {
|
||||
for (int i = 0; i < 60; ++i) {
|
||||
if (ImGui::Selectable(nums[i],i==min)) {
|
||||
min = i;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Text(":");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(width);
|
||||
if (ImGui::BeginCombo("##sec",nums[sec],ImGuiComboFlags_NoArrowButton)) {
|
||||
for (int i = 0; i < 60; ++i) {
|
||||
if (ImGui::Selectable(nums[i],i==sec)) {
|
||||
sec = i;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(am_pm[ap],ImVec2(height,height))) {
|
||||
ap = 1 - ap;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor(3);
|
||||
ImGui::PopStyleVar(2);
|
||||
ImGui::PopID();
|
||||
|
||||
if (changed) {
|
||||
hr = hr % 12 + ap * 12;
|
||||
Tm.tm_hour = hr;
|
||||
Tm.tm_min = min;
|
||||
Tm.tm_sec = sec;
|
||||
*t = MkTime(&Tm);
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
void StyleColorsAuto(ImPlotStyle* dst) {
|
||||
ImPlotStyle* style = dst ? dst : &ImPlot::GetStyle();
|
||||
ImVec4* colors = style->Colors;
|
||||
|
|
|
@ -623,7 +623,7 @@ void ShowDemoWindow(bool* p_open) {
|
|||
}
|
||||
|
||||
ImPlot::SetNextPlotLimits(t_min,t_max,0,1);
|
||||
if (ImPlot::BeginPlot("##Time", "Time", "Value", ImVec2(-1,0), 0, ImPlotAxisFlags_Time)) {
|
||||
if (ImPlot::BeginPlot("##Time", NULL, NULL, ImVec2(-1,0), 0, ImPlotAxisFlags_Time)) {
|
||||
if (data != NULL) {
|
||||
// downsample our data
|
||||
int downsample = (int)ImPlot::GetPlotLimits().X.Size() / 1000 + 1;
|
||||
|
@ -1212,7 +1212,7 @@ void ShowDemoWindow(bool* p_open) {
|
|||
ImGui::SameLine(); ImGui::ColorEdit4("##Bear", &bearCol.x, ImGuiColorEditFlags_NoInputs);
|
||||
ImPlot::GetStyle().UseLocalTime = false;
|
||||
ImPlot::SetNextPlotLimits(1546300800, 1571961600, 1250, 1600);
|
||||
if (ImPlot::BeginPlot("Candlestick Chart","Day","USD",ImVec2(-1,0),0,ImPlotAxisFlags_Time)) {
|
||||
if (ImPlot::BeginPlot("Candlestick Chart","Day","USD",ImVec2(-1,-1),0,ImPlotAxisFlags_Time)) {
|
||||
MyImPlot::PlotCandlestick("GOOGL",dates, opens, closes, lows, highs, 218, tooltip, 0.25f, bullCol, bearCol);
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
|
|
|
@ -183,28 +183,55 @@ enum ImPlotTimeUnit_ {
|
|||
};
|
||||
|
||||
enum ImPlotTimeFmt_ {
|
||||
ImPlotTimeFmt_Us, // .428 552
|
||||
ImPlotTimeFmt_SUs, // :29.428 552
|
||||
ImPlotTimeFmt_SMs, // :29.428
|
||||
ImPlotTimeFmt_S, // :29
|
||||
ImPlotTimeFmt_HrMinS, // 7:21:29pm
|
||||
ImPlotTimeFmt_HrMin, // 7:21pm
|
||||
ImPlotTimeFmt_Hr, // 7pm
|
||||
ImPlotTimeFmt_DayMo, // 10/3
|
||||
ImPlotTimeFmt_DayMoHr, // 10/3 7pm
|
||||
ImPlotTimeFmt_DayMoHrMin, // 10/3 7:21pm
|
||||
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
|
||||
ImPlotTimeFmt_Us, // .428 552
|
||||
ImPlotTimeFmt_SUs, // :29.428 552
|
||||
ImPlotTimeFmt_SMs, // :29.428
|
||||
ImPlotTimeFmt_S, // :29
|
||||
ImPlotTimeFmt_HrMinS, // 7:21:29pm
|
||||
ImPlotTimeFmt_HrMin, // 7:21pm
|
||||
ImPlotTimeFmt_Hr, // 7pm
|
||||
ImPlotTimeFmt_DayMo, // 10/3
|
||||
ImPlotTimeFmt_DayMoHr, // 10/3 7pm
|
||||
ImPlotTimeFmt_DayMoHrMin, // 10/3 7:21pm
|
||||
ImPlotTimeFmt_DayMoYr, // 10/3/91
|
||||
ImPlotTimeFmt_DayMoYrHrMin, // 10/3/91 7:21pm
|
||||
ImPlotTimeFmt_DayMoYrHrMinS, // 10/3/91 7:21:29pm
|
||||
ImPlotTimeFmt_DayMoYrHrMinSUs, // 10/3/1991 7:21:29.123456pm
|
||||
ImPlotTimeFmt_MoYr, // Oct 1991
|
||||
ImPlotTimeFmt_Mo, // Oct
|
||||
ImPlotTimeFmt_Yr // 1991
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] ImPlot Structs
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/// Two part timestamp struct.
|
||||
struct ImPlotTime {
|
||||
time_t S; // second part
|
||||
int Us; // microsecond part
|
||||
ImPlotTime() { S = 0; Us = 0; }
|
||||
ImPlotTime(time_t s, int us = 0) { S = s + us / 1000000; Us = us % 1000000; }
|
||||
void RollOver() { S = S + Us / 1000000; Us = Us % 1000000; }
|
||||
double ToDouble() const { return (double)S + (double)Us / 1000000.0; }
|
||||
static ImPlotTime FromDouble(double t) { return ImPlotTime((time_t)t, (int)(t * 1000000 - floor(t) * 1000000)); }
|
||||
};
|
||||
|
||||
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; }
|
||||
|
||||
// Storage for colormap modifiers
|
||||
struct ImPlotColormapMod {
|
||||
ImPlotColormapMod(const ImVec4* colormap, int colormap_size) {
|
||||
|
@ -297,6 +324,8 @@ struct ImPlotAxis
|
|||
bool HoveredTot;
|
||||
double* LinkedMin;
|
||||
double* LinkedMax;
|
||||
ImPlotTime PickerTimeMin, PickerTimeMax;
|
||||
int PickerLevel;
|
||||
|
||||
ImPlotAxis() {
|
||||
Flags = PreviousFlags = ImPlotAxisFlags_None;
|
||||
|
@ -306,6 +335,7 @@ struct ImPlotAxis
|
|||
HoveredExt = false;
|
||||
HoveredTot = false;
|
||||
LinkedMin = LinkedMax = NULL;
|
||||
PickerLevel = 0;
|
||||
}
|
||||
|
||||
bool SetMin(double _min) {
|
||||
|
@ -317,6 +347,7 @@ struct ImPlotAxis
|
|||
if (_min >= Range.Max)
|
||||
return false;
|
||||
Range.Min = _min;
|
||||
PickerTimeMin = ImPlotTime::FromDouble(Range.Min);
|
||||
return true;
|
||||
};
|
||||
|
||||
|
@ -329,6 +360,7 @@ struct ImPlotAxis
|
|||
if (_max <= Range.Min)
|
||||
return false;
|
||||
Range.Max = _max;
|
||||
PickerTimeMax = ImPlotTime::FromDouble(Range.Max);
|
||||
return true;
|
||||
};
|
||||
|
||||
|
@ -336,6 +368,8 @@ struct ImPlotAxis
|
|||
Range.Min = _min;
|
||||
Range.Max = _max;
|
||||
Constrain();
|
||||
PickerTimeMin = ImPlotTime::FromDouble(Range.Min);
|
||||
PickerTimeMax = ImPlotTime::FromDouble(Range.Max);
|
||||
}
|
||||
|
||||
void SetRange(const ImPlotRange& range) {
|
||||
|
@ -585,32 +619,6 @@ struct ImPlotAxisScale
|
|||
}
|
||||
};
|
||||
|
||||
/// Two part timestamp struct.
|
||||
struct ImPlotTime {
|
||||
time_t S; // second part
|
||||
int Us; // microsecond part
|
||||
ImPlotTime() { S = 0; Us = 0; }
|
||||
ImPlotTime(time_t s, int us = 0) { S = s + us / 1000000; Us = us % 1000000; }
|
||||
void RollOver() { S = S + Us / 1000000; Us = Us % 1000000; }
|
||||
double ToDouble() const { return (double)S + (double)Us / 1000000.0; }
|
||||
static ImPlotTime FromDouble(double t) { return ImPlotTime((time_t)t, (int)(t * 1000000 - floor(t) * 1000000)); }
|
||||
};
|
||||
|
||||
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!
|
||||
|
@ -638,6 +646,9 @@ IMPLOT_API ImPlotState* GetCurrentPlot();
|
|||
// Busts the cache for every plot in the current context
|
||||
IMPLOT_API void BustPlotCache();
|
||||
|
||||
// Shows a plot's context menu.
|
||||
IMPLOT_API void ShowPlotContextMenu(ImPlotState& plot);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Item Utils
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -688,6 +699,9 @@ IMPLOT_API void PushLinkedAxis(ImPlotAxis& axis);
|
|||
// Updates axis internal range from points for linked axes.
|
||||
IMPLOT_API void PullLinkedAxis(ImPlotAxis& axis);
|
||||
|
||||
// Shows an axis's context menu.
|
||||
IMPLOT_API void ShowAxisContextMenu(ImPlotAxisState& state, bool time_allowed = false);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Legend Utils
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -792,48 +806,57 @@ inline T OffsetAndStride(const T* data, int idx, int count, int offset, int stri
|
|||
|
||||
// Returns true if year is leap year (366 days long)
|
||||
inline bool IsLeapYear(int year) {
|
||||
if (year % 4 != 0) return false;
|
||||
if (year % 400 == 0) return true;
|
||||
if (year % 100 == 0) return false;
|
||||
return true;
|
||||
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
|
||||
}
|
||||
// Returns the number of days in a month, accounting for Feb. leap years. #month is zero indexed.
|
||||
inline int GetDaysInMonth(int year, int month) {
|
||||
static const int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
return days[month] + (int)(month == 1 && IsLeapYear(year));
|
||||
return days[month] + (int)(month == 1 && IsLeapYear(year));
|
||||
}
|
||||
|
||||
// Make a timestamp from a tm struct expressed as a UTC time (i.e. GMT timezone).
|
||||
// Make a UNIX timestamp from a tm struct expressed in UTC time (i.e. GMT timezone).
|
||||
IMPLOT_API ImPlotTime MkGmtTime(struct tm *ptm);
|
||||
// Make a tm struct from a timestamp expressed as a UTC time (i.e. GMT timezone).
|
||||
// Make a tm struct expressed in UTC time (i.e. GMT timezone) from a UNIX timestamp.
|
||||
IMPLOT_API tm* GetGmtTime(const ImPlotTime& t, tm* ptm);
|
||||
|
||||
// Make a timestamp from a tm struct expressed as a local time.
|
||||
// Make a UNIX timestamp from a tm struct expressed in local time.
|
||||
IMPLOT_API ImPlotTime MkLocTime(struct tm *ptm);
|
||||
// Make a tm struct from a timestamp expressed as a local time.
|
||||
// Make a tm struct expressed in local time from a UNIX timestamp.
|
||||
IMPLOT_API tm* GetLocTime(const ImPlotTime& t, tm* ptm);
|
||||
|
||||
// NB: These functions only work if there is a current ImPlotContext because the
|
||||
// internal tm struct is owned by the context!
|
||||
// NB: The following functions only work if there is a current ImPlotContext because the
|
||||
// internal tm struct is owned by the context! They are aware of ImPlotStyle.UseLocalTime.
|
||||
|
||||
// Adds time to a timestamp. #count must be positive!
|
||||
// Make a timestamp from time components.
|
||||
// year[1970-3000], month[0-11], day[1-31], hour[0-23], min[0-59], sec[0-59], us[0,999999]
|
||||
IMPLOT_API ImPlotTime MakeTime(int year, int month = 0, int day = 1, int hour = 0, int min = 0, int sec = 0, int us = 0);
|
||||
// Get year component from timestamp [1970-3000]
|
||||
IMPLOT_API int GetYear(const ImPlotTime& t);
|
||||
|
||||
// Adds or subtracts time from a timestamp. #count > 0 to add, < 0 to subtract.
|
||||
IMPLOT_API ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count);
|
||||
// Rounds a timestamp down to nearest.
|
||||
// Rounds a timestamp down to nearest unit.
|
||||
IMPLOT_API ImPlotTime FloorTime(const ImPlotTime& t, ImPlotTimeUnit unit);
|
||||
// Rounds a timestamp up to the nearest unit.
|
||||
IMPLOT_API ImPlotTime CeilTime(const ImPlotTime& t, ImPlotTimeUnit unit);
|
||||
// Rounds a timestamp up or down to the nearest unit.
|
||||
IMPLOT_API ImPlotTime RoundTime(const ImPlotTime& t, ImPlotTimeUnit unit);
|
||||
// Combines the date of one timestamp with the time-of-day of another timestamp.
|
||||
IMPLOT_API ImPlotTime CombineDateTime(const ImPlotTime& date_part, const ImPlotTime& time_part);
|
||||
|
||||
// Get year from timestamp
|
||||
IMPLOT_API int GetYear(const ImPlotTime& t);
|
||||
// Make a timestamp starting at the first day of a year
|
||||
IMPLOT_API ImPlotTime MakeYear(int year);
|
||||
|
||||
// Formates a timestamp t into a buffer according to fmt.
|
||||
// Formulates a timestamp t into a buffer according to fmt.
|
||||
IMPLOT_API int FormatTime(const ImPlotTime& t, char* buffer, int size, ImPlotTimeFmt fmt);
|
||||
// Prints a timestamp to console
|
||||
IMPLOT_API void PrintTime(const ImPlotTime& t, ImPlotTimeFmt fmt);
|
||||
IMPLOT_API void PrintTime(const ImPlotTime& t, ImPlotTimeFmt fmt = ImPlotTimeFmt_DayMoYrHrMinSUs);
|
||||
|
||||
// Shows a date picker widget block (year/month/day).
|
||||
// #level = 0 for day, 1 for month, 2 for year. Modified by user interaction.
|
||||
// #t will be set when a day is clicked and the function will return true.
|
||||
// #t1 and #t2 are optional dates to highlight.
|
||||
IMPLOT_API bool ShowDatePicker(const char* id, int* level, ImPlotTime* t, const ImPlotTime* t1 = NULL, const ImPlotTime* t2 = NULL);
|
||||
// Shows a time picker widget block (hour/min/sec).
|
||||
// #t will be set when a new hour, minute, or sec is selected or am/pm is toggled, and the function will return true.
|
||||
IMPLOT_API bool ShowTimePicker(const char* id, ImPlotTime* t);
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] Internal / Experimental Plotters
|
||||
|
|
Loading…
Reference in New Issue
Block a user