diff --git a/apps/graph/graph/graph_view.cpp b/apps/graph/graph/graph_view.cpp index 2e85e0f9a..739225465 100644 --- a/apps/graph/graph/graph_view.cpp +++ b/apps/graph/graph/graph_view.cpp @@ -8,7 +8,7 @@ using namespace Shared; namespace Graph { GraphView::GraphView(CartesianFunctionStore * functionStore, InteractiveCurveViewRange * graphRange, - CurveViewCursor * cursor, BannerView * bannerView, View * cursorView) : + CurveViewCursor * cursor, BannerView * bannerView, CursorView * cursorView) : FunctionGraphView(graphRange, cursor, bannerView, cursorView), m_functionStore(functionStore), m_tangent(false) diff --git a/apps/graph/graph/graph_view.h b/apps/graph/graph/graph_view.h index 54039b31d..23dea0330 100644 --- a/apps/graph/graph/graph_view.h +++ b/apps/graph/graph/graph_view.h @@ -9,7 +9,7 @@ namespace Graph { class GraphView : public Shared::FunctionGraphView { public: GraphView(CartesianFunctionStore * functionStore, Shared::InteractiveCurveViewRange * graphRange, - Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, View * cursorView); + Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, Shared::CursorView * cursorView); void reload() override; void drawRect(KDContext * ctx, KDRect rect) const override; void drawTangent(bool tangent) { m_tangent = tangent; } diff --git a/apps/regression/graph_controller.cpp b/apps/regression/graph_controller.cpp index da5979d39..0be8e1631 100644 --- a/apps/regression/graph_controller.cpp +++ b/apps/regression/graph_controller.cpp @@ -82,9 +82,9 @@ void GraphController::viewWillAppear() { /* Since *m_selectedDotIndex is altered by initCursorParameters(), * the following must absolutely come at the end. */ if (*m_selectedDotIndex >= 0) { - m_view.setCursorView(static_cast(&m_crossCursorView)); + m_view.setCursorView(static_cast(&m_crossCursorView)); } else { - m_view.setCursorView(static_cast(&m_roundCursorView)); + m_view.setCursorView(static_cast(&m_roundCursorView)); m_roundCursorView.setColor(Palette::DataColor[*m_selectedSeriesIndex]); } } diff --git a/apps/regression/graph_view.cpp b/apps/regression/graph_view.cpp index 158f4c40c..e1d31d590 100644 --- a/apps/regression/graph_view.cpp +++ b/apps/regression/graph_view.cpp @@ -8,7 +8,7 @@ using namespace Shared; namespace Regression { -GraphView::GraphView(Store * store, CurveViewCursor * cursor, BannerView * bannerView, View * cursorView) : +GraphView::GraphView(Store * store, CurveViewCursor * cursor, BannerView * bannerView, Shared::CursorView * cursorView) : CurveView(store, cursor, bannerView, cursorView), m_store(store), m_xLabels{}, diff --git a/apps/regression/graph_view.h b/apps/regression/graph_view.h index aa9be68e4..17269ad1c 100644 --- a/apps/regression/graph_view.h +++ b/apps/regression/graph_view.h @@ -9,7 +9,7 @@ namespace Regression { class GraphView : public Shared::CurveView { public: - GraphView(Store * store, Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, View * cursorView); + GraphView(Store * store, Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, Shared::CursorView * cursorView); void drawRect(KDContext * ctx, KDRect rect) const override; private: char * label(Axis axis, int index) const override; diff --git a/apps/sequence/graph/graph_view.cpp b/apps/sequence/graph/graph_view.cpp index 7d522d956..3ce352dd6 100644 --- a/apps/sequence/graph/graph_view.cpp +++ b/apps/sequence/graph/graph_view.cpp @@ -6,7 +6,7 @@ using namespace Shared; namespace Sequence { GraphView::GraphView(SequenceStore * sequenceStore, InteractiveCurveViewRange * graphRange, - CurveViewCursor * cursor, BannerView * bannerView, View * cursorView) : + CurveViewCursor * cursor, BannerView * bannerView, CursorView * cursorView) : FunctionGraphView(graphRange, cursor, bannerView, cursorView), m_sequenceStore(sequenceStore) { diff --git a/apps/sequence/graph/graph_view.h b/apps/sequence/graph/graph_view.h index 6d86fcb07..62550ca86 100644 --- a/apps/sequence/graph/graph_view.h +++ b/apps/sequence/graph/graph_view.h @@ -9,7 +9,7 @@ namespace Sequence { class GraphView : public Shared::FunctionGraphView { public: GraphView(SequenceStore * sequenceStore, Shared::InteractiveCurveViewRange * graphRange, - Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, View * cursorView); + Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, Shared::CursorView * cursorView); void drawRect(KDContext * ctx, KDRect rect) const override; private: SequenceStore * m_sequenceStore; diff --git a/apps/shared/Makefile b/apps/shared/Makefile index 6497254aa..ca523ec05 100644 --- a/apps/shared/Makefile +++ b/apps/shared/Makefile @@ -19,7 +19,6 @@ app_shared_src = $(addprefix apps/shared/,\ buffer_function_title_cell.cpp \ buffer_text_view_with_text_field.cpp \ button_with_separator.cpp \ - cursor_view.cpp \ curve_view.cpp \ curve_view_cursor.cpp \ editable_cell_table_view_controller.cpp \ diff --git a/apps/shared/cursor_view.cpp b/apps/shared/cursor_view.cpp deleted file mode 100644 index 792606be7..000000000 --- a/apps/shared/cursor_view.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "cursor_view.h" - -namespace Shared { - -void CursorView::drawRect(KDContext * ctx, KDRect rect) const { - KDCoordinate width = bounds().width(); - KDCoordinate height = bounds().height(); - ctx->fillRect(KDRect((width-1)/2, 0, 1, height), KDColorBlack); - ctx->fillRect(KDRect(0, (height-1)/2, width, 1), KDColorBlack); -} - -KDSize CursorView::minimalSizeForOptimalDisplay() const { - return KDSize(k_size, k_size); -} - -} diff --git a/apps/shared/cursor_view.h b/apps/shared/cursor_view.h index ab19976a3..600ae8ca1 100644 --- a/apps/shared/cursor_view.h +++ b/apps/shared/cursor_view.h @@ -5,12 +5,9 @@ namespace Shared { -class CursorView : public TransparentView { +class CursorView : public View { public: - void drawRect(KDContext * ctx, KDRect rect) const override; - KDSize minimalSizeForOptimalDisplay() const override; -private: - constexpr static KDCoordinate k_size = 19; + virtual void setCursorFrame(KDRect frame) { View::setFrame(frame); } }; } diff --git a/apps/shared/curve_view.cpp b/apps/shared/curve_view.cpp index d92cd4a2f..54565a58f 100644 --- a/apps/shared/curve_view.cpp +++ b/apps/shared/curve_view.cpp @@ -16,7 +16,7 @@ static inline float minFloat(float x, float y) { return x < y ? x : y; } static inline float maxFloat(float x, float y) { return x > y ? x : y; } CurveView::CurveView(CurveViewRange * curveViewRange, CurveViewCursor * curveViewCursor, BannerView * bannerView, - View * cursorView, View * okView, bool displayBanner) : + CursorView * cursorView, View * okView, bool displayBanner) : View(), m_bannerView(bannerView), m_curveViewCursor(curveViewCursor), @@ -68,7 +68,7 @@ void CurveView::setCurveViewRange(CurveViewRange * curveViewRange) { * might be identical to the previous one and in that case layoutSubviews will * do nothing). */ -void CurveView::setCursorView(View * cursorView) { +void CurveView::setCursorView(CursorView * cursorView) { markRectAsDirty(cursorFrame()); m_cursorView = cursorView; markRectAsDirty(cursorFrame()); @@ -709,7 +709,7 @@ void CurveView::stampAtLocation(KDContext * ctx, KDRect rect, float pxf, float p void CurveView::layoutSubviews() { if (m_curveViewCursor != nullptr && m_cursorView != nullptr) { - m_cursorView->setFrame(cursorFrame()); + m_cursorView->setCursorFrame(cursorFrame()); } if (m_bannerView != nullptr) { m_bannerView->setFrame(bannerFrame()); diff --git a/apps/shared/curve_view.h b/apps/shared/curve_view.h index 00ca88388..71a4a2b74 100644 --- a/apps/shared/curve_view.h +++ b/apps/shared/curve_view.h @@ -4,6 +4,7 @@ #include "banner_view.h" #include "curve_view_range.h" #include "curve_view_cursor.h" +#include "cursor_view.h" #include #include #include @@ -24,15 +25,15 @@ public: CurveView(CurveViewRange * curveViewRange = nullptr, CurveViewCursor * curveViewCursor = nullptr, BannerView * bannerView = nullptr, - View * cursorView = nullptr, + CursorView * cursorView = nullptr, View * okView = nullptr, bool displayBanner = true); virtual void reload(); // When the main view is selected, the banner view is visible bool isMainViewSelected() const; void selectMainView(bool mainViewSelected); - View * cursorView() { return m_cursorView; } - void setCursorView(View * cursorView); + CursorView * cursorView() { return m_cursorView; } + void setCursorView(Shared::CursorView * cursorView); View * bannerView() { return m_bannerView; } void setBannerView(View * bannerView); void setOkView(View * okView); @@ -104,7 +105,7 @@ private: float labelValueAtIndex(Axis axis, int i) const; bool bannerIsVisible() const; CurveViewRange * m_curveViewRange; - View * m_cursorView; + CursorView * m_cursorView; View * m_okView; bool m_forceOkDisplay; bool m_mainViewSelected; diff --git a/apps/shared/function_graph_view.cpp b/apps/shared/function_graph_view.cpp index db677c316..ee8cd73fc 100644 --- a/apps/shared/function_graph_view.cpp +++ b/apps/shared/function_graph_view.cpp @@ -7,7 +7,7 @@ using namespace Poincare; namespace Shared { FunctionGraphView::FunctionGraphView(InteractiveCurveViewRange * graphRange, - CurveViewCursor * cursor, BannerView * bannerView, View * cursorView) : + CurveViewCursor * cursor, BannerView * bannerView, CursorView * cursorView) : CurveView(graphRange, cursor, bannerView, cursorView), m_selectedRecord(), m_highlightedStart(NAN), diff --git a/apps/shared/function_graph_view.h b/apps/shared/function_graph_view.h index 1a8275f8c..0ec2f11cf 100644 --- a/apps/shared/function_graph_view.h +++ b/apps/shared/function_graph_view.h @@ -12,7 +12,7 @@ namespace Shared { class FunctionGraphView : public CurveView { public: FunctionGraphView(InteractiveCurveViewRange * graphRange, CurveViewCursor * cursor, - BannerView * bannerView, View * cursorView); + BannerView * bannerView, CursorView * cursorView); void drawRect(KDContext * ctx, KDRect rect) const override; void setContext(Poincare::Context * context); Poincare::Context * context() const; diff --git a/apps/shared/round_cursor_view.cpp b/apps/shared/round_cursor_view.cpp index baee1829e..a35bd7f08 100644 --- a/apps/shared/round_cursor_view.cpp +++ b/apps/shared/round_cursor_view.cpp @@ -2,11 +2,6 @@ namespace Shared { -RoundCursorView::RoundCursorView(KDColor color) : - m_color(color) -{ -} - static constexpr KDCoordinate cursorSize = 10; static const uint8_t cursorMask[cursorSize][cursorSize] = { {0xFF, 0xFF, 0xFF, 0xED, 0xB6, 0xB6, 0xED, 0xFF, 0xFF, 0xFF}, @@ -24,7 +19,10 @@ static const uint8_t cursorMask[cursorSize][cursorSize] = { static KDColor s_cursorWorkingBuffer[cursorSize*cursorSize]; void RoundCursorView::drawRect(KDContext * ctx, KDRect rect) const { - ctx->blendRectWithMask(bounds(), m_color, (const uint8_t *)cursorMask, s_cursorWorkingBuffer); + KDRect r = bounds(); + ctx->getPixels(r, m_underneathPixelBuffer); + m_underneathPixelBufferLoaded = true; + ctx->blendRectWithMask(r, m_color, (const uint8_t *)cursorMask, s_cursorWorkingBuffer); } KDSize RoundCursorView::minimalSizeForOptimalDisplay() const { @@ -36,4 +34,36 @@ void RoundCursorView::setColor(KDColor color) { markRectAsDirty(bounds()); } +#define GRAPH_CURSOR_SPEEDUP 1 + +void RoundCursorView::setCursorFrame(KDRect f) { +#if GRAPH_CURSOR_SPEEDUP + /* TODO This is quite dirty (we are out of the dirty tracking and we assume + * the cursor is the upmost view) but it works well. */ + if (m_frame == f) { + return; + } + const KDRect previousRelativeFrame = m_frame; + /* We want to avoid drawing the curve just because the cursor has been + * repositioned, as it is very slow for non cartesian curves.*/ + if (m_underneathPixelBufferLoaded && !previousRelativeFrame.isEmpty()) { + const KDRect previousFrame = absoluteVisibleFrame(); + // Erase the cursor + KDContext * ctx = KDIonContext::sharedContext(); + ctx->setOrigin(previousFrame.origin()); + ctx->setClippingRect(previousFrame); + ctx->fillRectWithPixels(KDRect(0,0,k_cursorSize, k_cursorSize), m_underneathPixelBuffer, s_cursorWorkingBuffer); + // Set the frame + m_frame = f; + // Draw the cursor + KDPoint translation = f.origin().translatedBy(previousRelativeFrame.origin().opposite()); + ctx->setOrigin(previousFrame.origin().translatedBy(translation)); + ctx->setClippingRect(previousFrame.translatedBy(translation)); + drawRect(ctx, f); + return; + } +#endif + CursorView::setCursorFrame(f); +} + } diff --git a/apps/shared/round_cursor_view.h b/apps/shared/round_cursor_view.h index f9df48562..f9119f1bf 100644 --- a/apps/shared/round_cursor_view.h +++ b/apps/shared/round_cursor_view.h @@ -1,18 +1,22 @@ #ifndef SHARED_ROUND_CURSOR_VIEW_H #define SHARED_ROUND_CURSOR_VIEW_H -#include +#include "cursor_view.h" namespace Shared { -class RoundCursorView : public TransparentView { +class RoundCursorView : public CursorView { public: - RoundCursorView(KDColor color = KDColorBlack); + RoundCursorView(KDColor color = KDColorBlack) : m_color(color), m_underneathPixelBufferLoaded(false) {} void drawRect(KDContext * ctx, KDRect rect) const override; KDSize minimalSizeForOptimalDisplay() const override; void setColor(KDColor color); + void setCursorFrame(KDRect frame) override; private: + constexpr static int k_cursorSize = 10; + mutable KDColor m_underneathPixelBuffer[k_cursorSize*k_cursorSize]; KDColor m_color; + mutable bool m_underneathPixelBufferLoaded; }; } diff --git a/apps/shared/vertical_cursor_view.h b/apps/shared/vertical_cursor_view.h index bf21c18c5..2caefdc01 100644 --- a/apps/shared/vertical_cursor_view.h +++ b/apps/shared/vertical_cursor_view.h @@ -2,12 +2,12 @@ #define SHARED_VERTICAL_CURSOR_VIEW_H #include +#include "cursor_view.h" namespace Shared { -class VerticalCursorView : public View { +class VerticalCursorView : public CursorView { public: - using View::View; void drawRect(KDContext * ctx, KDRect rect) const override; KDSize minimalSizeForOptimalDisplay() const override; }; diff --git a/escher/include/escher/view.h b/escher/include/escher/view.h index 32bfe796d..442c53b40 100644 --- a/escher/include/escher/view.h +++ b/escher/include/escher/view.h @@ -20,10 +20,15 @@ extern "C" { class Window; +namespace Shared { + class RoundCursorView; +} + class View { // We only want Window to be able to invoke View::redraw friend class Window; friend class TransparentView; + friend class Shared::RoundCursorView; public: View(); virtual ~View() {