#include "Time_Axis.h" #include "Axis_Format.h" #include #include namespace renderive::detail { namespace { Time_Axis_State time_state_from(const Time_Axis_Properties& properties) { Time_Axis_State state; static_cast(state) = properties; return state; } } // namespace Time_Axis_Control::Time_Axis_Control(Plot_Core& plot, const Time_Axis_Properties& properties) : Axis_State_Strategy(plot, time_state_from(properties)) {} std::size_t Time_Axis_Control::time_point_count() const { return read([](const Time_Axis_State& state) { return state.samples.size(); }); } int Time_Axis_Control::append_time(Time_Of_Day time) { int tick{}; update([&](Time_Axis_State& state) { tick = state.next_tick++; state.samples.emplace_back(tick, time); const auto limit = static_cast(std::max(512, state.visible_count.get() * 4)); while (state.samples.size() > limit) state.samples.pop_front(); }); return tick; } Time_Of_Day Time_Axis_Control::tick_to_time(int tick) const { return read([tick](const Time_Axis_State& state) { const 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::coordinate_range(const Time_Axis_State& state) const noexcept { const int latest = std::max(1, state.next_tick - 1); const int earliest = std::max(0, latest - state.visible_count.get() + 1); return state.newest_at_start ? Range{static_cast(latest), static_cast(earliest)} : Range{static_cast(earliest), static_cast(latest)}; } double Time_Axis_Control::calculate_tick_step(Range range, const Time_Axis_State& state) const { const double available = static_cast(state.pixel_length); const double label_width = std::max(48.0, state.unit_text_font.size * 7.0); const double label_count = std::max(1.0, available / (label_width + state.tick_label_spacing_px.get())); return std::max(1.0, std::ceil(range.size() / label_count)); } std::string Time_Axis_Control::format_tick_label(double tick, const Time_Axis_State& state) const { const int target = static_cast(std::llround(tick)); const auto iterator = std::find_if(state.samples.begin(), state.samples.end(), [target](const auto& value) { return value.first == target; }); return iterator == state.samples.end() ? std::string{} : formatted_axis_time(iterator->second, state.format); } } // namespace renderive::detail