mirror of
https://github.com/gwm17/implot.git
synced 2024-11-22 18:28:53 -05:00
fix up time format demo
This commit is contained in:
parent
d23bd30a44
commit
901f0558b1
62
implot.cpp
62
implot.cpp
|
@ -107,7 +107,6 @@ ImPlotStyle::ImPlotStyle() {
|
|||
ErrorBarWeight = 1.5f;
|
||||
DigitalBitHeight = 8;
|
||||
DigitalBitGap = 4;
|
||||
AntiAliasedLines = false;
|
||||
|
||||
PlotBorderSize = 1;
|
||||
MinorAlpha = 0.25f;
|
||||
|
@ -124,6 +123,9 @@ ImPlotStyle::ImPlotStyle() {
|
|||
PlotMinSize = ImVec2(300,225);
|
||||
|
||||
ImPlot::StyleColorsAuto(this);
|
||||
|
||||
AntiAliasedLines = false;
|
||||
UseLocalTime = false;
|
||||
}
|
||||
|
||||
namespace ImPlot {
|
||||
|
@ -646,7 +648,7 @@ inline int GetTimeStep(int max_divs, ImPlotTimeUnit unit) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
inline time_t MakeGmTime(const struct tm *ptm) {
|
||||
ImPlotTime MkGmtTime(struct tm *ptm) {
|
||||
time_t secs = 0;
|
||||
int year = ptm->tm_year + 1900;
|
||||
for (int y = 1970; y < year; ++y)
|
||||
|
@ -657,21 +659,52 @@ inline time_t MakeGmTime(const struct tm *ptm) {
|
|||
secs += ptm->tm_hour * 3600;
|
||||
secs += ptm->tm_min * 60;
|
||||
secs += ptm->tm_sec;
|
||||
return secs;
|
||||
return ImPlotTime(secs,0);
|
||||
}
|
||||
|
||||
inline tm* GetGmTime(const time_t* time, tm* tm)
|
||||
tm* GetGmtTime(const ImPlotTime& t, tm* ptm)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (gmtime_s(tm, time) == 0)
|
||||
return tm;
|
||||
if (gmtime_s(ptm, &t.S) == 0)
|
||||
return ptm;
|
||||
else
|
||||
return NULL;
|
||||
#else
|
||||
return gmtime_r(time, tm);
|
||||
return gmtime_r(&t.S, ptm);
|
||||
#endif
|
||||
}
|
||||
|
||||
ImPlotTime MkLocTime(struct tm *ptm) {
|
||||
ImPlotTime t;
|
||||
t.S = mktime(ptm);
|
||||
return t;
|
||||
}
|
||||
|
||||
tm* GetLocTime(const ImPlotTime& t, tm* ptm) {
|
||||
#ifdef _WIN32
|
||||
if (localtime_s(ptm, &t.S) == 0)
|
||||
return ptm;
|
||||
else
|
||||
return NULL;
|
||||
#else
|
||||
return localtime_r(&t.S, ptm);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline ImPlotTime MkTime(struct tm *ptm) {
|
||||
if (GetStyle().UseLocalTime)
|
||||
return MkLocTime(ptm);
|
||||
else
|
||||
return MkGmtTime(ptm);
|
||||
}
|
||||
|
||||
inline tm* GetTime(const ImPlotTime& t, tm* ptm) {
|
||||
if (GetStyle().UseLocalTime)
|
||||
return GetLocTime(t,ptm);
|
||||
else
|
||||
return GetGmtTime(t,ptm);
|
||||
}
|
||||
|
||||
ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count) {
|
||||
tm& Tm = GImPlot->Tm;
|
||||
ImPlotTime t_out = t;
|
||||
|
@ -683,7 +716,7 @@ ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count) {
|
|||
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
|
||||
GetGmTime(&t.S, &Tm);
|
||||
GetTime(t_out, &Tm);
|
||||
t_out.S += 86400 * GetDaysInMonth(Tm.tm_year + 1900, Tm.tm_mon);
|
||||
}
|
||||
break;
|
||||
|
@ -701,8 +734,7 @@ ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count) {
|
|||
}
|
||||
|
||||
ImPlotTime FloorTime(const ImPlotTime& t, ImPlotTimeUnit unit) {
|
||||
GetGmTime(&t.S, &GImPlot->Tm);
|
||||
GImPlot->Tm.tm_isdst = -1;
|
||||
GetTime(t, &GImPlot->Tm);
|
||||
switch (unit) {
|
||||
case ImPlotTimeUnit_S: return ImPlotTime(t.S, 0);
|
||||
case ImPlotTimeUnit_Ms: return ImPlotTime(t.S, (t.Us / 1000) * 1000);
|
||||
|
@ -714,7 +746,7 @@ ImPlotTime FloorTime(const ImPlotTime& t, ImPlotTimeUnit unit) {
|
|||
case ImPlotTimeUnit_Min: GImPlot->Tm.tm_sec = 0; break;
|
||||
default: return t;
|
||||
}
|
||||
return ImPlotTime(MakeGmTime(&GImPlot->Tm),0);
|
||||
return MkTime(&GImPlot->Tm);
|
||||
}
|
||||
|
||||
ImPlotTime CeilTime(const ImPlotTime& t, ImPlotTimeUnit unit) {
|
||||
|
@ -731,7 +763,7 @@ ImPlotTime RoundTime(const ImPlotTime& t, ImPlotTimeUnit unit) {
|
|||
|
||||
int GetYear(const ImPlotTime& t) {
|
||||
tm& Tm = GImPlot->Tm;
|
||||
GetGmTime(&t.S, &Tm);
|
||||
GetTime(t, &Tm);
|
||||
return Tm.tm_year + 1900;
|
||||
}
|
||||
|
||||
|
@ -747,14 +779,12 @@ ImPlotTime MakeYear(int year) {
|
|||
Tm.tm_mon = 0;
|
||||
Tm.tm_year = yr;
|
||||
Tm.tm_sec = 0;
|
||||
Tm.tm_isdst = -1;
|
||||
time_t s = MakeGmTime(&Tm);
|
||||
return ImPlotTime(s);
|
||||
return MkTime(&Tm);
|
||||
}
|
||||
|
||||
int FormatTime(const ImPlotTime& t, char* buffer, int size, ImPlotTimeFmt fmt) {
|
||||
tm& Tm = GImPlot->Tm;
|
||||
GetGmTime(&t.S, &Tm);
|
||||
GetTime(t, &Tm);
|
||||
|
||||
const char* ap = Tm.tm_hour < 12 ? "am" : "pm";
|
||||
const int us = t.Us % 1000;
|
||||
|
|
5
implot.h
5
implot.h
|
@ -217,7 +217,6 @@ struct ImPlotStyle {
|
|||
float DigitalBitHeight; // = 8, digital channels bit height (at y = 1.0f) in pixels
|
||||
float DigitalBitGap; // = 4, digital channels bit padding gap in pixels
|
||||
// plot styling variables
|
||||
bool AntiAliasedLines; // = false, enable global anti-aliasing on plot lines (overrides ImPlotFlags_AntiAliased)
|
||||
float PlotBorderSize; // = 1, line thickness of border around plot area
|
||||
float MinorAlpha; // = 0.25 alpha multiplier applied to minor axis grid lines
|
||||
ImVec2 MajorTickLen; // = 10,10 major tick lengths for X and Y axes
|
||||
|
@ -231,7 +230,11 @@ struct ImPlotStyle {
|
|||
ImVec2 LegendPadding; // = 10,10 legend padding from top-left of plot
|
||||
ImVec2 InfoPadding; // = 10,10 padding between plot edge and interior info text
|
||||
ImVec2 PlotMinSize; // = 300,225 minimum size plot frame can be when shrunk
|
||||
// colors
|
||||
ImVec4 Colors[ImPlotCol_COUNT]; // array of plot specific colors
|
||||
// settings/flags
|
||||
bool AntiAliasedLines; // = false, enable global anti-aliasing on plot lines (overrides ImPlotFlags_AntiAliased)
|
||||
bool UseLocalTime; // = false, axis labels will be formatted for your timezone when ImPlotAxisFlag_Time is enabled
|
||||
ImPlotStyle();
|
||||
};
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define sprintf sprintf_s
|
||||
|
@ -124,6 +125,25 @@ struct RollingBuffer {
|
|||
}
|
||||
};
|
||||
|
||||
// Huge data used by Time Formatting example (~500 MB allocation!)
|
||||
struct HugeTimeData {
|
||||
HugeTimeData(double min) {
|
||||
Ts = new double[Size];
|
||||
Ys = new double[Size];
|
||||
for (int i = 0; i < Size; ++i) {
|
||||
Ts[i] = min + i;
|
||||
Ys[i] = GetY(Ts[i]);
|
||||
}
|
||||
}
|
||||
~HugeTimeData() { delete[] Ts; delete[] Ys; }
|
||||
static double GetY(double t) {
|
||||
return 0.5 + 0.25 * sin(t/86400/12) + 0.005 * sin(t/3600);
|
||||
}
|
||||
double* Ts;
|
||||
double* Ys;
|
||||
static const int Size = 60*60*24*366;
|
||||
};
|
||||
|
||||
void ShowDemoWindow(bool* p_open) {
|
||||
t_float DEMO_TIME = (t_float)ImGui::GetTime();
|
||||
static bool show_imgui_metrics = false;
|
||||
|
@ -591,11 +611,42 @@ void ShowDemoWindow(bool* p_open) {
|
|||
}
|
||||
}
|
||||
if (ImGui::CollapsingHeader("Time Formatted Axes")) {
|
||||
static double min = 1577836800; // 01/01/2020 @ 12:00:00am (UTC)
|
||||
static double max = 1609459200; // 01/01/2021 @ 12:00:00am (UTC)
|
||||
ImPlot::SetNextPlotLimits(min,max,0,1);
|
||||
if (ImPlot::BeginPlot("##Time", "UTC Time", "Y-Axis", ImVec2(-1,0), 0, ImPlotAxisFlags_Time)) {
|
||||
|
||||
static double t_min = 1577836800; // 01/01/2020 @ 12:00:00am (UTC)
|
||||
static double t_max = 1609459200; // 01/01/2021 @ 12:00:00am (UTC)
|
||||
|
||||
ImGui::BulletText("When ImPlotAxisFlags_Time is enabled on the X-Axis, values are interpreted as\n"
|
||||
"UNIX timestamps in seconds and axis labels are formated as date/time.");
|
||||
ImGui::BulletText("By default, labels are in UTC time but can be set to use local time instead.");
|
||||
|
||||
ImGui::Checkbox("Use Local Time",&ImPlot::GetStyle().UseLocalTime);
|
||||
|
||||
static HugeTimeData* data = NULL;
|
||||
if (data == NULL) {
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Generate Huge Data (~500MB!)")) {
|
||||
static HugeTimeData sdata(t_min);
|
||||
data = &sdata;
|
||||
}
|
||||
}
|
||||
|
||||
ImPlot::SetNextPlotLimits(t_min,t_max,0,1);
|
||||
if (ImPlot::BeginPlot("##Time", "Time", "Value", ImVec2(-1,0), 0, ImPlotAxisFlags_Time)) {
|
||||
if (data != NULL) {
|
||||
// downsample our data
|
||||
int downsample = (int)ImPlot::GetPlotLimits().X.Size() / 1000 + 1;
|
||||
int start = (int)(ImPlot::GetPlotLimits().X.Min - t_min);
|
||||
start = start < 0 ? 0 : start > HugeTimeData::Size - 1 ? HugeTimeData::Size - 1 : start;
|
||||
int end = (int)(ImPlot::GetPlotLimits().X.Max - t_min) + 1000;
|
||||
end = end < 0 ? 0 : end > HugeTimeData::Size - 1 ? HugeTimeData::Size - 1 : end;
|
||||
int size = (end - start)/downsample;
|
||||
// plot it
|
||||
ImPlot::PlotLine("Time Series", &data->Ts[start], &data->Ys[start], size, 0, sizeof(double)*downsample);
|
||||
}
|
||||
// plot time now
|
||||
double t_now = (double)time(0);
|
||||
double y_now = HugeTimeData::GetY(t_now);
|
||||
ImPlot::PlotScatter("Now",&t_now,&y_now,1);
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
}
|
||||
|
@ -1133,8 +1184,9 @@ void ShowDemoWindow(bool* p_open) {
|
|||
static ImVec4 bearCol = ImVec4(0.853f, 0.050f, 0.310f, 1.000f);
|
||||
ImGui::SameLine(); ImGui::ColorEdit4("##Bull", &bullCol.x, ImGuiColorEditFlags_NoInputs);
|
||||
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,-1),0,ImPlotAxisFlags_Time)) {
|
||||
if (ImPlot::BeginPlot("Candlestick Chart","Day","USD",ImVec2(-1,0),0,ImPlotAxisFlags_Time)) {
|
||||
MyImPlot::PlotCandlestick("GOOGL",dates, opens, closes, lows, highs, 218, tooltip, 0.25f, bullCol, bearCol);
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
|
|
|
@ -577,7 +577,7 @@ struct ImPlotAxisScale
|
|||
}
|
||||
};
|
||||
|
||||
/// Two part time struct.
|
||||
/// Two part timestamp struct.
|
||||
struct ImPlotTime {
|
||||
time_t S; // second part
|
||||
int Us; // microsecond part
|
||||
|
@ -777,8 +777,7 @@ inline T OffsetAndStride(const T* data, int idx, int count, int offset, int stri
|
|||
// Time Utils
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// NB: These functions only work if there is a current ImPlotContext because the
|
||||
// internal tm struct is owned by the context!
|
||||
|
||||
|
||||
// Returns true if year is leap year (366 days long)
|
||||
inline bool IsLeapYear(int year) {
|
||||
|
@ -793,6 +792,19 @@ inline int GetDaysInMonth(int year, int month) {
|
|||
return days[month] + (int)(month == 1 && IsLeapYear(year));
|
||||
}
|
||||
|
||||
// Make a timestamp from a tm struct expressed as a UTC time (i.e. GMT timezone).
|
||||
ImPlotTime MkGmtTime(struct tm *ptm);
|
||||
// Make a tm struct from a timestamp expressed as a UTC time (i.e. GMT timezone).
|
||||
tm* GetGmtTime(const ImPlotTime& t, tm* ptm);
|
||||
|
||||
// Make a timestamp from a tm struct expressed as a local time.
|
||||
ImPlotTime MkLocTime(struct tm *ptm);
|
||||
// Make a tm struct from a timestamp expressed as a local time.
|
||||
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!
|
||||
|
||||
// Adds time to a timestamp. #count must be positive!
|
||||
ImPlotTime AddTime(const ImPlotTime& t, ImPlotTimeUnit unit, int count);
|
||||
// Rounds a timestamp down to nearest.
|
||||
|
|
Loading…
Reference in New Issue
Block a user