mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[apps/graph] Faster cursor scrolling on device
This commit is quite dirty but works well
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -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<View *>(&m_crossCursorView));
|
||||
m_view.setCursorView(static_cast<Shared::CursorView *>(&m_crossCursorView));
|
||||
} else {
|
||||
m_view.setCursorView(static_cast<View *>(&m_roundCursorView));
|
||||
m_view.setCursorView(static_cast<Shared::CursorView *>(&m_roundCursorView));
|
||||
m_roundCursorView.setColor(Palette::DataColor[*m_selectedSeriesIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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{},
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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); }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "banner_view.h"
|
||||
#include "curve_view_range.h"
|
||||
#include "curve_view_cursor.h"
|
||||
#include "cursor_view.h"
|
||||
#include <poincare/preferences.h>
|
||||
#include <poincare/coordinate_2D.h>
|
||||
#include <cmath>
|
||||
@@ -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;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
#ifndef SHARED_ROUND_CURSOR_VIEW_H
|
||||
#define SHARED_ROUND_CURSOR_VIEW_H
|
||||
|
||||
#include <escher.h>
|
||||
#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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
#define SHARED_VERTICAL_CURSOR_VIEW_H
|
||||
|
||||
#include <escher.h>
|
||||
#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;
|
||||
};
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user