126 lines
4.0 KiB
C++
126 lines
4.0 KiB
C++
#include "Time_Axis.h"
|
|
|
|
#include "Axis_Format.h"
|
|
|
|
#include <algorithm>
|
|
#include <cmath>
|
|
|
|
namespace renderive::detail {
|
|
namespace {
|
|
|
|
Time_Axis_State time_state_from(const Time_Axis_Properties& properties) {
|
|
return {
|
|
std::max(2, properties.visible_count),
|
|
std::max(0, properties.tick_label_spacing_px),
|
|
properties.format,
|
|
properties.newest_at_start,
|
|
0,
|
|
{}
|
|
};
|
|
}
|
|
|
|
} // namespace
|
|
|
|
Time_Axis_Control::Time_Axis_Control(Plot_Core& plot, const Time_Axis_Properties& properties)
|
|
: Abs_Axis(plot, properties), time_(time_state_from(properties)) {}
|
|
|
|
int Time_Axis_Control::visible_time_point_count() const {
|
|
return time_.get<&Time_Axis_State::visible_count>();
|
|
}
|
|
|
|
void Time_Axis_Control::set_visible_time_point_count(int value) {
|
|
time_.set<&Time_Axis_State::visible_count>(std::max(2, value));
|
|
changed();
|
|
}
|
|
|
|
int Time_Axis_Control::tick_label_spacing_px() const {
|
|
return time_.get<&Time_Axis_State::tick_label_spacing_px>();
|
|
}
|
|
|
|
void Time_Axis_Control::set_tick_label_spacing_px(int value) {
|
|
time_.set<&Time_Axis_State::tick_label_spacing_px>(std::max(0, value));
|
|
changed();
|
|
}
|
|
|
|
std::string Time_Axis_Control::time_format() const {
|
|
return time_.get<&Time_Axis_State::format>();
|
|
}
|
|
|
|
void Time_Axis_Control::set_time_format(std::string value) {
|
|
time_.set<&Time_Axis_State::format>(std::move(value));
|
|
changed();
|
|
}
|
|
|
|
Font Time_Axis_Control::font() const { return unit_text_font(); }
|
|
|
|
void Time_Axis_Control::set_font(Font value) { set_unit_text_font(value); }
|
|
|
|
bool Time_Axis_Control::newest_at_axis_start() const {
|
|
return time_.get<&Time_Axis_State::newest_at_start>();
|
|
}
|
|
|
|
void Time_Axis_Control::set_newest_at_axis_start(bool value) {
|
|
time_.set<&Time_Axis_State::newest_at_start>(value);
|
|
changed();
|
|
}
|
|
|
|
std::size_t Time_Axis_Control::time_point_count() const {
|
|
return time_.read([](const Time_Axis_State& state) { return state.samples.size(); });
|
|
}
|
|
|
|
int Time_Axis_Control::append_time(Time_Of_Day time) {
|
|
int tick{};
|
|
time_.update([&](Time_Axis_State& state) {
|
|
tick = state.next_tick++;
|
|
state.samples.emplace_back(tick, time);
|
|
const auto limit = static_cast<std::size_t>(std::max(512, state.visible_count * 4));
|
|
while (state.samples.size() > limit)
|
|
state.samples.pop_front();
|
|
});
|
|
changed();
|
|
return tick;
|
|
}
|
|
|
|
Time_Of_Day Time_Axis_Control::tick_to_time(int tick) const {
|
|
return time_.read([tick](const Time_Axis_State& state) {
|
|
auto iterator = std::find_if(state.samples.begin(), state.samples.end(),
|
|
[tick](const auto& value) { return value.first == tick; });
|
|
return iterator == state.samples.end() ? Time_Of_Day{} : iterator->second;
|
|
});
|
|
}
|
|
|
|
Range Time_Axis_Control::coord_range() const {
|
|
return time_.read([](const Time_Axis_State& state) {
|
|
const int latest = std::max(1, state.next_tick - 1);
|
|
const int earliest = std::max(0, latest - state.visible_count + 1);
|
|
return state.newest_at_start ? Range{static_cast<double>(latest), static_cast<double>(earliest)}
|
|
: Range{static_cast<double>(earliest), static_cast<double>(latest)};
|
|
});
|
|
}
|
|
|
|
double Time_Axis_Control::tick_step(Range range) const {
|
|
const double available = static_cast<double>(pixel_length());
|
|
const double label_width = std::max(48.0, font().size * 7.0);
|
|
const double spacing = static_cast<double>(tick_label_spacing_px());
|
|
const double label_count = std::max(1.0, available / (label_width + spacing));
|
|
return std::max(1.0, std::ceil(range.size() / label_count));
|
|
}
|
|
|
|
std::string Time_Axis_Control::tick_label(double tick) const {
|
|
const Time_Of_Day time = tick_to_time(static_cast<int>(std::llround(tick)));
|
|
if (!time.valid())
|
|
return {};
|
|
return formatted_axis_time(time, time_format());
|
|
}
|
|
|
|
void Time_Axis_Control::publish() {
|
|
Abs_Axis::publish();
|
|
time_.publish();
|
|
}
|
|
|
|
std::uint64_t Time_Axis_Control::state_revision() const {
|
|
return Abs_Axis::state_revision() + time_.state_revision();
|
|
}
|
|
|
|
} // namespace renderive::detail
|