diff --git a/src/gui/fluxviewercontrol.cc b/src/gui/fluxviewercontrol.cc index 10895350..878af9a8 100644 --- a/src/gui/fluxviewercontrol.cc +++ b/src/gui/fluxviewercontrol.cc @@ -13,8 +13,9 @@ DECLARE_COLOUR(FOREGROUND, 0, 0, 0); DECLARE_COLOUR(FLUX, 64, 64, 255); DECLARE_COLOUR(RECORD, 255, 255, 255); -const int BORDER = 10; +const int BORDER = 4; const int MINIMUM_TICK_DISTANCE = 10; +const double RENDER_LIMIT = 3000.0; FluxViewerControl::FluxViewerControl(wxWindow* parent, wxWindowID id, @@ -50,15 +51,48 @@ void FluxViewerControl::SetFlux(std::shared_ptr flux) auto size = GetSize(); _nanosecondsPerPixel = (double)_totalDuration / (double)size.GetWidth(); - ResizeScrollbar(); + UpdateScale(); Refresh(); } -void FluxViewerControl::ResizeScrollbar() +void FluxViewerControl::UpdateScale() { auto size = GetSize(); nanoseconds_t thumbSize = size.GetWidth() * _nanosecondsPerPixel; _scrollbar->SetScrollbar(_scrollPosition/1000, thumbSize/1000, _totalDuration/1000, thumbSize/2000); + + int totalPixels = (_totalDuration / _nanosecondsPerPixel) + 1; + if ((totalPixels != _densityMap.size()) && (_nanosecondsPerPixel > RENDER_LIMIT)) + { + _densityMap.resize(totalPixels); + std::fill(_densityMap.begin(), _densityMap.end(), 0.0); + + int i = 0; + for (const auto& trackdata : _flux->trackDatas) + { + FluxmapReader fmr(*trackdata->fluxmap); + while (!fmr.eof()) + { + unsigned ticks; + if (!fmr.findEvent(F_BIT_PULSE, ticks)) + break; + + int fx = fmr.tell().ns() / _nanosecondsPerPixel; + _densityMap.at(i + fx)++; + } + i += trackdata->fluxmap->duration() / _nanosecondsPerPixel; + } + + double max = *std::max_element(_densityMap.begin(), _densityMap.end()); + for (auto& d : _densityMap) + d /= max; + } +} + +static int interpolate(int lo, int hi, float factor) +{ + float range = hi - lo; + return lo + range*factor; } void FluxViewerControl::OnPaint(wxPaintEvent&) @@ -128,6 +162,20 @@ void FluxViewerControl::OnPaint(wxPaintEvent&) tickCount++; } + if (x <= 0) + dc.DrawText( + fmt::format("{}us", (int)(_scrollPosition / 1000LL)), + { BORDER, t3y + ch2/2 } + ); + + if ((x+fw) >= w) + { + wxString text = fmt::format( + "{}us", (int)((_scrollPosition + (w * _nanosecondsPerPixel)) / 1000LL)); + auto size = dc.GetTextExtent(text); + dc.DrawText(text, { w - size.GetWidth() - BORDER, t3y + ch2/2 }); + } + /* Sector blocks. */ for (const auto& sector : trackdata->sectors) @@ -155,26 +203,55 @@ void FluxViewerControl::OnPaint(wxPaintEvent&) /* Flux chart. */ dc.SetPen(FLUX_PEN); - dc.DrawLine({x, t4y}, {x+fw, t4y}); - FluxmapReader fmr(*trackdata->fluxmap); - while (!fmr.eof()) + if (_nanosecondsPerPixel > RENDER_LIMIT) { - int event; - unsigned ticks; - fmr.getNextEvent(event, ticks); + /* Draw using density map. */ - int fx = fmr.tell().ns() / _nanosecondsPerPixel; - - if (event & F_BIT_INDEX) + dc.SetPen(*wxTRANSPARENT_PEN); + for (int fx = 0; fx < _densityMap.size(); fx++) { - dc.SetPen(INDEX_SEPARATOR_PEN); - dc.DrawLine({x+fx, 0}, {x+fx, h}); - dc.SetPen(FLUX_PEN); + if (((x+fx) > 0) && ((x+fx) < w)) + { + float density = _densityMap[fx]; + wxColour colour( + interpolate(BACKGROUND_COLOUR.Red(), FLUX_COLOUR.Red(), density), + interpolate(BACKGROUND_COLOUR.Green(), FLUX_COLOUR.Green(), density), + interpolate(BACKGROUND_COLOUR.Blue(), FLUX_COLOUR.Blue(), density)); + wxBrush brush(colour); + dc.SetBrush(brush); + dc.DrawRectangle({x+fx, t4y - ch2}, {1, ch}); + } } - - if (event & F_BIT_PULSE) - dc.DrawLine({x+fx, t4y - ch2}, {x+fx, t4y + ch2}); } + else + { + /* Draw discrete pulses. */ + + FluxmapReader fmr(*trackdata->fluxmap); + while (!fmr.eof()) + { + int event; + unsigned ticks; + fmr.getNextEvent(event, ticks); + + int fx = fmr.tell().ns() / _nanosecondsPerPixel; + if (((x+fx) > 0) && ((x+fx) < w)) + { + if (event & F_BIT_INDEX) + { + dc.SetPen(INDEX_SEPARATOR_PEN); + dc.DrawLine({x+fx, 0}, {x+fx, h}); + dc.SetPen(FLUX_PEN); + } + + if (event & F_BIT_PULSE) + dc.DrawLine({x+fx, t4y - ch2}, {x+fx, t4y + ch2}); + } + } + } + + dc.SetPen(FLUX_PEN); + dc.DrawLine({x, t4y}, {x+fw, t4y}); } x += w; @@ -193,7 +270,7 @@ void FluxViewerControl::OnMouseWheel(wxMouseEvent& event) _nanosecondsPerPixel *= 1.2; _scrollPosition -= x * _nanosecondsPerPixel; - ResizeScrollbar(); + UpdateScale(); Refresh(); } diff --git a/src/gui/fluxviewercontrol.h b/src/gui/fluxviewercontrol.h index 5f63b1b6..d4d53058 100644 --- a/src/gui/fluxviewercontrol.h +++ b/src/gui/fluxviewercontrol.h @@ -21,7 +21,7 @@ public: void SetFlux(std::shared_ptr flux); private: - void ResizeScrollbar(); + void UpdateScale(); private: void OnPaint(wxPaintEvent&); @@ -34,6 +34,7 @@ private: nanoseconds_t _scrollPosition; nanoseconds_t _totalDuration; double _nanosecondsPerPixel; + std::vector _densityMap; wxDECLARE_EVENT_TABLE(); };