Files
Crosspoint/src/activities/reader/DictionaryWordSelectActivity.h
T

87 lines
2.8 KiB
C++

#pragma once
#include <Epub/Page.h>
#include <I18n.h>
#include <memory>
#include <vector>
#include "activities/Activity.h"
#include "util/Dictionary.h"
// Word selection over the current reader page: Left/Right step through words
// in reading order, Up/Down jump rows, Confirm looks the word up and opens
// DictionaryDefinitionActivity, Back returns to the reader. On touch devices a
// touch-down moves the highlight and a tap on a word looks it up directly.
class DictionaryWordSelectActivity final : public Activity {
public:
explicit DictionaryWordSelectActivity(GfxRenderer& renderer, MappedInputManager& mappedInput,
std::unique_ptr<Page> page, int marginLeft, int marginTop)
: Activity("DictionaryWordSelect", renderer, mappedInput),
page(std::move(page)),
marginLeft(marginLeft),
marginTop(marginTop) {}
void onEnter() override;
void loop() override;
void render(RenderLock&&) override;
private:
// Screen box of one selectable word. `text` points into the owned Page's
// TextBlock arena (NUL-terminated), valid for this activity's lifetime.
struct WordBox {
int16_t x;
int16_t y;
int16_t width;
uint16_t row;
const char* text;
EpdFontFamily::Style style;
};
enum class Popup : uint8_t { None, Busy, NotFound, Error };
void extractWords();
int closestInRow(uint16_t row, int centerX) const;
int wordAt(int x, int y) const;
void moveVertical(int direction);
void performLookup();
bool drawHighlightWithSnapshot();
void drawHints() const;
std::unique_ptr<Page> page;
const int marginLeft;
const int marginTop;
int fontId = 0;
int lineHeight = 0;
std::vector<WordBox> words;
int selected = 0;
uint16_t rowCount = 0;
Dictionary dict;
bool dictOpenAttempted = false;
bool dictOpenOk = false;
Popup popup = Popup::None;
StrId popupMsg = StrId::STR_DICT_NOT_FOUND;
unsigned long popupTime = 0;
// Differential highlight repaint: the pixels under the current highlight
// box, so a cursor move restores them and repaints only the two affected
// boxes instead of re-running the full two-pass page render (which also
// reloads every SD-font glyph on the page). snapshotIdx is the word whose
// under-pixels are saved; -1 means the framebuffer no longer holds a clean
// page (popup drawn, sub-activity shown) and the next render must be full.
static constexpr size_t SNAPSHOT_CAPACITY = 4096;
std::unique_ptr<uint8_t[]> snapshot;
int16_t snapshotX = 0;
int16_t snapshotY = 0;
int16_t snapshotW = 0;
int16_t snapshotH = 0;
int snapshotIdx = -1;
// The activity is entered while Confirm is still held (long-press trigger):
// ignore the stale release until a fresh press is seen.
bool confirmPressSeen = false;
};